Beispiel #1
0
        /*
         *
         * public static unsafe void Fill16Blocks(
         *                       byte *dest, [ebp + 8]
         *                       int value, [ebp + 12]
         *                       int BlocksNum) [ebp + 16]
         */
        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.SSE2.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 AssembleNew(Assembler aAssembler, object aMethodInfo)
        {
            // load element size into eax
            // load length into ebx
            // calculate entire size into eax and move to exc
            // load start into edi
            // clear ecx bytes starting at edi

            // load element size into eax
            XS.Set(EAX, EBP, sourceDisplacement: SourceArrayDisplacement);
            XS.Add(EAX, 8);
            XS.Set(EAX, EAX, sourceIsIndirect: true);

            // load length into ebx
            XS.Set(EBX, EBP, sourceDisplacement: SourceArrayDisplacement);
            XS.Add(EBX, 12);
            XS.Set(EBX, EBX, sourceIsIndirect: true);

            // calculate size in bytes and move to ecx
            XS.Multiply(EBX);
            XS.Set(ECX, EAX);

            // load start into esi
            XS.Set(EDI, EBP, sourceDisplacement: SourceArrayDisplacement);
            XS.Add(EDI, 16);

            // clear eax bytes starting at esi
            XS.Set(EAX, 0);
            XS.LiteralCode("rep stosb");
        }
        public override void Execute(_MethodInfo aMethod, ILOpCode aOpCode)
        {
            var xValue        = aOpCode.StackPopTypes[0];
            var xValueIsFloat = TypeIsFloat(xValue);
            var xValueSize    = SizeOfType(xValue);

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

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

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

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

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

                default:
                    //EmitNotImplementedException( Assembler, GetServiceProvider(), "Conv_I: SourceSize " + xSource + " not supported!", mCurLabel, mMethodInformation, mCurOffset, mNextLabel );
                    throw new NotImplementedException("Conv_R_Un with type " + xValue + " not supported!");
                }
            }
            else
            {
                throw new NotImplementedException("Conv_R_Un with type " + xValue + " not supported!");
            }
        }