Beispiel #1
0
        /*
         *
         * public static unsafe void Fill16Blocks(
         *                       byte *dest, [ebp + 16]
         *                       int value, [ebp + 12]
         *                       int BlocksNum) [ebp + 8]
         */
        public override void AssembleNew(Assembler aAssembler, object aMethodInfo)
        {
            /* First we copy dest, value and DestSize from EBP (stack) to 3 different registers */
            XS.Comment("Destination (int pointer)");
            XS.Set(EAX, EBP, sourceDisplacement: DestDisplacement);

            XS.Comment("Value");
            XS.Set(EBX, EBP, sourceDisplacement: ValueDisplacement);

            XS.Comment("BlocksNum");
            XS.Set(ECX, EBP, sourceDisplacement: BlocksNumDisplacement);

            /*
             * Now we need to copy 'value' (EBX) to an SSE register but we should not simply do a copy (!)
             * but all the register with 'value' repeating!
             * That is in the 16 byte SSE register should go this repeating pattern:
             * |value|value|value|value
             * luckily we don't need to do a loop for this there is the SSE3 instruction for this shufps
             */
            XS.MoveD(XMM0, EBX);
            XS.SSE.Shufps(XMM0, XMM0, 0x0000); // This broadcast the first element of XMM0 on the other 3

            /* Do the 'loop' */
            XS.Xor(EDI, EDI); // EDI is 0
            XS.Label(".loop");
            //XS.SSE.MoveUPS(EAX, XMM0, destinationIsIndirect: true, destinationDisplacement: EDI);
            XS.LiteralCode("movups[EAX + EDI], XMM0");
            XS.Add(EDI, 16);
            XS.Sub(ECX, 1);
            //XS.LiteralCode("jnz .loop");
            XS.Jump(ConditionalTestEnum.NotZero, ".loop");

            //XS.Return();
        }
Beispiel #2
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)
            {
                // Using SSE registers (that do NOT branch!) This is needed only for long now
#if false
                XS.Set(XSRegisters.ESI, 1);
                // esi = 1
                XS.Xor(XSRegisters.EDI, XSRegisters.EDI);
                // edi = 0
#endif
                if (xStackItemIsFloat)
                {
                    // Please note that SSE supports double operations only from version 2
                    XS.SSE2.MoveSD(XMM0, ESP, sourceIsIndirect: true);
                    // Increment ESP to get the value of the next double
                    XS.Add(ESP, 8);
                    XS.SSE2.MoveSD(XMM1, ESP, sourceIsIndirect: true);
                    XS.SSE2.CompareSD(XMM1, XMM0, comparision: LessThan);
                    XS.MoveD(EBX, XMM1);
                    XS.And(EBX, 1);
                    // We need to move the stack pointer of 4 Byte to "eat" the second double that is yet in the stack or we get a corrupted stack!
                    XS.Add(ESP, 4);
                    XS.Set(ESP, EBX, destinationIsIndirect: true);
                }
                else
                {
                    XS.Set(ESI, 1);
                    // esi = 1
                    XS.Xor(EDI, EDI);
                    // edi = 0
                    XS.Pop(EAX);
                    XS.Pop(EDX);
                    //value2: EDX:EAX
                    XS.Pop(EBX);
                    XS.Pop(ECX);
                    //value1: ECX:EBX
                    XS.Sub(EBX, EAX);
                    XS.SubWithCarry(ECX, EDX);
                    //result = value1 - value2
                    new ConditionalMove {
                        Condition = ConditionalTestEnum.Below, DestinationReg = RegistersEnum.EDI, SourceReg = RegistersEnum.ESI
                    };
                    XS.Push(XSRegisters.EDI);
                }
            }
            else
            {
                if (xStackItemIsFloat)
                {
                    XS.Comment("TEST TODO");
                    XS.SSE.MoveSS(XMM0, ESP, sourceIsIndirect: true);
                    XS.Add(ESP, 4);
                    XS.SSE.MoveSS(XMM1, ESP, sourceIsIndirect: true);
                    XS.SSE.CompareSS(XMM1, XMM0, comparision: LessThan);
                    XS.MoveD(EBX, XMM1);
                    XS.And(ESP, 1, destinationIsIndirect: true);
                    XS.Set(ESP, EBX, destinationIsIndirect: true);
                }
                else
                {
                    XS.Pop(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 #3
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)
            {
                // Using SSE registers (that do NOT branch!) This is needed only for long now
#if false
                XS.Set(XSRegisters.ESI, 1);
                // esi = 1
                XS.Xor(XSRegisters.EDI, XSRegisters.EDI);
                // edi = 0
#endif
                if (xStackItemIsFloat)
                {
                    // Please note that SSE supports double operations only from version 2
                    XS.SSE2.MoveSD(XMM0, ESP, sourceIsIndirect: true);
                    // Increment ESP to get the value of the next double
                    XS.Add(ESP, 8);
                    XS.SSE2.MoveSD(XMM1, ESP, sourceIsIndirect: true);
                    XS.SSE2.CompareSD(XMM1, XMM0, comparision: NotLessThanOrEqualTo);
                    XS.MoveD(EBX, XMM1);
                    XS.And(EBX, 1);
                    // We need to move the stack pointer of 4 Byte to "eat" the second double that is yet in the stack or we get a corrupted stack!
                    XS.Add(ESP, 4);
                    XS.Set(ESP, EBX, destinationIsIndirect: true);
                }
                else
                {
                    XS.Set(ESI, 1);
                    // esi = 1
                    XS.Xor(EDI, EDI);
                    // edi = 0
                    XS.Pop(EAX);
                    XS.Pop(EDX);

                    //value2: EDX:EAX
                    XS.Pop(EBX);
                    XS.Pop(ECX);
                    //value1: ECX:EBX
                    XS.Compare(ECX, EDX);
                    XS.Jump(ConditionalTestEnum.GreaterThan, LabelTrue);
                    XS.Jump(ConditionalTestEnum.LessThan, LabelFalse);
                    XS.Compare(EBX, EAX);
                    XS.Label(LabelTrue);
                    new ConditionalMove {
                        Condition = ConditionalTestEnum.GreaterThan, DestinationReg = RegistersEnum.EDI, SourceReg = RegistersEnum.ESI
                    };
                    XS.Label(LabelFalse);
                    XS.Push(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);
                    XS.SSE.CompareSS(XMM1, XMM0, comparision: NotLessThanOrEqualTo);
                    XS.MoveD(EBX, XMM1);
                    XS.And(XSRegisters.EBX, 1);
                    XS.Set(ESP, EBX, destinationIsIndirect: true);
                }

                else
                {
                    XS.Pop(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 #4
0
        public override void Execute(_MethodInfo aMethod, ILOpCode aOpCode)
        {
            var xStackItem         = aOpCode.StackPopTypes[0];
            var xStackItemSize     = SizeOfType(xStackItem);
            var xStackItemIsFloat  = TypeIsFloat(xStackItem);
            var xStackItem2        = aOpCode.StackPopTypes[1];
            var xStackItem2Size    = SizeOfType(xStackItem2);
            var xStackItem2IsFloat = TypeIsFloat(xStackItem2);
            var xSize = Math.Max(xStackItemSize, xStackItem2Size);

            var xNextLabel = GetLabel(aMethod, aOpCode.NextPosition);

            if (xSize > 8)
            {
                throw new Exception("Cosmos.IL2CPU.x86->IL->Ceq.cs->Error: StackSizes > 8 not supported");
            }
            else if (xSize <= 4)
            {
                if (xStackItemIsFloat) // float
                {
                    XS.SSE.MoveSS(XMM0, ESP, sourceIsIndirect: true);
                    XS.Add(ESP, 4);
                    XS.SSE.MoveSS(XMM1, ESP, sourceIsIndirect: true);
                    XS.SSE.CompareSS(XMM1, XMM0, comparision: Equal);
                    XS.MoveD(EBX, XMM1);
                    XS.And(EBX, 1);
                    XS.Set(ESP, EBX, destinationIsIndirect: true);
                }
                else
                {
                    XS.Pop(EAX);
                    XS.Compare(EAX, ESP, sourceIsIndirect: true);
                    XS.Jump(ConditionalTestEnum.Equal, Label.LastFullLabel + ".True");
                    XS.Jump(Label.LastFullLabel + ".False");
                    XS.Label(".True");
                    XS.Add(ESP, 4);
                    XS.Push(1);
                    XS.Jump(xNextLabel);
                    XS.Label(".False");
                    XS.Add(ESP, 4);
                    XS.Push(0);
                    XS.Jump(xNextLabel);
                }
            }
            else if (xSize > 4)
            {
                if (xStackItemIsFloat)
                {
                    // Please note that SSE supports double operations only from version 2
                    XS.SSE2.MoveSD(XMM0, ESP, sourceIsIndirect: true);
                    // Increment ESP to get the value of the next double
                    XS.Add(ESP, 8);
                    XS.SSE2.MoveSD(XMM1, ESP, sourceIsIndirect: true);
                    XS.SSE2.CompareSD(XMM1, XMM0, comparision: Equal);
                    XS.MoveD(EBX, XMM1);
                    XS.And(EBX, 1);
                    // We need to move the stack pointer of 4 Byte to "eat" the second double that is yet in the stack or we get a corrupted stack!
                    XS.Add(ESP, 4);
                    XS.Set(ESP, EBX, destinationIsIndirect: true);
                }
                else
                {
                    if (IsReferenceType(xStackItem) && IsReferenceType(xStackItem2))
                    {
                        XS.Comment(xStackItem.Name);
                        XS.Add(ESP, 4);
                        XS.Pop(EAX);

                        XS.Comment(xStackItem2.Name);
                        XS.Add(ESP, 4);
                        XS.Pop(EBX);

                        XS.Compare(EAX, EBX);
                        XS.Jump(ConditionalTestEnum.NotEqual, Label.LastFullLabel + ".False");

                        // equal
                        XS.Push(1);
                        XS.Jump(xNextLabel);
                        XS.Label(Label.LastFullLabel + ".False");
                        //not equal
                        XS.Push(0);
                        XS.Jump(xNextLabel);
                    }
                    else
                    {
                        XS.Pop(EAX);
                        XS.Compare(EAX, ESP, sourceDisplacement: 4);
                        XS.Pop(EAX);
                        XS.Jump(ConditionalTestEnum.NotEqual, Label.LastFullLabel + ".False");
                        XS.Xor(EAX, ESP, sourceDisplacement: 4);
                        XS.Jump(ConditionalTestEnum.NotZero, Label.LastFullLabel + ".False");

                        //they are equal
                        XS.Add(ESP, 8);
                        XS.Push(1);
                        XS.Jump(xNextLabel);
                        XS.Label(Label.LastFullLabel + ".False");
                        //not equal
                        XS.Add(ESP, 8);
                        XS.Push(0);
                        XS.Jump(xNextLabel);
                    }
                }
            }
            else
            {
                throw new Exception("Cosmos.IL2CPU.x86->IL->Ceq.cs->Error: Case not handled!");
            }
        }
Beispiel #5
0
        public override void Execute(_MethodInfo aMethod, ILOpCode aOpCode)
        {
            var xOp          = aOpCode.OpCode;
            var xBranchLabel = AppAssembler.TmpBranchLabel(aMethod, aOpCode);

            var xStackType = aOpCode.StackPopTypes[0];
            var xSize      = SizeOfType(xStackType);
            var xIsFloat   = TypeIsFloat(xStackType);

            if (xOp == ILOpCode.Code.Brtrue ||
                xOp == ILOpCode.Code.Brfalse)
            {
                if (xIsFloat)
                {
                    throw new NotSupportedException();
                }

                if (xSize <= 4)
                {
                    XS.Pop(EAX);
                    XS.Compare(EAX, 0);
                    XS.Jump(xOp == ILOpCode.Code.Brtrue ? ConditionalTestEnum.NotEqual : ConditionalTestEnum.Equal, xBranchLabel);
                }
                else if (xSize <= 8)
                {
                    XS.Pop(EAX);
                    XS.Pop(EBX);

                    if (xOp == ILOpCode.Code.Brtrue)
                    {
                        XS.Compare(EAX, 0);
                        XS.Jump(ConditionalTestEnum.NotEqual, xBranchLabel);

                        XS.Compare(EBX, 0);
                        XS.Jump(ConditionalTestEnum.NotEqual, xBranchLabel);
                    }
                    else
                    {
                        var xEndLabel = GetLabel(aMethod, aOpCode) + ".End";

                        XS.Compare(EAX, 0);
                        XS.Jump(ConditionalTestEnum.NotEqual, xEndLabel);

                        XS.Compare(EBX, 0);
                        XS.Jump(ConditionalTestEnum.Equal, xBranchLabel);

                        XS.Label(xEndLabel);
                    }
                }
                else if (xSize > 8)
                {
                    throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Branch.cs->Error: StackSize > 8 not supported");
                }

                return;
            }

            if (xIsFloat)
            {
                var xTestOp      = SseCompareOPs[xOp];
                var xIsUnordered = xOp == ILOpCode.Code.Bge_Un ||
                                   xOp == ILOpCode.Code.Bgt_Un ||
                                   xOp == ILOpCode.Code.Ble_Un ||
                                   xOp == ILOpCode.Code.Blt_Un ||
                                   xOp == ILOpCode.Code.Bne_Un;

                if (xSize <= 4)
                {
                    XS.SSE.MoveSS(XMM0, ESP, sourceIsIndirect: true);
                    XS.Add(ESP, 4);
                    XS.SSE.MoveSS(XMM1, ESP, sourceIsIndirect: true);
                    XS.Add(ESP, 4);

                    if (xIsUnordered)
                    {
                        XS.SSE.MoveSS(XMM2, XMM1);
                        XS.SSE.CompareSS(XMM2, XMM0, ComparePseudoOpcodes.Unordered);
                        XS.MoveD(EAX, XMM2);
                        XS.Compare(EAX, 0);
                        XS.Jump(ConditionalTestEnum.NotEqual, xBranchLabel);
                    }

                    XS.SSE.CompareSS(XMM1, XMM0, xTestOp);
                    XS.MoveD(EAX, XMM1);
                    XS.Compare(EAX, 0);
                    XS.Jump(ConditionalTestEnum.NotEqual, xBranchLabel);
                }
                else if (xSize <= 8)
                {
                    XS.SSE2.MoveSD(XMM0, ESP, sourceIsIndirect: true);
                    XS.Add(ESP, 8);
                    XS.SSE2.MoveSD(XMM1, ESP, sourceIsIndirect: true);
                    XS.Add(ESP, 8);

                    if (xIsUnordered)
                    {
                        XS.SSE2.MoveSD(XMM2, XMM1);
                        XS.SSE2.CompareSD(XMM2, XMM0, ComparePseudoOpcodes.Unordered);
                        XS.MoveD(EAX, XMM2);
                        XS.Compare(EAX, 0);
                        XS.Jump(ConditionalTestEnum.NotEqual, xBranchLabel);
                    }

                    XS.SSE2.CompareSD(XMM1, XMM0, xTestOp);
                    XS.MoveD(EAX, XMM1);
                    XS.Compare(EAX, 0);
                    XS.Jump(ConditionalTestEnum.NotEqual, xBranchLabel);
                }
            }
            else
            {
                var xTestOp = TestOPs[xOp];

                if (xSize <= 4)
                {
                    XS.Pop(EAX);
                    XS.Pop(EBX);
                    XS.Compare(EBX, EAX);
                    XS.Jump(xTestOp, xBranchLabel);
                }
                else if (xSize <= 8)
                {
                    var xEndLabel = GetLabel(aMethod, aOpCode) + ".End";

                    XS.Pop(EAX);
                    XS.Pop(EDX);

                    XS.Pop(EBX);
                    XS.Pop(ECX);

                    switch (xOp)
                    {
                    case ILOpCode.Code.Beq:
                    case ILOpCode.Code.Bne_Un:
                        XS.Compare(ECX, EDX);
                        XS.Jump(ConditionalTestEnum.NotEqual, xOp == ILOpCode.Code.Beq ? xEndLabel : xBranchLabel);
                        XS.Compare(EBX, EAX);
                        XS.Jump(xTestOp, xBranchLabel);

                        break;

                    case ILOpCode.Code.Bge:
                    case ILOpCode.Code.Bgt:
                        XS.Compare(ECX, EDX);
                        XS.Jump(ConditionalTestEnum.GreaterThan, xBranchLabel);
                        XS.Jump(ConditionalTestEnum.NotEqual, xEndLabel);
                        XS.Compare(EBX, EAX);
                        XS.Jump(xTestOp, xBranchLabel);

                        break;

                    case ILOpCode.Code.Ble:
                    case ILOpCode.Code.Blt:
                        XS.Compare(ECX, EDX);
                        XS.Jump(ConditionalTestEnum.LessThan, xBranchLabel);
                        XS.Jump(ConditionalTestEnum.NotEqual, xEndLabel);
                        XS.Compare(EBX, EAX);
                        XS.Jump(xTestOp, xBranchLabel);

                        break;

                    case ILOpCode.Code.Bge_Un:
                    case ILOpCode.Code.Bgt_Un:
                        XS.Compare(ECX, EDX);
                        XS.Jump(ConditionalTestEnum.Above, xBranchLabel);
                        XS.Jump(ConditionalTestEnum.NotEqual, xEndLabel);
                        XS.Compare(EBX, EAX);
                        XS.Jump(xTestOp, xBranchLabel);

                        break;

                    case ILOpCode.Code.Ble_Un:
                    case ILOpCode.Code.Blt_Un:
                        XS.Compare(ECX, EDX);
                        XS.Jump(ConditionalTestEnum.Below, xBranchLabel);
                        XS.Jump(ConditionalTestEnum.NotEqual, xEndLabel);
                        XS.Compare(EBX, EAX);
                        XS.Jump(xTestOp, xBranchLabel);

                        break;
                    }

                    XS.Label(xEndLabel);
                }
            }

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