Beispiel #1
0
        public override void Execute(MethodInfo aMethod, ILOpCode aOpCode)
        {
            // TODO overflow check for float
            var xType    = aOpCode.StackPopTypes[0];
            var xSize    = SizeOfType(xType);
            var xIsFloat = TypeIsFloat(xType);

            if (xSize > 8)
            {
                //EmitNotImplementedException( Assembler, aServiceProvider, "Size '" + xSize.Size + "' not supported (add)", aCurrentLabel, aCurrentMethodInfo, aCurrentOffset, aNextLabel );
                throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Add_Ovf_Un.cs->Error: StackSize > 8 not supported");
            }
            else
            {
                var xBaseLabel    = GetLabel(aMethod, aOpCode) + ".";
                var xSuccessLabel = xBaseLabel + "Success";
                if (xSize > 4)
                {
                    if (xIsFloat)
                    {
                        //TODO overflow check
                        XS.FPU.FloatLoad(ESP, destinationIsIndirect: true, size: RegisterSize.Long64);
                        XS.Add(ESP, 8);
                        XS.FPU.FloatAdd(ESP, isIndirect: true, size: RegisterSize.Long64);
                        XS.FPU.FloatStoreAndPop(ESP, isIndirect: true, size: RegisterSize.Long64);
                    }
                    else
                    {
                        XS.Pop(XSRegisters.EDX); // low part
                        XS.Pop(XSRegisters.EAX); // high part
                        XS.Add(ESP, EDX, destinationIsIndirect: true);
                        XS.AddWithCarry(ESP, EAX, destinationDisplacement: 4);
                    }
                }
                else
                {
                    if (xIsFloat) //float
                    {
                        //TODO overflow check
                        XS.SSE.MoveSS(XMM0, ESP, sourceIsIndirect: true);
                        XS.Add(XSRegisters.ESP, 4);
                        XS.SSE.MoveSS(XMM1, ESP, sourceIsIndirect: true);
                        XS.SSE.AddSS(XMM0, XMM1);
                        XS.SSE.MoveSS(XMM1, ESP, sourceIsIndirect: true);
                    }
                    else //integer
                    {
                        XS.Pop(XSRegisters.EAX);
                        XS.Add(ESP, EAX, destinationIsIndirect: true);
                    }
                }
                if (false == xIsFloat)
                {
                    XS.Jump(ConditionalTestEnum.NotCarry, xSuccessLabel);
                    ThrowOverflowException();
                }
                XS.Label(xSuccessLabel);
            }
        }
Beispiel #2
0
        public override void Execute(_MethodInfo aMethod, ILOpCode aOpCode)
        {
            // TODO overflow check for float
            var xType    = aOpCode.StackPopTypes[0];
            var xSize    = SizeOfType(xType);
            var xIsFloat = TypeIsFloat(xType);

            if (xIsFloat)
            {
                throw new Exception("Cosmos.IL2CPU.x86->IL->Add_Ovf_Un.cs->Error: Expected unsigned integer operands but get float!");
            }

            if (xSize > 8)
            {
                //EmitNotImplementedException( Assembler, aServiceProvider, "Size '" + xSize.Size + "' not supported (add)", aCurrentLabel, aCurrentMethodInfo, aCurrentOffset, aNextLabel );
                throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Add_Ovf_Un.cs->Error: StackSize > 8 not supported");
            }
            else
            {
                var xBaseLabel    = GetLabel(aMethod, aOpCode) + ".";
                var xSuccessLabel = xBaseLabel + "Success";
                if (xSize > 4)   // long
                {
                    XS.Pop(EDX); // low part
                    XS.Pop(EAX); // high part
                    XS.Add(ESP, EDX, destinationIsIndirect: true);
                    XS.AddWithCarry(ESP, EAX, destinationDisplacement: 4);
                }
                else //integer
                {
                    XS.Pop(EAX);
                    XS.Add(ESP, EAX, destinationIsIndirect: true);
                }

                // Let's check if we add overflow and if so throw OverflowException
                XS.Jump(ConditionalTestEnum.NotCarry, xSuccessLabel);
                if (xSize > 4) // Hack to stop stack corruption
                {
                    XS.Add(ESP, 8);
                }
                else
                {
                    XS.Add(ESP, 4);
                }
                Call.DoExecute(Assembler, aMethod, typeof(ExceptionHelper).GetMethod("ThrowOverflow", BindingFlags.Static | BindingFlags.Public), aOpCode, GetLabel(aMethod, aOpCode), xSuccessLabel, DebugEnabled);
                XS.Label(xSuccessLabel);
            }
        }
Beispiel #3
0
 public static void DoExecute(uint xSize, bool xIsFloat)
 {
     if (xSize > 8)
     {
         //EmitNotImplementedException( Assembler, aServiceProvider, "Size '" + xSize.Size + "' not supported (add)", aCurrentLabel, aCurrentMethodInfo, aCurrentOffset, aNextLabel );
         throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Add.cs->Error: StackSize > 8 not supported");
     }
     else
     {
         if (xSize > 4)
         {
             if (xIsFloat) // double
             {
                 // Please note that SSE supports double operations only from version 2
                 XS.SSE2.MoveSD(XMM0, ESP, sourceIsIndirect: true);
                 // Move the stack of 8 bytes to get the second double
                 XS.Add(ESP, 8);
                 XS.SSE2.MoveSD(XMM1, ESP, sourceIsIndirect: true);
                 XS.SSE2.AddSD(XMM1, XMM0);
                 XS.SSE2.MoveSD(ESP, XMM1, destinationIsIndirect: true);
             }
             else // long
             {
                 XS.Pop(XSRegisters.EDX); // low part
                 XS.Pop(XSRegisters.EAX); // high part
                 XS.Add(ESP, EDX, destinationIsIndirect: true);
                 XS.AddWithCarry(ESP, EAX, destinationDisplacement: 4);
             }
         }
         else
         {
             if (xIsFloat) //float
             {
                 XS.SSE.MoveSS(XMM0, ESP, sourceIsIndirect: true);
                 XS.Add(XSRegisters.ESP, 4);
                 XS.SSE.MoveSS(XMM1, ESP, sourceIsIndirect: true);
                 XS.SSE.AddSS(XMM1, XMM0);
                 XS.SSE.MoveSS(ESP, XMM1, destinationIsIndirect: true);
             }
             else //integer
             {
                 XS.Pop(XSRegisters.EAX);
                 XS.Add(ESP, EAX, destinationIsIndirect: true);
             }
         }
     }
 }
Beispiel #4
0
 public static void DoExecute(uint xSize, bool xIsFloat)
 {
     if (xSize > 8)
     {
         //EmitNotImplementedException( Assembler, aServiceProvider, "Size '" + xSize.Size + "' not supported (add)", aCurrentLabel, aCurrentMethodInfo, aCurrentOffset, aNextLabel );
         throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Add.cs->Error: StackSize > 8 not supported");
     }
     else
     {
         if (xSize > 4)
         {
             if (xIsFloat)
             {
                 XS.FPU.FloatLoad(ESP, destinationIsIndirect: true, size: RegisterSize.Long64);
                 XS.Add(ESP, 8);
                 new CPUx86.x87.FloatAdd {
                     DestinationReg = CPUx86.RegistersEnum.ESP, DestinationIsIndirect = true, Size = 64
                 };
                 XS.FPU.FloatStoreAndPop(ESP, isIndirect: true, size: RegisterSize.Long64);
             }
             else
             {
                 XS.Pop(XSRegisters.EDX); // low part
                 XS.Pop(XSRegisters.EAX); // high part
                 XS.Add(ESP, EDX, destinationIsIndirect: true);
                 XS.AddWithCarry(ESP, EAX, destinationDisplacement: 4);
             }
         }
         else
         {
             if (xIsFloat) //float
             {
                 XS.SSE.MoveSS(XMM0, ESP, sourceIsIndirect: true);
                 XS.Add(XSRegisters.ESP, 4);
                 XS.SSE.MoveSS(XMM1, ESP, sourceIsIndirect: true);
                 XS.SSE.AddSS(XMM0, XMM1);
                 XS.SSE.MoveSS(XMM1, ESP, sourceIsIndirect: true);
             }
             else //integer
             {
                 XS.Pop(XSRegisters.EAX);
                 XS.Add(ESP, EAX, destinationIsIndirect: true);
             }
         }
     }
 }
Beispiel #5
0
        public override void Execute(_MethodInfo aMethod, ILOpCode aOpCode)
        {
            var xStackContent        = aOpCode.StackPopTypes[0];
            var xStackContentSize    = SizeOfType(xStackContent);
            var xStackContentIsFloat = TypeIsFloat(xStackContent);

            if (xStackContentSize > 4)
            {
                if (xStackContentIsFloat)
                {
                    // There is no direct double negate instruction in SSE simply we do a XOR with 0x8000000000 to flip the sign bit
                    XS.SSE2.MoveSD(XMM0, ESP, sourceIsIndirect: true);
                    XS.SSE2.XorPD(XMM0, "__doublesignbit", sourceIsIndirect: true);
                    XS.SSE2.MoveSD(ESP, XMM0, destinationIsIndirect: true);
                }
                else
                {
                    XS.Pop(EBX);    // low
                    XS.Pop(EAX);    // high
                    XS.Negate(EBX); // set carry if EBX != 0
                    XS.AddWithCarry(EAX, 0);
                    XS.Negate(EAX);
                    XS.Push(EAX);
                    XS.Push(EBX);
                }
            }
            else
            {
                if (xStackContentIsFloat)
                {
                    // There is no direct float negate instruction in SSE simply we do a XOR with 0x80000000 to flip the sign bit
                    XS.SSE.MoveSS(XMM0, ESP, sourceIsIndirect: true);
                    XS.SSE.MoveSS(XMM1, "__floatsignbit", sourceIsIndirect: true);
                    XS.SSE.XorPS(XMM0, XMM1);
                    XS.SSE.MoveSS(ESP, XMM0, destinationIsIndirect: true);
                }
                else
                {
                    XS.Pop(EAX);
                    XS.Negate(EAX);
                    XS.Push(EAX);
                }
            }
        }
Beispiel #6
0
        public override void Execute(MethodInfo aMethod, ILOpCode aOpCode)
        {
            var xStackContent        = aOpCode.StackPopTypes[0];
            var xStackContentSize    = SizeOfType(xStackContent);
            var xStackContentIsFloat = TypeIsFloat(xStackContent);

            if (xStackContentSize > 4)
            {
                if (xStackContentIsFloat)
                {
                    XS.FPU.FloatLoad(ESP, destinationIsIndirect: true, size: RegisterSize.Long64);
                    XS.FPU.FloatNegate();
                    XS.FPU.FloatStoreAndPop(ESP, isIndirect: true, size: RegisterSize.Long64);
                }
                else
                {
                    XS.Pop(XSRegisters.EBX);                     // low
                    XS.Pop(XSRegisters.EAX);                     // high
                    XS.Negate(XSRegisters.EBX);                  // set carry if EBX != 0
                    XS.AddWithCarry(XSRegisters.EAX, 0);
                    XS.Negate(XSRegisters.EAX);
                    XS.Push(XSRegisters.EAX);
                    XS.Push(XSRegisters.EBX);
                }
            }
            else
            {
                if (xStackContentIsFloat)
                {
                    XS.FPU.FloatLoad(ESP, destinationIsIndirect: true, size: RegisterSize.Int32);
                    XS.FPU.FloatNegate();
                    XS.FPU.FloatStoreAndPop(ESP, isIndirect: true, size: RegisterSize.Int32);
                }
                else
                {
                    XS.Pop(XSRegisters.EAX);
                    XS.Negate(XSRegisters.EAX);
                    XS.Push(XSRegisters.EAX);
                }
            }
        }
Beispiel #7
0
        public override void Execute(_MethodInfo aMethod, ILOpCode aOpCode)
        {
            var xType    = aOpCode.StackPopTypes[0];
            var xSize    = SizeOfType(xType);
            var xIsFloat = TypeIsFloat(xType);

            if (xIsFloat)
            {
                throw new Exception("Cosmos.IL2CPU.x86->IL->Add_Ovf.cs->Error: Expected signed integer operands but get float!");
            }

            if (xSize > 8)
            {
                //EmitNotImplementedException( Assembler, aServiceProvider, "Size '" + xSize.Size + "' not supported (add)", aCurrentLabel, aCurrentMethodInfo, aCurrentOffset, aNextLabel );
                throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Add_Ovf.cs->Error: StackSize > 8 not supported");
            }
            else
            {
                var xBaseLabel    = GetLabel(aMethod, aOpCode) + ".";
                var xSuccessLabel = xBaseLabel + "Success";
                if (xSize > 4)   // long
                {
                    XS.Pop(EDX); // low part
                    XS.Pop(EAX); // high part
                    XS.Add(ESP, EDX, destinationIsIndirect: true);
                    XS.AddWithCarry(ESP, EAX, destinationDisplacement: 4);
                }
                else //integer
                {
                    XS.Pop(EAX);
                    XS.Add(ESP, EAX, destinationIsIndirect: true);
                }

                // Let's check if we add overflow and if so throw OverflowException
                XS.Jump(ConditionalTestEnum.NoOverflow, xSuccessLabel);
                ThrowOverflowException();
                XS.Label(xSuccessLabel);
            }
        }
Beispiel #8
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);
                }
            }
        }