Beispiel #1
0
        public override void AssembleNew(Assembler aAssembler, object aMethodInfo)
        {
            // IDT is already initialized but just for base hooks, and asm only.
            // ie Int 1, 3 and GPF
            // This routine updates the IDT now that we have C# running to allow C# hooks to handle
            // the other INTs

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

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

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

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

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

                if (Array.IndexOf(xInterruptsWithParam, j) == -1)
                {
                    XS.Push(0);
                }
                XS.Push((uint)j);
                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(INTs).Assembly, typeof(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(AsmMarker.Labels[AsmMarker.Type.Processor_IntsEnabled], 1, destinationIsIndirect: true, size: RegisterSize.Byte8);
            XS.LoadIdt(EAX, isIndirect: true);
            // Reenable interrupts
            XS.EnableInterrupts();

            XS.Label(".__AFTER_ENABLE_INTERRUPTS");
        }
Beispiel #2
0
        public static void DoAssemble(Type type)
        {
            if (type == null)
            {
                throw new ArgumentNullException(nameof(type));
            }
            XS.Pop(EAX);
            var xObjSize = SizeOfType(type);

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

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

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

            case 3:
            {
                XS.Set(EBX, EAX, sourceDisplacement: (int)(xObjSize - 3));
                XS.And(EBX, 0xFFFFFF);
                XS.Push(EBX);
                break;
            }

            case 0:
            {
                break;
            }

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

            xObjSize -= (xObjSize % 4);

            for (int i = 1; i <= (xObjSize / 4); i++)
            {
                XS.Push(EAX, displacement: (int)(xObjSize - (i * 4)));
            }
        }
Beispiel #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)
            {
                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.SSE2.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.SSE2.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 #4
0
        public override void Execute(MethodInfo aMethod, ILOpCode aOpCode)
        {
            var xStackItem_ShiftAmount = aOpCode.StackPopTypes[0];
            var xStackItem_Value       = aOpCode.StackPopTypes[1];
            var xStackItem_Value_Size  = SizeOfType(xStackItem_Value);

            XS.Pop(XSRegisters.ECX); // shift amount
#if DOTNETCOMPATIBLE
            if (xStackItem_Value.Size == 4)
#else
            if (xStackItem_Value_Size <= 4)
#endif
            {
                // To retain the sign bit we must use ShiftRightArithmetic and not ShiftRight!
                //XS.ShiftRight(XSRegisters.ESP, XSRegisters.CL, destinationIsIndirect: true, size: RegisterSize.Int32);
                XS.ShiftRightArithmetic(XSRegisters.ESP, XSRegisters.CL, destinationIsIndirect: true, size: RegisterSize.Int32);
            }
#if DOTNETCOMPATIBLE
            else if (xStackItem_Value_Size == 8)
#else
            else if (xStackItem_Value_Size <= 8)
#endif
            {
                string BaseLabel      = GetLabel(aMethod, aOpCode) + ".";
                string HighPartIsZero = BaseLabel + "HighPartIsZero";
                string End_Shr        = BaseLabel + "End_Shr";

                // [ESP] is low part
                // [ESP + 4] is high part

                // move high part in EAX
                XS.Set(XSRegisters.EAX, XSRegisters.ESP, sourceDisplacement: 4);

                XS.Compare(XSRegisters.CL, 32, size: RegisterSize.Byte8);
                XS.Jump(CPU.ConditionalTestEnum.AboveOrEqual, HighPartIsZero);

                // shift lower part
                XS.ShiftRightDouble(ESP, EAX, CL, destinationIsIndirect: true);
                // shift higher part
                // To retain the sign bit we must use ShiftRightArithmetic and not ShiftRight!
                //XS.ShiftRight(ESP, CL, destinationDisplacement: 4, size: RegisterSize.Int32);
                XS.ShiftRightArithmetic(ESP, CL, destinationDisplacement: 4, size: RegisterSize.Int32);
                XS.Jump(End_Shr);

                XS.Label(HighPartIsZero);

                // remove bits >= 32, so that CL max value could be only 31
                XS.And(XSRegisters.CL, 0x1f, size: RegisterSize.Byte8);

                // shift high part and move it in low part
                // To retain the sign bit we must use ShiftRightArithmetic and not ShiftRight!
                XS.ShiftRightArithmetic(XSRegisters.EAX, XSRegisters.CL);
                XS.Set(ESP, EAX, destinationIsIndirect: true);
                // replace unknown high part with a zero
                XS.Set(ESP, 0, destinationIsIndirect: true, destinationDisplacement: 4);
                //new CPUx86.Mov { DestinationReg = CPUx86.RegistersEnum.ESP, DestinationIsIndirect = true, DestinationDisplacement = 4, SourceValue = 0};

                XS.Label(End_Shr);
            }
            else
            {
                throw new NotSupportedException("A size bigger 8 not supported at Shr!");
            }

            /*string xLabelName = AppAssembler.TmpPosLabel(aMethod, aOpCode);
             * var xStackItem_ShiftAmount = Assembler.Stack.Pop();
             * var xStackItem_Value = Assembler.Stack.Peek();
             * if( xStackItem_Value.Size <= 4 )
             * {
             *  XS.Pop(XSRegisters.ECX); // shift amount
             *  XS.ShiftRight(XSRegisters.ESP, XSRegisters.CL, destinationIsIndirect: true);
             * }
             * else if( xStackItem_Value.Size <= 8 )
             * {
             *                  XS.Pop(XSRegisters.ECX); // shift amount
             *                  // [ESP] is high part
             *                  // [ESP + 4] is low part
             *                  XS.Mov(XSRegisters.EAX, XSRegisters.ESP, sourceDisplacement: 4);
             *                  // shift low part
             *                  new CPUx86.ShiftRightDouble { DestinationReg = CPUx86.Registers.ESP, DestinationIsIndirect = true, SourceReg = CPUx86.Registers.EAX, ArgumentReg = CPUx86.Registers.CL };
             *                  // shift high part
             *                  XS.ShiftRight(XSRegisters.ESP, XSRegisters.CL, destinationIsIndirect: true, size: RegisterSize.Int32);
             * }*/
        }
Beispiel #5
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 #6
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.SSE2.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.SSE2.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 (TypeIsReferenceType(xStackItem) && TypeIsReferenceType(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 #7
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 #8
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 #9
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 #10
0
        public static void Assemble(Assembler aAssembler, uint aElementSize, _MethodInfo aMethod, ILOpCode aOpCode, bool debugEnabled)
        {
            DoNullReferenceCheck(aAssembler, debugEnabled, (int)(8 + Align(aElementSize, 4)));
            uint xStackSize = aElementSize;

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

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

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

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

            XS.Label(xNoIndexOutOfRangeExeptionLabel);

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

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

            XS.Pop(ECX);

            //get bytes
            var bytes = aElementSize / 4;

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

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

            case 3:
            {
                new Comment(aAssembler, "Start 3 word");
                XS.Pop(EBX);
                XS.And(EBX, 0xFFFFFF);         // Only take the value of the lower three bytes
                XS.Set(ECX, EBX, destinationIsIndirect: true);
                break;
            }

            case 0:
            {
                break;
            }

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

            XS.Add(ESP, 12);
        }
Beispiel #11
0
        public override void Execute(_MethodInfo aMethod, ILOpCode aOpCode)
        {
            var xStackItem_ShiftAmount = aOpCode.StackPopTypes[0];
            var xStackItem_Value       = aOpCode.StackPopTypes[1];
            var xStackItem_Value_Size  = SizeOfType(xStackItem_Value);

            XS.Pop(XSRegisters.ECX); // shift amount
#if DOTNETCOMPATIBLE
            if (xStackItem_Value.Size == 4)
#else
            if (xStackItem_Value_Size <= 4)
#endif
            {
                XS.ShiftRight(XSRegisters.ESP, XSRegisters.CL, destinationIsIndirect: true, size: RegisterSize.Int32);
            }
#if DOTNETCOMPATIBLE
            else if (xStackItem_Value_Size == 8)
#else
            else if (xStackItem_Value_Size <= 8)
#endif
            {
                string BaseLabel      = GetLabel(aMethod, aOpCode) + ".";
                string HighPartIsZero = BaseLabel + "HighPartIsZero";
                string End_Shr        = BaseLabel + "End_Shr";

                // [ESP] is low part
                // [ESP + 4] is high part

                // move high part in EAX
                XS.Set(XSRegisters.EAX, XSRegisters.ESP, sourceDisplacement: 4);

                XS.Compare(XSRegisters.CL, 32, size: RegisterSize.Byte8);
                XS.Jump(CPU.ConditionalTestEnum.AboveOrEqual, HighPartIsZero);

                // shift lower part
                XS.ShiftRightDouble(ESP, EAX, CL, destinationIsIndirect: true);
                // shift higher part
                XS.ShiftRight(ESP, CL, destinationDisplacement: 4, size: RegisterSize.Int32);
                XS.Jump(End_Shr);

                XS.Label(HighPartIsZero);
                // remove bits >= 32, so that CL max value could be only 31
                XS.And(XSRegisters.CL, 0x1f, size: RegisterSize.Byte8);

                // shift high part and move it in low part
                XS.ShiftRight(XSRegisters.EAX, XSRegisters.CL);
                XS.Set(ESP, EAX, destinationIsIndirect: true);
                // replace unknown high part with a zero
                new CPUx86.Mov {
                    DestinationReg = CPUx86.RegistersEnum.ESP, DestinationIsIndirect = true, DestinationDisplacement = 4, SourceValue = 0
                };

                XS.Label(End_Shr);
            }
            else
            {
                throw new NotSupportedException("A size bigger 8 not supported at Shr!");
            }

            /*string xLabelName = AppAssembler.TmpPosLabel(aMethod, aOpCode);
             * var xStackItem_ShiftAmount = Assembler.Stack.Pop();
             * var xStackItem_Value = Assembler.Stack.Peek();
             * if( xStackItem_Value.Size <= 4 )
             * {
             *  XS.Pop(XSRegisters.ECX); // shift amount
             *  XS.ShiftRight(XSRegisters.ESP, XSRegisters.CL, destinationIsIndirect: true);
             * }
             * else if( xStackItem_Value.Size <= 8 )
             * {
             *                  XS.Pop(XSRegisters.ECX); // shift amount
             *                  // [ESP] is high part
             *                  // [ESP + 4] is low part
             *                  XS.Mov(XSRegisters.EAX, XSRegisters.ESP, sourceDisplacement: 4);
             *                  // shift low part
             *                  new CPUx86.ShiftRightDouble { DestinationReg = CPUx86.Registers.ESP, DestinationIsIndirect = true, SourceReg = CPUx86.Registers.EAX, ArgumentReg = CPUx86.Registers.CL };
             *                  // shift high part
             *                  XS.ShiftRight(XSRegisters.ESP, XSRegisters.CL, destinationIsIndirect: true, size: RegisterSize.Int32);
             * }*/

#if false
            XS.Pop(XSRegisters.ECX); // shift amount
            string xBaseLabel             = GetLabel(aMethod, aOpCode) + ".";
            var    xStackItem_ShiftAmount = aOpCode.StackPopTypes[0];
            var    xStackItem_Value       = aOpCode.StackPopTypes[1];

            if (TypeIsFloat(xStackItem_Value))
            {
                throw new NotImplementedException("Floats not yet supported!");
            }
            var xStackItem_Value_Size = SizeOfType(xStackItem_Value);
            if (xStackItem_Value_Size <= 4)
            {
                XS.Pop(XSRegisters.EAX); // shift amount
                XS.Pop(XSRegisters.EBX); // value
                XS.Set(XSRegisters.CL, XSRegisters.AL);
                XS.ShiftRight(XSRegisters.EBX, CL);
                XS.Push(XSRegisters.EBX);
                return;
            }
            if (xStackItem_Value_Size <= 8)
            {
                string BaseLabel      = GetLabel(aMethod, aOpCode) + ".";
                string HighPartIsZero = BaseLabel + "HighPartIsZero";
                string End_Shr        = BaseLabel + "End_Shr";

                // [ESP] is low part
                // [ESP + 4] is high part

                // move high part in EAX
                XS.Set(XSRegisters.EAX, XSRegisters.ESP, sourceDisplacement: 4);

                XS.Compare(XSRegisters.CL, 32, size: RegisterSize.Byte8);
                XS.Jump(CPU.ConditionalTestEnum.AboveOrEqual, HighPartIsZero);

                // shift lower part
                XS.ShiftRightDouble(ESP, EAX, CL, destinationIsIndirect: true);
                // shift higher part
                XS.ShiftRight(ESP, CL, destinationDisplacement: 4, size: RegisterSize.Int32);
                XS.Jump(End_Shr);

                XS.Label(HighPartIsZero);
                // remove bits >= 32, so that CL max value could be only 31
                XS.And(XSRegisters.CL, 0x1f, size: RegisterSize.Byte8);

                // shift high part and move it in low part
                XS.ShiftRight(XSRegisters.EAX, XSRegisters.CL);
                XS.Set(ESP, EAX, destinationIsIndirect: true);
                // replace unknown high part with a zero, if <= 32
                new CPUx86.Mov {
                    DestinationReg = CPUx86.RegistersEnum.ESP, DestinationIsIndirect = true, DestinationDisplacement = 4, SourceValue = 0
                };

                XS.Label(End_Shr);

#if false
                XS.Pop(XSRegisters.EDX);
                XS.Set(XSRegisters.EAX, 0);
                XS.Label(xBaseLabel + "__StartLoop");
                XS.Compare(XSRegisters.EDX, XSRegisters.EAX);
                XS.Jump(CPUx86.ConditionalTestEnum.Equal, xBaseLabel + "__EndLoop");
                XS.Set(EBX, ESP, sourceIsIndirect: true);
                XS.Set(XSRegisters.CL, 1);
                XS.ShiftRight(XSRegisters.EBX, CL);
                XS.Set(ESP, EBX, destinationIsIndirect: true);
                XS.Set(XSRegisters.CL, 1);
                XS.RotateThroughCarryRight(ESP, CL, destinationDisplacement: 4, size: RegisterSize.Int32);
                XS.Add(XSRegisters.EAX, 1);
                new CPUx86.Jump {
                    DestinationLabel = xBaseLabel + "__StartLoop"
                };


                XS.Label(xBaseLabel + "__EndLoop");
#endif
                return;
#endif
        }
    }
Beispiel #12
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.SSE2.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.SSE2.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 #13
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)
                {
                    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.Equal
                    };
                    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.Equal, Label.LastFullLabel + ".True");
                    XS.Jump(Label.LastFullLabel + ".False");
                    XS.Label(".True");
                    XS.Add(XSRegisters.ESP, 4);
                    XS.Push(1);
                    XS.Jump(xNextLabel);
                    XS.Label(".False");
                    XS.Add(XSRegisters.ESP, 4);
                    XS.Push(0);
                    XS.Jump(xNextLabel);
                }
            }
            else if (xSize > 4)
            {
                if (xStackItemIsFloat)
                {
                    XS.Set(XSRegisters.ESI, 1);
                    // esi = 1
                    XS.Xor(XSRegisters.EDI, XSRegisters.EDI);
                    // edi = 0

                    // 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 zero is set, ST(0) == ST(i)
                    new ConditionalMove {
                        Condition = ConditionalTestEnum.Equal, DestinationReg = RegistersEnum.EDI, SourceReg = RegistersEnum.ESI
                    };
                    // pops fpu stack
                    XS.FPU.FloatStoreAndPop(ST0);
                    XS.FPU.FloatStoreAndPop(ST0);
                    XS.Add(XSRegisters.ESP, 16);
                    XS.Push(XSRegisters.EDI);
                }
                else
                {
                    XS.Pop(XSRegisters.EAX);
                    XS.Compare(XSRegisters.EAX, XSRegisters.ESP, sourceDisplacement: 4);
                    XS.Pop(XSRegisters.EAX);
                    XS.Jump(ConditionalTestEnum.NotEqual, Label.LastFullLabel + ".False");
                    XS.Xor(XSRegisters.EAX, XSRegisters.ESP, sourceDisplacement: 4);
                    XS.Jump(ConditionalTestEnum.NotZero, Label.LastFullLabel + ".False");

                    //they are equal, eax == 0
                    XS.Add(XSRegisters.ESP, 8);
                    XS.Add(XSRegisters.EAX, 1);
                    XS.Push(XSRegisters.EAX);
                    XS.Jump(xNextLabel);
                    XS.Label(Label.LastFullLabel + ".False");
                    //eax = 0
                    XS.Add(XSRegisters.ESP, 8);
                    XS.Xor(XSRegisters.EAX, XSRegisters.EAX);
                    XS.Push(XSRegisters.EAX);
                    XS.Jump(xNextLabel);
                }
            }
            else
            {
                throw new Exception("Cosmos.IL2CPU.x86->IL->Ceq.cs->Error: Case not handled!");
            }
        }