Beispiel #1
0
 public override void AssembleNew(Cosmos.Assembler.Assembler aAssembler, object aMethodInfo)
 {
     XS.Mov(XSRegisters.EAX, XSRegisters.CPUx86.Registers.CR0);
     XS.And(XSRegisters.EAX, 0x7FFFFFFF);
     XS.Mov(XSRegisters.CR0, XSRegisters.CPUx86.Registers.EAX);
 }
Beispiel #2
0
        public override void Execute(_MethodInfo aMethod, ILOpCode aOpCode)
        {
            var xIsSingleCompare = true;

            switch (aOpCode.OpCode)
            {
            case ILOpCode.Code.Beq:
            case ILOpCode.Code.Bge:
            case ILOpCode.Code.Bgt:
            case ILOpCode.Code.Bge_Un:
            case ILOpCode.Code.Bgt_Un:
            case ILOpCode.Code.Ble:
            case ILOpCode.Code.Ble_Un:
            case ILOpCode.Code.Bne_Un:
            case ILOpCode.Code.Blt:
            case ILOpCode.Code.Blt_Un:
                xIsSingleCompare = false;
                break;
            }

            var xStackContent     = aOpCode.StackPopTypes[0];
            var xStackContentSize = SizeOfType(xStackContent);

            if (xStackContentSize > 8)
            {
                throw new Exception("Cosmos.IL2CPU.x86->IL->Branch.cs->Error: StackSize > 8 not supported");
            }

            CPU.ConditionalTestEnum xTestOp;
            // all conditions are inverted here?
            switch (aOpCode.OpCode)
            {
            case ILOpCode.Code.Beq:
                xTestOp = CPU.ConditionalTestEnum.Zero;
                break;

            case ILOpCode.Code.Bge:
                xTestOp = CPU.ConditionalTestEnum.GreaterThanOrEqualTo;
                break;

            case ILOpCode.Code.Bgt:
                xTestOp = CPU.ConditionalTestEnum.GreaterThan;
                break;

            case ILOpCode.Code.Ble:
                xTestOp = CPU.ConditionalTestEnum.LessThanOrEqualTo;
                break;

            case ILOpCode.Code.Blt:
                xTestOp = CPU.ConditionalTestEnum.LessThan;
                break;

            case ILOpCode.Code.Bne_Un:
                xTestOp = CPU.ConditionalTestEnum.NotEqual;
                break;

            case ILOpCode.Code.Bge_Un:
                xTestOp = CPU.ConditionalTestEnum.AboveOrEqual;
                break;

            case ILOpCode.Code.Bgt_Un:
                xTestOp = CPU.ConditionalTestEnum.Above;
                break;

            case ILOpCode.Code.Ble_Un:
                xTestOp = CPU.ConditionalTestEnum.BelowOrEqual;
                break;

            case ILOpCode.Code.Blt_Un:
                xTestOp = CPU.ConditionalTestEnum.Below;
                break;

            case ILOpCode.Code.Brfalse:
                xTestOp = CPU.ConditionalTestEnum.Zero;
                break;

            case ILOpCode.Code.Brtrue:
                xTestOp = CPU.ConditionalTestEnum.NotZero;
                break;

            default:
                throw new Exception("Cosmos.IL2CPU.x86->IL->Branch.cs->Error: Unknown OpCode for conditional branch.");
            }
            if (!xIsSingleCompare)
            {
                if (xStackContentSize <= 4)
                {
                    //if (xStackContent.IsFloat)
                    //{
                    //    throw new Exception("Cosmos.IL2CPU.x86->IL->Branch.cs->Error: Comparison of floats (System.Single) is not yet supported!");
                    //}
                    //else
                    //{
                    XS.Pop(XSRegisters.EAX);
                    XS.Pop(XSRegisters.EBX);
                    XS.Compare(XSRegisters.EBX, XSRegisters.EAX);
                    new ConditionalJump {
                        Condition = xTestOp, DestinationLabel = AppAssembler.TmpBranchLabel(aMethod, aOpCode)
                    };
                    //}
                }
                else
                {
                    //if (xStackContent.IsFloat)
                    //{
                    //    throw new Exception("Cosmos.IL2CPU.x86->IL->Branch.cs->Error: Comparison of doubles (System.Double) is not yet supported!");
                    //}
                    //else
                    //{
                    var xNoJump = GetLabel(aMethod, aOpCode) + "__NoBranch";

                    // value 2  EBX:EAX
                    XS.Pop(XSRegisters.EAX);
                    XS.Pop(XSRegisters.EBX);
                    // value 1  EDX:ECX
                    XS.Pop(XSRegisters.ECX);
                    XS.Pop(XSRegisters.EDX);
                    switch (xTestOp)
                    {
                    case ConditionalTestEnum.Zero:     // Equal
                    case ConditionalTestEnum.NotEqual: // NotZero
                        XS.Xor(XSRegisters.EAX, XSRegisters.ECX);
                        new ConditionalJump {
                            Condition = xTestOp, DestinationLabel = AppAssembler.TmpBranchLabel(aMethod, aOpCode)
                        };
                        XS.Xor(XSRegisters.EBX, XSRegisters.EDX);
                        new ConditionalJump {
                            Condition = xTestOp, DestinationLabel = AppAssembler.TmpBranchLabel(aMethod, aOpCode)
                        };
                        break;

                    case ConditionalTestEnum.GreaterThanOrEqualTo:
                        XS.Compare(XSRegisters.EDX, XSRegisters.EBX);
                        XS.Jump(ConditionalTestEnum.LessThan, xNoJump);
                        new ConditionalJump {
                            Condition = ConditionalTestEnum.GreaterThan, DestinationLabel = AppAssembler.TmpBranchLabel(aMethod, aOpCode)
                        };
                        XS.Compare(XSRegisters.ECX, XSRegisters.EAX);
                        XS.Jump(ConditionalTestEnum.Below, xNoJump);
                        break;

                    case ConditionalTestEnum.GreaterThan:
                        XS.Compare(XSRegisters.EDX, XSRegisters.EBX);
                        XS.Jump(ConditionalTestEnum.LessThan, xNoJump);
                        new ConditionalJump {
                            Condition = ConditionalTestEnum.GreaterThan, DestinationLabel = AppAssembler.TmpBranchLabel(aMethod, aOpCode)
                        };
                        XS.Compare(XSRegisters.ECX, XSRegisters.EAX);
                        XS.Jump(ConditionalTestEnum.BelowOrEqual, xNoJump);
                        break;

                    case ConditionalTestEnum.LessThanOrEqualTo:
                        XS.Compare(XSRegisters.EDX, XSRegisters.EBX);
                        new ConditionalJump {
                            Condition = ConditionalTestEnum.LessThan, DestinationLabel = AppAssembler.TmpBranchLabel(aMethod, aOpCode)
                        };
                        XS.Jump(ConditionalTestEnum.GreaterThan, xNoJump);
                        XS.Compare(XSRegisters.ECX, XSRegisters.EAX);
                        new ConditionalJump {
                            Condition = ConditionalTestEnum.BelowOrEqual, DestinationLabel = AppAssembler.TmpBranchLabel(aMethod, aOpCode)
                        };
                        break;

                    case ConditionalTestEnum.LessThan:
                        XS.Compare(XSRegisters.EDX, XSRegisters.EBX);
                        new ConditionalJump {
                            Condition = ConditionalTestEnum.LessThan, DestinationLabel = AppAssembler.TmpBranchLabel(aMethod, aOpCode)
                        };
                        XS.Jump(ConditionalTestEnum.GreaterThan, xNoJump);
                        XS.Compare(XSRegisters.ECX, XSRegisters.EAX);
                        new ConditionalJump {
                            Condition = ConditionalTestEnum.Below, DestinationLabel = AppAssembler.TmpBranchLabel(aMethod, aOpCode)
                        };
                        break;

                    // from here all unsigned
                    case ConditionalTestEnum.AboveOrEqual:
                        XS.Compare(XSRegisters.EDX, XSRegisters.EBX);
                        new ConditionalJump {
                            Condition = ConditionalTestEnum.Above, DestinationLabel = AppAssembler.TmpBranchLabel(aMethod, aOpCode)
                        };
                        XS.Compare(XSRegisters.ECX, XSRegisters.EAX);
                        XS.Jump(ConditionalTestEnum.Below, xNoJump);
                        break;

                    case ConditionalTestEnum.Above:
                        XS.Compare(XSRegisters.EDX, XSRegisters.EBX);
                        new ConditionalJump {
                            Condition = ConditionalTestEnum.Above, DestinationLabel = AppAssembler.TmpBranchLabel(aMethod, aOpCode)
                        };
                        XS.Compare(XSRegisters.ECX, XSRegisters.EAX);
                        XS.Jump(ConditionalTestEnum.BelowOrEqual, xNoJump);
                        break;

                    case ConditionalTestEnum.BelowOrEqual:
                        XS.Compare(XSRegisters.EDX, XSRegisters.EBX);
                        new ConditionalJump {
                            Condition = ConditionalTestEnum.Above, DestinationLabel = AppAssembler.TmpBranchLabel(aMethod, aOpCode)
                        };
                        XS.Jump(ConditionalTestEnum.Below, xNoJump);
                        XS.Compare(XSRegisters.ECX, XSRegisters.EAX);
                        new ConditionalJump {
                            Condition = ConditionalTestEnum.Above, DestinationLabel = AppAssembler.TmpBranchLabel(aMethod, aOpCode)
                        };
                        break;

                    case ConditionalTestEnum.Below:
                        XS.Compare(XSRegisters.EDX, XSRegisters.EBX);
                        new ConditionalJump {
                            Condition = ConditionalTestEnum.Above, DestinationLabel = AppAssembler.TmpBranchLabel(aMethod, aOpCode)
                        };
                        XS.Jump(ConditionalTestEnum.Below, xNoJump);
                        XS.Compare(XSRegisters.ECX, XSRegisters.EAX);
                        new ConditionalJump {
                            Condition = ConditionalTestEnum.AboveOrEqual, DestinationLabel = AppAssembler.TmpBranchLabel(aMethod, aOpCode)
                        };
                        break;

                    default:
                        throw new Exception("Unknown OpCode for conditional branch in 64-bit.");
                    }
                    XS.Label(xNoJump);
                    //}
                }
            }
            else
            {
                //if (xStackContent.IsFloat)
                //{
                //    throw new Exception("Cosmos.IL2CPU.x86->IL->Branch.cs->Error: Simple comparison of floating point numbers is not yet supported!");
                //}
                //else
                //{
                // todo: improve code clarity
                if (xStackContentSize <= 4)
                {
                    XS.Pop(XSRegisters.EAX);
                    if (xTestOp == ConditionalTestEnum.Zero)
                    {
                        XS.Compare(XSRegisters.EAX, 0);
                        new ConditionalJump {
                            Condition = ConditionalTestEnum.Equal, DestinationLabel = AppAssembler.TmpBranchLabel(aMethod, aOpCode)
                        };
                    }
                    else if (xTestOp == ConditionalTestEnum.NotZero)
                    {
                        XS.Compare(XSRegisters.EAX, 0);
                        new ConditionalJump {
                            Condition = ConditionalTestEnum.NotEqual, DestinationLabel = AppAssembler.TmpBranchLabel(aMethod, aOpCode)
                        };
                    }
                    else
                    {
                        throw new NotSupportedException("Cosmos.IL2CPU.x86->IL->Branch.cs->Error: Situation not supported yet! (In the Simple Comparison)");
                    }
                }
                else
                {
                    if (TypeIsReferenceType(xStackContent))
                    {
                        XS.Add(XSRegisters.ESP, 4);
                        XS.Pop(XSRegisters.EAX);
                    }
                    else
                    {
                        XS.Pop(XSRegisters.EAX);
                        XS.Pop(XSRegisters.EBX);
                    }

                    switch (xTestOp)
                    {
                    case ConditionalTestEnum.Zero:    // Equal
                    case ConditionalTestEnum.NotZero: // NotEqual
                        if (TypeIsReferenceType(xStackContent))
                        {
                            XS.Xor(XSRegisters.EAX, 0);
                            new ConditionalJump {
                                Condition = xTestOp, DestinationLabel = AppAssembler.TmpBranchLabel(aMethod, aOpCode)
                            };
                        }
                        else
                        {
                            XS.Xor(XSRegisters.EAX, 0);
                            new ConditionalJump {
                                Condition = xTestOp, DestinationLabel = AppAssembler.TmpBranchLabel(aMethod, aOpCode)
                            };
                            XS.Xor(XSRegisters.EBX, 0);
                            new ConditionalJump {
                                Condition = xTestOp, DestinationLabel = AppAssembler.TmpBranchLabel(aMethod, aOpCode)
                            };
                        }
                        break;

                    default:
                        throw new NotImplementedException("Cosmos.IL2CPU.X86.IL.Branch: Simple branch " + aOpCode.OpCode + " not implemented for operand ");
                    }
                }
            }
            //}
        }
Beispiel #3
0
        /* void Copy(Array sourceArray,			ebp + 0x1C
         *			 int sourceIndex,			ebp + 0x18
         *			 Array destinationArray,	ebp + 0x14
         *			 int destinationIndex,		ebp + 0x10
         *			 int length,				ebp + 0xC
         *			 bool reliable);			ebp + 0x8
         */
        public override void AssembleNew(Assembler.Assembler aAssembler, object aMethodInfo)
        {
            new CPUx86.Mov {
                DestinationReg = CPUx86.Registers.EAX, SourceReg = CPUx86.Registers.EBP, SourceIsIndirect = true, SourceDisplacement = SourceArrayDisplacement
            };
            new CPUx86.Mov {
                DestinationReg = CPUx86.Registers.EAX, SourceReg = CPUx86.Registers.EAX, SourceIsIndirect = true
            };                                                                                                                   // dereference memory handle to pointer
            new CPUx86.Push {
                DestinationReg = CPUx86.Registers.EAX
            };
            new CPUx86.Add {
                DestinationReg = CPUx86.Registers.ESP, DestinationIsIndirect = true, SourceValue = 12, Size = 32
            };                                                                                                                   // pointer is at the element size
            new CPUx86.Pop {
                DestinationReg = CPUx86.Registers.EAX
            };
            new CPUx86.Mov {
                DestinationReg = CPUx86.Registers.EAX, SourceReg = CPUx86.Registers.EAX, SourceIsIndirect = true
            };                                                                                                                   // element size
            new CPUx86.Mov {
                DestinationReg = CPUx86.Registers.EBX, SourceReg = CPUx86.Registers.EBP, SourceIsIndirect = true, SourceDisplacement = SourceIndexDisplacement
            };
            new CPUx86.Multiply {
                DestinationReg = CPUx86.Registers.EBX
            };
            new CPUx86.Add {
                DestinationReg = CPUx86.Registers.EAX, SourceValue = 16
            };
            new CPUx86.Mov {
                DestinationReg = CPUx86.Registers.ESI, SourceReg = CPUx86.Registers.EBP, SourceIsIndirect = true, SourceDisplacement = SourceArrayDisplacement
            };
            new CPUx86.Mov {
                DestinationReg = CPUx86.Registers.ESI, SourceReg = CPUx86.Registers.ESI, SourceIsIndirect = true
            };                                                                                                                   // dereference memory handle to pointer
            new CPUx86.Add {
                DestinationReg = CPUx86.Registers.ESI, SourceReg = CPUx86.Registers.EAX
            };                                                                                          // source ptr
            new CPUx86.Mov {
                DestinationReg = CPUx86.Registers.EDX, SourceReg = CPUx86.Registers.EBP, SourceIsIndirect = true, SourceDisplacement = DestinationArrayDisplacement
            };
            new CPUx86.Mov {
                DestinationReg = CPUx86.Registers.EDX, SourceReg = CPUx86.Registers.EDX, SourceIsIndirect = true
            };                                                                                                                   // dereference memory handle to pointer
            new CPUx86.Push {
                DestinationReg = CPUx86.Registers.EDX
            };
            new CPUx86.Add {
                DestinationReg = CPUx86.Registers.ESP, DestinationIsIndirect = true, SourceValue = 12, Size = 32
            };                                                                                                                   // pointer is at element size
            new CPUx86.Pop {
                DestinationReg = CPUx86.Registers.EAX
            };
            new CPUx86.Mov {
                DestinationReg = CPUx86.Registers.EAX, SourceReg = CPUx86.Registers.EAX, SourceIsIndirect = true
            };                                                                                                                   // dereference handle to pointer
            new CPUx86.Mov {
                DestinationReg = CPUx86.Registers.ECX, SourceReg = CPUx86.Registers.EBP, SourceIsIndirect = true, SourceDisplacement = DestinationIndexDisplacement
            };
            new CPUx86.Multiply {
                DestinationReg = CPUx86.Registers.ECX
            };
            new CPUx86.Add {
                DestinationReg = CPUx86.Registers.EAX, SourceValue = 16
            };
            new CPUx86.Mov {
                DestinationReg = CPUx86.Registers.EDI, SourceReg = CPUx86.Registers.EBP, SourceIsIndirect = true, SourceDisplacement = DestinationArrayDisplacement
            };
            new CPUx86.Mov {
                DestinationReg = CPUx86.Registers.EDI, SourceReg = CPUx86.Registers.EDI, SourceIsIndirect = true
            };                                                                                                                   // dereference handle to pointer
            new CPUx86.Add {
                DestinationReg = CPUx86.Registers.EDI, SourceReg = CPUx86.Registers.EAX
            };

            // calculate byte count to copy
            new CPUx86.Mov {
                DestinationReg = CPUx86.Registers.EAX, SourceReg = CPUx86.Registers.EBP, SourceIsIndirect = true, SourceDisplacement = DestinationArrayDisplacement
            };
            new CPUx86.Mov {
                DestinationReg = CPUx86.Registers.EAX, SourceReg = CPUx86.Registers.EAX, SourceIsIndirect = true
            };                                                                                                                   // dereference memory handle to pointer
            new CPUx86.Add {
                DestinationReg = CPUx86.Registers.EAX, SourceValue = 12
            };
            new CPUx86.Mov {
                DestinationReg = CPUx86.Registers.EAX, SourceReg = CPUx86.Registers.EAX, SourceIsIndirect = true
            };
            new CPUx86.Mov {
                DestinationReg = CPUx86.Registers.EDX, SourceReg = CPUx86.Registers.EBP, SourceIsIndirect = true, SourceDisplacement = LengthDisplacement
            };
            new CPUx86.Multiply {
                DestinationReg = CPUx86.Registers.EDX
            };
            XS.Set(XSRegisters.OldToNewRegister(CPUx86.Registers.ECX), XSRegisters.OldToNewRegister(CPUx86.Registers.EAX));
            new CPUx86.Movs {
                Size = 8, Prefixes = CPUx86.InstructionPrefixes.Repeat
            };
        }
Beispiel #4
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);

            if (aNeedsGC)
            {
                DoNullReferenceCheck(aAssembler, debugEnabled, (int)xRoundedSize + 4);
            }
            else
            {
                DoNullReferenceCheck(aAssembler, debugEnabled, (int)xRoundedSize);
            }

            XS.Comment("After Nullref check");

            if (aNeedsGC)
            {
                XS.Set(XSRegisters.ECX, XSRegisters.ESP, sourceDisplacement: (int)xRoundedSize + 4);
            }
            else
            {
                XS.Set(XSRegisters.ECX, XSRegisters.ESP, sourceDisplacement: (int)xRoundedSize);
            }

            if (xActualOffset != 0)
            {
                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!");
            }
            XS.Add(XSRegisters.ESP, 4);
            if (aNeedsGC)
            {
                XS.Add(XSRegisters.ESP, 4);
            }
        }
 public override void AssembleNew(Cosmos.Assembler.Assembler aAssembler, object aMethodInfo)
 {
     XS.EnableInterrupts();
 }
Beispiel #6
0
        /* void Copy(
         *           Array sourceArray,			ebp + 36
         *			 int sourceIndex,			ebp + 28
         *			 Array destinationArray,	ebp + 24
         *			 int destinationIndex,		ebp + 16
         *			 int length,				ebp + 12
         *			 bool reliable);			ebp + 8
         */

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

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

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

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

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

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

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

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

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

            XS.Jump(xArrayCopyEndLabel);

            XS.Label(xArrayCopyReverseLabel);

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

            XS.Label(xArrayCopyReverseLoopLabel);

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

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

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

            XS.Label(xArrayCopyEndLabel);
        }
Beispiel #7
0
 public override void Execute(_MethodInfo aMethod, ILOpCode aOpCode)
 {
     XS.Jump(AppAssembler.TmpBranchLabel(aMethod, aOpCode));
 }
        public override void Execute(_MethodInfo aMethod, ILOpCode aOpCode)
        {
            var       xType   = aMethod.MethodBase.DeclaringType;
            var       xOpCode = (OpField)aOpCode;
            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;
                }
            }
        }
Beispiel #9
0
 public override void AssembleNew(Assembler aAssembler, object aMethodInfo)
 {
     XS.Push(ILOp.GetTypeIDLabel(typeof(string)));
 }
Beispiel #10
0
 public override void Execute(MethodInfo aMethod, ILOpCode aOpCode)
 {
     DoNullReferenceCheck(Assembler, DebugEnabled, 0);
     XS.Pop(XSRegisters.EAX);
     XS.Push(XSRegisters.EAX, isIndirect: true);
 }
Beispiel #11
0
 public override void Execute(_MethodInfo aMethod, ILOpCode aOpCode)
 {
     XS.Push(0);
     XS.Push(0);
 }
 public override void AssembleNew(Cosmos.Assembler.Assembler aAssembler, object aMethodInfo)
 {
     XS.ClearInterruptFlag();
 }
Beispiel #13
0
 public override void AssembleNew(Assembler.Assembler aAssembler, object aMethodInfo)
 {
     XS.Set(XSRegisters.EDX, XSRegisters.EBP, sourceDisplacement: 0x08);
     XS.ReadFromPortDX(XSRegisters.EAX);
     XS.Push(XSRegisters.EAX);
 }
Beispiel #14
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 #15
0
        public override void Execute(MethodInfo aMethod, ILOpCode aOpCode)
        {
            var xStackItem        = aOpCode.StackPopTypes[0];
            var xStackItemSize    = SizeOfType(xStackItem);
            var xStackItemIsFloat = TypeIsFloat(xStackItem);

            if (xStackItemSize > 8)
            {
                throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Clt_Un.cs->Error: StackSizes > 8 not supported");
            }
            string BaseLabel  = GetLabel(aMethod, aOpCode) + ".";
            string LabelTrue  = BaseLabel + "True";
            string LabelFalse = BaseLabel + "False";

            if (xStackItemSize > 4)
            {
                XS.Set(XSRegisters.ESI, 1);
                // esi = 1
                XS.Xor(XSRegisters.EDI, XSRegisters.EDI);
                // edi = 0
                if (xStackItemIsFloat)
                {
                    // value 2
                    XS.FPU.FloatLoad(ESP, destinationIsIndirect: true, size: RegisterSize.Long64);
                    // value 1
                    new FloatLoad {
                        DestinationReg = RegistersEnum.ESP, Size = 64, DestinationDisplacement = 8, DestinationIsIndirect = true
                    };
                    XS.FPU.FloatCompareAndSet(ST1);
                    // if carry is set, ST(0) < ST(i)
                    new ConditionalMove {
                        Condition = ConditionalTestEnum.Below, DestinationReg = RegistersEnum.EDI, SourceReg = RegistersEnum.ESI
                    };
                    // pops fpu stack
                    XS.FPU.FloatStoreAndPop(ST0);
                    XS.FPU.FloatStoreAndPop(ST0);
                    XS.Add(XSRegisters.ESP, 16);
                }
                else
                {
                    XS.Pop(XSRegisters.EAX);
                    XS.Pop(XSRegisters.EDX);
                    //value2: EDX:EAX
                    XS.Pop(XSRegisters.EBX);
                    XS.Pop(XSRegisters.ECX);
                    //value1: ECX:EBX
                    XS.Sub(XSRegisters.EBX, XSRegisters.EAX);
                    XS.SubWithCarry(XSRegisters.ECX, XSRegisters.EDX);
                    //result = value1 - value2
                    new ConditionalMove {
                        Condition = ConditionalTestEnum.Below, DestinationReg = RegistersEnum.EDI, SourceReg = RegistersEnum.ESI
                    };
                }
                XS.Push(XSRegisters.EDI);
            }
            else
            {
                if (xStackItemIsFloat)
                {
                        #warning THIS NEEDS TO BE TESTED!!!
                    XS.Comment("TEST TODO");
                    XS.SSE.MoveSS(XMM0, ESP, sourceIsIndirect: true);
                    XS.Add(XSRegisters.ESP, 4);
                    XS.SSE.MoveSS(XMM1, ESP, sourceIsIndirect: true);
                    new CompareSS {
                        DestinationReg = RegistersEnum.XMM1, SourceReg = RegistersEnum.XMM0, pseudoOpcode = (byte)ComparePseudoOpcodes.LessThan
                    };
                    XS.SSE.MoveSS(XMM1, ESP, sourceIsIndirect: true);
                    XS.And(ESP, 1, destinationIsIndirect: true);
                }
                else
                {
                    XS.Pop(XSRegisters.ECX);
                    XS.Pop(XSRegisters.EAX);
                    XS.Push(XSRegisters.ECX);
                    XS.Compare(EAX, ESP, sourceIsIndirect: true);
                    XS.Jump(ConditionalTestEnum.Below, LabelTrue);
                    XS.Jump(LabelFalse);
                    XS.Label(LabelTrue);
                    XS.Add(XSRegisters.ESP, 4);
                    XS.Push(1);
                    new Jump {
                        DestinationLabel = GetLabel(aMethod, aOpCode.NextPosition)
                    };
                    XS.Label(LabelFalse);
                    XS.Add(XSRegisters.ESP, 4);
                    XS.Push(0);
                }
            }
        }
Beispiel #16
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) ?? new ConstructorInfo[0]).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 #17
0
        public override void Execute(MethodInfo aMethod, ILOpCode aOpCode)
        {
            var xType   = aMethod.MethodBase.DeclaringType;
            var xOpCode = (ILOpCodes.OpField)aOpCode;

            SysReflection.FieldInfo xField = xOpCode.Value;
            // 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);

            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 #18
0
        public override void Execute(MethodInfo aMethod, ILOpCode aOpCode)
        {
            var xStackTop      = aOpCode.StackPopTypes[0];
            var xStackTop2     = aOpCode.StackPopTypes[0];
            var xStackTopSize  = SizeOfType(xStackTop);
            var xStackTop2Size = SizeOfType(xStackTop2);

            if (xStackTopSize != xStackTop2Size)
            {
                throw new Exception("Different size for substract: " + aMethod.MethodBase + "!");
            }

            var xStackTopIsFloat = TypeIsFloat(xStackTop);

            switch (xStackTopSize)
            {
            case 1:
            case 2:
            case 4:
                if (xStackTopIsFloat)
                {
                    XS.SSE.MoveSS(XMM0, ESP, sourceIsIndirect: true);
                    XS.Add(XSRegisters.ESP, 4);
                    XS.SSE.MoveSS(XMM1, ESP, sourceIsIndirect: true);
                    XS.SSE.SubSS(XMM0, XMM1);
                    XS.SSE.MoveSS(ESP, XMM1, destinationIsIndirect: true);
                }
                else
                {
                    XS.Pop(XSRegisters.ECX);
                    XS.Pop(XSRegisters.EAX);
                    XS.Sub(XSRegisters.EAX, XSRegisters.ECX);
                    XS.Push(XSRegisters.EAX);
                }
                break;

            case 8:
                if (xStackTopIsFloat)
                {
                    new FloatLoad
                    {
                        DestinationReg          = RegistersEnum.ESP,
                        Size                    = 64,
                        DestinationIsIndirect   = true,
                        DestinationDisplacement = 8
                    };
                    new FloatSub
                    {
                        DestinationReg        = RegistersEnum.ESP,
                        DestinationIsIndirect = true,
                        Size = 64
                    };
                    XS.Add(ESP, 8);
                    XS.FPU.FloatStoreAndPop(ESP, isIndirect: true, size: RegisterSize.Long64);
                }
                else
                {
                    XS.Pop(XSRegisters.EAX);
                    XS.Pop(XSRegisters.EDX);
                    XS.Sub(ESP, EAX, destinationIsIndirect: true);
                    XS.SubWithCarry(ESP, EDX, destinationDisplacement: 4);
                }
                break;

            default:
                throw new NotImplementedException("not implemented");
            }
        }
Beispiel #19
0
 public override void AssembleNew(Assembler aAssembler, object aMethodInfo)
 {
     XS.Set(XSRegisters.EDX, XSRegisters.EBP, sourceDisplacement: 0x0C);
     XS.Set(XSRegisters.EAX, XSRegisters.EBP, sourceDisplacement: 0x08);
     XS.WriteToPortDX(XSRegisters.EAX);
 }
Beispiel #20
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 #21
0
        public override void Execute(MethodInfo aMethod, ILOpCode aOpCode)
        {
            var xStackItem        = aOpCode.StackPopTypes[0];
            var xStackItemSize    = SizeOfType(xStackItem);
            var xStackItemIsFloat = TypeIsFloat(xStackItem);

            if (xStackItemSize > 8)
            {
                //EmitNotImplementedException( Assembler, GetServiceProvider(), "Cgt: StackSizes>8 not supported", CurInstructionLabel, mMethodInfo, mCurrentOffset, NextInstructionLabel );
                throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Cgt.cs->Error: StackSizes > 8 not supported");
                //return;
            }
            string BaseLabel  = GetLabel(aMethod, aOpCode) + ".";
            string LabelTrue  = BaseLabel + "True";
            string LabelFalse = BaseLabel + "False";
            var    xNextLabel = GetLabel(aMethod, aOpCode.NextPosition);

            if (xStackItemSize > 4)
            {
                XS.Set(XSRegisters.ESI, 1);
                // esi = 1
                XS.Xor(XSRegisters.EDI, XSRegisters.EDI);
                // edi = 0
                if (xStackItemIsFloat)
                {
                    // value 1
                    new FloatLoad {
                        DestinationReg = RegistersEnum.ESP, Size = 64, DestinationDisplacement = 8, DestinationIsIndirect = true
                    };
                    // value 2
                    XS.FPU.FloatLoad(ESP, destinationIsIndirect: true, size: RegisterSize.Long64);
                    XS.FPU.FloatCompareAndSet(ST1);
                    // if carry is set, ST(0) < ST(i)
                    new ConditionalMove {
                        Condition = ConditionalTestEnum.Below, DestinationReg = RegistersEnum.EDI, SourceReg = RegistersEnum.ESI
                    };
                    // pops fpu stack
                    XS.FPU.FloatStoreAndPop(ST0);
                    XS.FPU.FloatStoreAndPop(ST0);
                    XS.Add(XSRegisters.ESP, 16);
                }
                else
                {
                    XS.Pop(XSRegisters.EAX);
                    XS.Pop(XSRegisters.EDX);
                    //value2: EDX:EAX
                    XS.Pop(XSRegisters.EBX);
                    XS.Pop(XSRegisters.ECX);
                    //value1: ECX:EBX
                    XS.Compare(XSRegisters.ECX, XSRegisters.EDX);
                    XS.Jump(ConditionalTestEnum.GreaterThan, LabelTrue);
                    XS.Jump(ConditionalTestEnum.LessThan, LabelFalse);
                    XS.Compare(XSRegisters.EBX, XSRegisters.EAX);
                    XS.Label(LabelTrue);
                    new ConditionalMove {
                        Condition = ConditionalTestEnum.GreaterThan, DestinationReg = RegistersEnum.EDI, SourceReg = RegistersEnum.ESI
                    };
                    XS.Label(LabelFalse);
                }
                XS.Push(XSRegisters.EDI);

                /*
                 * XS.Jump(ConditionalTestEnum.GreaterThan, LabelTrue);
                 * XS.Label(LabelFalse);
                 * XS.Push(0);
                 * XS.Jump(xNextLabel);
                 * XS.Label(LabelTrue );
                 * XS.Push(1);*/
            }
            else
            {
                if (xStackItemIsFloat)
                {
                    XS.SSE.MoveSS(XMM0, ESP, sourceIsIndirect: true);
                    XS.Add(XSRegisters.ESP, 4);
                    XS.SSE.MoveSS(XMM1, ESP, sourceIsIndirect: true);
                    new CompareSS {
                        DestinationReg = RegistersEnum.XMM1, SourceReg = RegistersEnum.XMM0, pseudoOpcode = (byte)ComparePseudoOpcodes.NotLessThanOrEqualTo
                    };
                    XS.SSE2.MoveD(XMM1, EBX);
                    XS.And(XSRegisters.EBX, 1);
                    XS.Set(ESP, EBX, destinationIsIndirect: true);
                }

                else
                {
                    XS.Pop(XSRegisters.EAX);
                    XS.Compare(EAX, ESP, sourceIsIndirect: true);
                    XS.Jump(ConditionalTestEnum.LessThan, LabelTrue);
                    XS.Jump(LabelFalse);
                    XS.Label(LabelTrue);
                    XS.Add(XSRegisters.ESP, 4);
                    XS.Push(1);
                    XS.Jump(xNextLabel);
                    XS.Label(LabelFalse);
                    XS.Add(XSRegisters.ESP, 4);
                    XS.Push(0);
                }
            }
        }
Beispiel #22
0
        public override void Execute(MethodInfo aMethod, ILOpCode aOpCode)
        {
            var xStackItem     = aOpCode.StackPopTypes[0];
            var xStackItemSize = SizeOfType(xStackItem);
            var xSize          = Math.Max(xStackItemSize, SizeOfType(aOpCode.StackPopTypes[1]));

            if (xSize > 4)
            {
                if (TypeIsFloat(xStackItem))
                {
                    new CPUx86.SSE.MoveSS {
                        DestinationReg = CPUx86.Registers.XMM0, SourceReg = CPUx86.Registers.ESP, SourceIsIndirect = true
                    };
                    new CPUx86.Add {
                        DestinationReg = CPUx86.Registers.ESP, SourceValue = 8
                    };
                    new CPUx86.SSE.MoveSS {
                        DestinationReg = CPUx86.Registers.XMM1, SourceReg = CPUx86.Registers.ESP, SourceIsIndirect = true
                    };
                    new CPUx86.SSE.XorPS {
                        DestinationReg = CPUx86.Registers.XMM2, SourceReg = CPUx86.Registers.XMM2
                    };
                    new CPUx86.SSE.DivPS {
                        DestinationReg = CPUx86.Registers.XMM0, SourceReg = CPUx86.Registers.XMM1
                    };
                    new CPUx86.SSE.MoveSS {
                        SourceReg = CPUx86.Registers.XMM2, DestinationReg = CPUx86.Registers.ESP, DestinationIsIndirect = true
                    };
                }
                else
                {
                    string BaseLabel       = GetLabel(aMethod, aOpCode) + ".";
                    string LabelShiftRight = BaseLabel + "ShiftRightLoop";
                    string LabelNoLoop     = BaseLabel + "NoLoop";
                    string LabelEnd        = BaseLabel + "End";

                    // divisor
                    //low
                    new CPUx86.Mov {
                        DestinationReg = CPUx86.Registers.ESI, SourceReg = CPUx86.Registers.ESP, SourceIsIndirect = true
                    };
                    //high
                    new CPUx86.Mov {
                        DestinationReg = CPUx86.Registers.EDI, SourceReg = CPUx86.Registers.ESP, SourceIsIndirect = true, SourceDisplacement = 4
                    };

                    //dividend
                    // low
                    new CPUx86.Mov {
                        DestinationReg = CPUx86.Registers.EAX, SourceReg = CPUx86.Registers.ESP, SourceIsIndirect = true, SourceDisplacement = 8
                    };
                    //high
                    new CPUx86.Mov {
                        DestinationReg = CPUx86.Registers.EDX, SourceReg = CPUx86.Registers.ESP, SourceIsIndirect = true, SourceDisplacement = 12
                    };

                    // pop both 8 byte values
                    new CPUx86.Add {
                        DestinationReg = CPUx86.Registers.ESP, SourceValue = 16
                    };

                    // set flags
                    new CPUx86.Or {
                        DestinationReg = CPUx86.Registers.EDI, SourceReg = CPUx86.Registers.EDI
                    };
                    // if high dword of divisor is already zero, we dont need the loop
                    new CPUx86.ConditionalJump {
                        Condition = CPUx86.ConditionalTestEnum.Zero, DestinationLabel = LabelNoLoop
                    };

                    // set ecx to zero for counting the shift operations
                    new CPUx86.Xor {
                        DestinationReg = CPUx86.Registers.ECX, SourceReg = CPUx86.Registers.ECX
                    };

                    new Label(LabelShiftRight);

                    // shift divisor 1 bit right
                    new CPUx86.ShiftRightDouble {
                        DestinationReg = CPUx86.Registers.ESI, SourceReg = CPUx86.Registers.EDI, ArgumentValue = 1
                    };
                    new CPUx86.ShiftRight {
                        DestinationReg = CPUx86.Registers.EDI, SourceValue = 1
                    };

                    // increment shift counter
                    new CPUx86.INC {
                        DestinationReg = CPUx86.Registers.ECX
                    };

                    // set flags
                    new CPUx86.Or {
                        DestinationReg = CPUx86.Registers.EDI, SourceReg = CPUx86.Registers.EDI
                    };
                    // loop while high dword of divisor till it is zero
                    new CPUx86.ConditionalJump {
                        Condition = CPUx86.ConditionalTestEnum.NotZero, DestinationLabel = LabelShiftRight
                    };

                    // shift the divident now in one step
                    // shift divident CL bits right
                    new CPUx86.ShiftRightDouble {
                        DestinationReg = CPUx86.Registers.EAX, SourceReg = CPUx86.Registers.EDX, ArgumentReg = CPUx86.Registers.CL
                    };
                    new CPUx86.ShiftRight {
                        DestinationReg = CPUx86.Registers.EDX, SourceReg = CPUx86.Registers.CL
                    };

                    // so we shifted both, so we have near the same relation as original values
                    // divide this
                    new CPUx86.Divide {
                        DestinationReg = CPUx86.Registers.ESI
                    };

                    // save remainder to stack
                    new CPUx86.Push {
                        DestinationValue = 0
                    };
                    new CPUx86.Push {
                        DestinationReg = CPUx86.Registers.EDX
                    };

                    //TODO: implement proper derivation correction and overflow detection

                    new CPUx86.Jump {
                        DestinationLabel = LabelEnd
                    };

                    new Label(LabelNoLoop);

                    //save high dividend
                    XS.Set(XSRegisters.OldToNewRegister(CPUx86.Registers.ECX), XSRegisters.OldToNewRegister(CPUx86.Registers.EAX));
                    XS.Set(XSRegisters.OldToNewRegister(CPUx86.Registers.EAX), XSRegisters.OldToNewRegister(CPUx86.Registers.EDX));
                    // zero EDX, so that high part is zero -> reduce overflow case
                    new CPUx86.Xor {
                        DestinationReg = CPUx86.Registers.EDX, SourceReg = CPUx86.Registers.EDX
                    };
                    // divide high part
                    new CPUx86.Divide {
                        DestinationReg = CPUx86.Registers.ESI
                    };
                    XS.Set(XSRegisters.OldToNewRegister(CPUx86.Registers.EAX), XSRegisters.OldToNewRegister(CPUx86.Registers.ECX));
                    // divide low part
                    new CPUx86.Divide {
                        DestinationReg = CPUx86.Registers.ESI
                    };
                    // save remainder result
                    new CPUx86.Push {
                        DestinationValue = 0
                    };
                    new CPUx86.Push {
                        DestinationReg = CPUx86.Registers.EDX
                    };

                    new Label(LabelEnd);
                }
            }
            else
            {
                if (TypeIsFloat(xStackItem))
                {
                    new CPUx86.SSE.MoveSS {
                        DestinationReg = CPUx86.Registers.XMM0, SourceReg = CPUx86.Registers.ESP, SourceIsIndirect = true
                    };
                    new CPUx86.Add {
                        DestinationReg = CPUx86.Registers.ESP, SourceValue = 4
                    };
                    new CPUx86.SSE.MoveSS {
                        DestinationReg = CPUx86.Registers.XMM1, SourceReg = CPUx86.Registers.ESP, SourceIsIndirect = true
                    };
                    new CPUx86.Add {
                        DestinationReg = CPUx86.Registers.ESP, SourceValue = 4
                    };
                    new CPUx86.SSE.XorPS {
                        DestinationReg = CPUx86.Registers.XMM2, SourceReg = CPUx86.Registers.XMM2
                    };
                    new CPUx86.SSE.DivPS {
                        DestinationReg = CPUx86.Registers.XMM0, SourceReg = CPUx86.Registers.XMM1
                    };
                    new CPUx86.Sub {
                        DestinationReg = CPUx86.Registers.ESP, SourceValue = 4
                    };
                    new CPUx86.SSE.MoveSS {
                        SourceReg = CPUx86.Registers.XMM2, DestinationReg = CPUx86.Registers.ESP, DestinationIsIndirect = true
                    };
                }
                else
                {
                    new CPUx86.Pop {
                        DestinationReg = CPUx86.Registers.ECX
                    };
                    new CPUx86.Pop {
                        DestinationReg = CPUx86.Registers.EAX
                    };                                                        // gets devised by ecx
                    new CPUx86.Xor {
                        DestinationReg = CPUx86.Registers.EDX, SourceReg = CPUx86.Registers.EDX
                    };

                    new CPUx86.Divide {
                        DestinationReg = CPUx86.Registers.ECX
                    };                                                           // => EAX / ECX
                    new CPUx86.Push {
                        DestinationReg = CPUx86.Registers.EDX
                    };
                }
            }
        }
Beispiel #23
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);
                }
            }
        }
Beispiel #24
0
 public override void AssembleNew(Cosmos.Assembler.Assembler aAssembler, object aMethodInfo)
 {
     XS.Halt();
 }
Beispiel #25
0
        public static void DoExecute(uint xStackContentSize, string aBaseLabel)
        {
            //TODO: Throw System.OverflowException if the result won't fit in the type.

            if (xStackContentSize > 4)
            {
                // div of both == LEFT_LOW * RIGHT_LOW + ((LEFT_LOW * RIGHT_HIGH + RIGHT_LOW * LEFT_HIGH) << 32)
                string Simple32Multiply = aBaseLabel + "Simple32Multiply";
                string MoveReturnValue  = aBaseLabel + "MoveReturnValue";

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

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

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

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

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

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

                XS.Jump(MoveReturnValue);

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

                XS.Label(MoveReturnValue);
                // move high result to left high
                XS.Set(ESP, EDX, destinationDisplacement: 12);
                // move low result to left low
                XS.Set(ESP, EAX, destinationDisplacement: 8);
                // pop right 64 value
                XS.Add(XSRegisters.ESP, 8);
            }
            else
            {
                XS.Pop(XSRegisters.EAX);
                XS.Multiply(ESP, isIndirect: true, size: RegisterSize.Int32);
                XS.Add(XSRegisters.ESP, 4);
                XS.Push(XSRegisters.EAX);
            }
        }
        public override void AssembleNew(Assembler.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(Assembler.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(Assembler.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(Assembler.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 Assembler.x86.Movs {
                    Size = 8, Prefixes = Assembler.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(Assembler.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 #27
0
        public override void Execute(MethodInfo aMethod, ILOpCode aOpCode)
        {
            var xOpVar        = (OpVar)aOpCode;
            var xDisplacement = Ldarg.GetArgumentDisplacement(aMethod, xOpVar.Value);

            new Mov {
                DestinationReg = RegistersEnum.EBX, SourceValue = (uint)(xDisplacement)
            };
            XS.Set(XSRegisters.OldToNewRegister(RegistersEnum.EAX), XSRegisters.OldToNewRegister(RegistersEnum.EBP));
            new CPUx86.Add {
                DestinationReg = RegistersEnum.EAX, SourceReg = RegistersEnum.EBX
            };
            new CPUx86.Push {
                DestinationReg = RegistersEnum.EAX
            };

//            if (aMethod.MethodBase.DeclaringType.FullName == "Cosmos.Kernel.Plugs.Console"
//                && aMethod.MethodBase.Name == "Write"
//                && aMethod.MethodBase.GetParameters()[0].ParameterType == typeof(int))
//            {
//                Console.Write("");
//            }
//            Cosmos.IL2CPU.ILOpCodes.OpVar xOpVar = ( Cosmos.IL2CPU.ILOpCodes.OpVar )aOpCode;
//            var xMethodInfo = aMethod.MethodBase as System.Reflection.MethodInfo;
//            uint xReturnSize = 0;
//            if( xMethodInfo != null )
//            {
//                xReturnSize = Align( SizeOfType( xMethodInfo.ReturnType ), 4 );
//            }
//            uint xOffset = 8;
//            var xCorrectedOpValValue = xOpVar.Value;
//            if( !aMethod.MethodBase.IsStatic && xOpVar.Value > 0 )
//            {
//                // if the method has a $this, the OpCode value includes the this at index 0, but GetParameters() doesnt include the this
//                xCorrectedOpValValue -= 1;
//            }
//            var xParams = aMethod.MethodBase.GetParameters();
//            for( int i = xParams.Length - 1; i > xCorrectedOpValValue; i-- )
//            {
//                var xSize = Align( SizeOfType( xParams[ i ].ParameterType ), 4 );
//                xOffset += xSize;
//            }
//            var xCurArgSize = Align( SizeOfType( xParams[ xCorrectedOpValValue ].ParameterType ), 4 );
//            uint xArgSize = 0;
//            foreach( var xParam in xParams )
//            {
//                xArgSize += Align( SizeOfType( xParam.ParameterType ), 4 );
//            }
//            xReturnSize = 0;
//            uint xExtraSize = 0;
//            if( xReturnSize > xArgSize )
//            {
//                xExtraSize = xArgSize - xReturnSize;
//            }
//            xOffset += xExtraSize;
//#warning TODO: check this
//            new CPUx86.Push { DestinationReg = CPUx86.Registers.EBP };

//            for( int i = 0; i < ( xCurArgSize / 4 ); i++ )
//            {
//                new CPUx86.Push { DestinationValue = ( uint )( xCurArgSize - ( ( i + 1 ) * 4 ) ) };
//            }
//            Assembler.Stack.Push( ( int )xCurArgSize, xParams[ xCorrectedOpValValue ].ParameterType );

//            //for( int i = 0; i < ( mSize / 4 ); i++ )
//            //{
//            //    mVirtualAddresses[ i ] = ( mOffset + ( ( i + 1 ) * 4 ) + 4 );
//            //}
//            //mAddress = aMethodInfo.Arguments[ aIndex ].VirtualAddresses.First();


//            Assembler.Stack.Push( new StackContents.Item( 4, typeof( uint ) ) );

//            //new CPUx86.Push { DestinationValue = ( uint )mAddress };
//            //
//            Assembler.Stack.Push( new StackContents.Item( 4, typeof( uint ) ) );

//            new Add( Assembler ).Execute( aMethod, aOpCode );
        }
Beispiel #28
0
        public override void AssembleNew(Assembler.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);
                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).GetTypeInfo().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();

                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("static_field__Cosmos_Core_CPU_mInterruptsEnabled", 1, destinationIsIndirect: true, size: RegisterSize.Byte8);
            XS.LoadIdt(EAX, isIndirect: true);
            // Reenable interrupts
            XS.EnableInterrupts();

            XS.Label(".__AFTER_ENABLE_INTERRUPTS");
        }
Beispiel #29
0
        public override void Execute(_MethodInfo aMethod, ILOpCode aOpCode)
        {
            var xValue        = aOpCode.StackPopTypes[0];
            var xValueIsFloat = TypeIsFloat(xValue);
            var xValueSize    = SizeOfType(xValue);

            if (xValueSize > 8)
            {
                //EmitNotImplementedException( Assembler, aServiceProvider, "Size '" + xSize.Size + "' not supported (add)", aCurrentLabel, aCurrentMethodInfo, aCurrentOffset, aNextLabel );
                throw new NotImplementedException();
            }
            //TODO if on stack a float it is first truncated, http://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.conv_r_un.aspx
            if (!xValueIsFloat)
            {
                switch (xValueSize)
                {
                case 1:
                case 2:
                case 4:
                    /*
                     * Code generated by C# / Visual Studio 2015
                     * mov         eax,dword ptr [anInt]
                     * mov         dword ptr [ebp-0E0h],eax
                     * cvtsi2sd    xmm0,dword ptr [ebp-0E0h]
                     * mov         ecx,dword ptr [ebp-0E0h]
                     * shr         ecx,1Fh
                     * addsd       xmm0,mmword ptr __xmm@41f00000000000000000000000000000 (01176B40h)[ecx*8]
                     * movsd       mmword ptr [aDouble],xmm0 # This for now means to copy our converted double to ESP
                     */
                    string BaseLabel           = GetLabel(aMethod, aOpCode) + ".";
                    string LabelSign_Bit_Unset = BaseLabel + "LabelSign_Bit_Unset";

                    XS.Set(EAX, ESP, sourceIsIndirect: true);
                    XS.Set(EBP, EAX, destinationDisplacement: -0xE0, destinationIsIndirect: true);
                    XS.SSE2.ConvertSI2SD(XMM0, EBP, sourceDisplacement: -0xE0, sourceIsIndirect: true);
                    XS.Set(ECX, EBP, sourceDisplacement: -0xE0, sourceIsIndirect: true);
                    // OK now we put in ECX the last bit of our unsigned value,  we call it "SIGN_BIT" but is a little improper...
                    XS.ShiftRight(ECX, 31);

                    /*
                     * if the 'SIGN_BIT' is 0 it means that our uint could have been placed in a normal int so ConvertSI2SD did already
                     * the right thing: we have finished
                     * if the value is 1 we need to do that addition with that weird constant to obtain the real value as double
                     */
                    XS.Compare(ECX, 0x00);
                    XS.Jump(ConditionalTestEnum.Equal, LabelSign_Bit_Unset);
                    XS.LiteralCode(@"addsd xmm0, [__uint2double_const]");
                    XS.Label(LabelSign_Bit_Unset);
                    // We have converted our value to double put it on ESP
                    // expand stack, that moved data is valid stack
                    XS.Sub(ESP, 4);
                    XS.SSE2.MoveSD(ESP, XMM0, destinationIsIndirect: true);
                    break;

                case 8:
                    BaseLabel           = GetLabel(aMethod, aOpCode) + ".";
                    LabelSign_Bit_Unset = BaseLabel + "LabelSign_Bit_Unset";

                    /*
                     * mov EAX, ESP + 4
                     * fild  qword ptr [esp]
                     * shr EAX, 31
                     * cmp ESP, 0
                     * jpe LabelSign_Bit_Unset
                     * LabelSign_Bit_Unset:
                     * fadd  dword ptr __ulong2double_const2
                     * fstp ESP
                     */
                    // Save the high part of the ulong in EAX (we cannot move all of ESP as it has 64 bit size)
                    XS.Set(EAX, ESP, sourceIsIndirect: true, sourceDisplacement: 4);
                    XS.FPU.IntLoad(ESP, isIndirect: true, size: RegisterSize.Long64);
                    XS.Test(EAX, EAX);
                    XS.Jump(ConditionalTestEnum.NotSign, LabelSign_Bit_Unset);
                    // If the sign is set we remove it using the constant __ulong2double_const4
                    XS.LiteralCode(@"fadd dword [__ulong2double_const]");
                    XS.Label(LabelSign_Bit_Unset);
                    // Convert the value to double and move it into the stack
                    XS.FPU.FloatStoreAndPop(ESP, isIndirect: true, size: RegisterSize.Long64);
                    break;

                default:
                    //EmitNotImplementedException( Assembler, GetServiceProvider(), "Conv_I: SourceSize " + xSource + " not supported!", mCurLabel, mMethodInformation, mCurOffset, mNextLabel );
                    throw new NotImplementedException("Conv_R_Un with type " + xValue + " not supported!");
                }
            }
            else
            {
                throw new NotImplementedException("Conv_R_Un with type " + xValue + " not supported!");
            }
        }
Beispiel #30
0
 public override void AssembleNew(Assembler aAssembler, object aMethodInfo)
 {
     XS.Set(XSRegisters.EAX, LabelName.Get(CPUUpdateIDTAsm.GetMethodDef(typeof(Cosmos.Core.Processing.ProcessorScheduler).Assembly, typeof(Cosmos.Core.Processing.ProcessorScheduler).FullName, "EntryPoint", true)));
     XS.Push(XSRegisters.EAX);
 }