Пример #1
0
        public override void Execute(MethodInfo aMethod, ILOpCode aOpCode)
        {
            var xOpVar   = (OpVar)aOpCode;
            var xAddress = GetEBPOffsetForLocal(aMethod, xOpVar.Value);

            xAddress += (GetStackCountForLocal(aMethod, aMethod.MethodBase.GetMethodBody().LocalVariables[xOpVar.Value]) - 1) * 4;

            // xAddress contains full size of locals, excluding the actual local
            XS.Set(XSRegisters.OldToNewRegister(CPUx86.Registers.EAX), XSRegisters.OldToNewRegister(CPUx86.Registers.EBP));
            new CPUx86.Sub
            {
                DestinationReg = CPUx86.Registers.EAX,
                SourceValue    = xAddress
            };
            new CPUx86.Push
            {
                DestinationReg = CPUx86.Registers.EAX,
            };
        }
Пример #2
0
        public override void Execute(MethodInfo aMethod, ILOpCode aOpCode)
        {
            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)
            {
                new CPUx86.Pop {
                    DestinationReg = CPUx86.Registers.EAX
                };                                                        // shift amount
                new CPUx86.Pop {
                    DestinationReg = CPUx86.Registers.EBX
                };                                                        // value
                XS.Set(XSRegisters.OldToNewRegister(CPUx86.Registers.CL), XSRegisters.OldToNewRegister(CPUx86.Registers.AL));
                new CPUx86.ShiftRight {
                    DestinationReg = CPUx86.Registers.EBX, SourceReg = CPUx86.Registers.CL
                };
                new CPUx86.Push {
                    DestinationReg = CPUx86.Registers.EBX
                };
                return;
            }
            if (xStackItem_Value_Size <= 8)
            {
                new CPUx86.Pop {
                    DestinationReg = CPUx86.Registers.EDX
                };
                new CPUx86.Mov {
                    DestinationReg = CPUx86.Registers.EAX, SourceValue = 0
                };
                new Label(xBaseLabel + "__StartLoop");
                new CPUx86.Compare {
                    DestinationReg = CPUx86.Registers.EDX, SourceReg = CPUx86.Registers.EAX
                };
                new CPUx86.ConditionalJump {
                    Condition = CPUx86.ConditionalTestEnum.Equal, DestinationLabel = xBaseLabel + "__EndLoop"
                };
                new CPUx86.Mov {
                    DestinationReg = CPUx86.Registers.EBX, SourceReg = CPUx86.Registers.ESP, SourceIsIndirect = true
                };
                new CPUx86.Mov {
                    DestinationReg = CPUx86.Registers.CL, SourceValue = 1
                };
                new CPUx86.ShiftRight {
                    DestinationReg = CPUx86.Registers.EBX, SourceReg = CPUx86.Registers.CL
                };
                new CPUx86.Mov {
                    DestinationReg = CPUx86.Registers.ESP, DestinationIsIndirect = true, SourceReg = CPUx86.Registers.EBX
                };
                new CPUx86.Mov {
                    DestinationReg = CPUx86.Registers.CL, SourceValue = 1
                };
                new CPUx86.RotateThroughCarryRight {
                    DestinationReg = CPUx86.Registers.ESP, DestinationIsIndirect = true, DestinationDisplacement = 4, Size = 32, SourceReg = CPUx86.Registers.CL
                };
                new CPUx86.Add {
                    DestinationReg = CPUx86.Registers.EAX, SourceValue = 1
                };
                new CPUx86.Jump {
                    DestinationLabel = xBaseLabel + "__StartLoop"
                };

                new Label(xBaseLabel + "__EndLoop");
                return;
            }
        }
Пример #3
0
        public static void DoExecute(uint xStackContentSize, string aBaseLabel)
        {
            //TODO: Throw System.OverflowException if the result won't fit in the type.

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

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

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

                // compair LEFT_HIGH, RIGHT_HIGH , on zero only simple multiply is used
                //mov RIGHT_HIGH to eax, is useable on Full 64 multiply
                new Assembler.x86.Mov
                {
                    DestinationReg     = Cosmos.Assembler.x86.Registers.EAX,
                    SourceReg          = Cosmos.Assembler.x86.Registers.ESP,
                    SourceIsIndirect   = true,
                    SourceDisplacement = 4
                };
                new Assembler.x86.Or
                {
                    DestinationReg     = Cosmos.Assembler.x86.Registers.EAX,
                    SourceReg          = Cosmos.Assembler.x86.Registers.ESP,
                    SourceIsIndirect   = true,
                    SourceDisplacement = 12
                };
                new Assembler.x86.ConditionalJump
                {
                    Condition        = Cosmos.Assembler.x86.ConditionalTestEnum.Zero,
                    DestinationLabel = Simple32Multiply
                };
                // Full 64 Multiply

                // copy again, or could change EAX
                //TODO is there an opcode that does OR without change EAX?
                new Assembler.x86.Mov
                {
                    DestinationReg     = Cosmos.Assembler.x86.Registers.EAX,
                    SourceReg          = Cosmos.Assembler.x86.Registers.ESP,
                    SourceIsIndirect   = true,
                    SourceDisplacement = 4
                };
                // eax contains already RIGHT_HIGH
                // multiply with LEFT_LOW
                new Assembler.x86.Multiply
                {
                    DestinationReg          = Cosmos.Assembler.x86.Registers.ESP,
                    DestinationIsIndirect   = true,
                    DestinationDisplacement = 8,
                    Size = 32
                };
                // save result of LEFT_LOW * RIGHT_HIGH
                XS.Set(XSRegisters.OldToNewRegister(Registers.ECX), XSRegisters.OldToNewRegister(Registers.EAX));

                //mov RIGHT_LOW to eax
                new Assembler.x86.Mov
                {
                    DestinationReg   = Cosmos.Assembler.x86.Registers.EAX,
                    SourceReg        = Cosmos.Assembler.x86.Registers.ESP,
                    SourceIsIndirect = true
                };
                // multiply with LEFT_HIGH
                new Assembler.x86.Multiply
                {
                    DestinationReg          = Cosmos.Assembler.x86.Registers.ESP,
                    DestinationIsIndirect   = true,
                    DestinationDisplacement = 12,
                    Size = 32
                };
                // add result of LEFT_LOW * RIGHT_HIGH + RIGHT_LOW + LEFT_HIGH
                new Assembler.x86.Add
                {
                    DestinationReg = Cosmos.Assembler.x86.Registers.ECX,
                    SourceReg      = Cosmos.Assembler.x86.Registers.EAX
                };

                //mov RIGHT_LOW to eax
                new Assembler.x86.Mov
                {
                    DestinationReg   = Cosmos.Assembler.x86.Registers.EAX,
                    SourceReg        = Cosmos.Assembler.x86.Registers.ESP,
                    SourceIsIndirect = true
                };
                // multiply with LEFT_LOW
                new Assembler.x86.Multiply
                {
                    DestinationReg          = Cosmos.Assembler.x86.Registers.ESP,
                    DestinationIsIndirect   = true,
                    DestinationDisplacement = 8,
                    Size = 32
                };
                // add LEFT_LOW * RIGHT_HIGH + RIGHT_LOW + LEFT_HIGH to high dword of last result
                new Assembler.x86.Add
                {
                    DestinationReg = Cosmos.Assembler.x86.Registers.EDX,
                    SourceReg      = Cosmos.Assembler.x86.Registers.ECX
                };

                new Assembler.x86.Jump {
                    DestinationLabel = MoveReturnValue
                };

                new Label(Simple32Multiply);
                //mov RIGHT_LOW to eax
                new Assembler.x86.Mov
                {
                    DestinationReg   = Cosmos.Assembler.x86.Registers.EAX,
                    SourceReg        = Cosmos.Assembler.x86.Registers.ESP,
                    SourceIsIndirect = true
                };
                // multiply with LEFT_LOW
                new Assembler.x86.Multiply
                {
                    DestinationReg          = Cosmos.Assembler.x86.Registers.ESP,
                    DestinationIsIndirect   = true,
                    DestinationDisplacement = 8,
                    Size = 32
                };

                new Label(MoveReturnValue);
                // move high result to left high
                new Assembler.x86.Mov
                {
                    DestinationReg          = Cosmos.Assembler.x86.Registers.ESP,
                    DestinationIsIndirect   = true,
                    DestinationDisplacement = 12,
                    SourceReg = Cosmos.Assembler.x86.Registers.EDX
                };
                // move low result to left low
                new Assembler.x86.Mov
                {
                    DestinationReg          = Cosmos.Assembler.x86.Registers.ESP,
                    DestinationIsIndirect   = true,
                    DestinationDisplacement = 8,
                    SourceReg = Cosmos.Assembler.x86.Registers.EAX
                };
                // pop right 64 value
                new Assembler.x86.Add {
                    DestinationReg = Cosmos.Assembler.x86.Registers.ESP, SourceValue = 8
                };
            }
            else
            {
                new Assembler.x86.Pop {
                    DestinationReg = Cosmos.Assembler.x86.Registers.EAX
                };
                new Assembler.x86.Multiply
                {
                    DestinationReg        = Cosmos.Assembler.x86.Registers.ESP,
                    DestinationIsIndirect = true,
                    Size = 32
                };
                new Assembler.x86.Add {
                    DestinationReg = Cosmos.Assembler.x86.Registers.ESP, SourceValue = 4
                };
                new Assembler.x86.Push {
                    DestinationReg = Cosmos.Assembler.x86.Registers.EAX
                };
            }
        }
Пример #4
0
        public override void Execute(MethodInfo aMethod, ILOpCode aOpCode)
        {
            var xStackItem     = aOpCode.StackPopTypes[0];
            var xStackItemSize = SizeOfType(xStackItem);
            var xSize          = Math.Max(xStackItemSize, SizeOfType(aOpCode.StackPopTypes[1]));

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

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

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

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

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

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

                    new Label(LabelShiftRight);

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

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

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

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

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

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

                    //TODO: implement proper derivation correction and overflow detection

                    new CPUx86.Jump {
                        DestinationLabel = LabelEnd
                    };

                    new Label(LabelNoLoop);
                    //save high dividend
                    XS.Set(XSRegisters.OldToNewRegister(CPUx86.Registers.ECX), XSRegisters.OldToNewRegister(CPUx86.Registers.EAX));
                    XS.Set(XSRegisters.OldToNewRegister(CPUx86.Registers.EAX), XSRegisters.OldToNewRegister(CPUx86.Registers.EDX));
                    // extend that sign is in edx
                    new CPUx86.SignExtendAX {
                        Size = 32
                    };
                    // divide high part
                    new CPUx86.IDivide {
                        DestinationReg = CPUx86.Registers.ESI
                    };
                    XS.Set(XSRegisters.OldToNewRegister(CPUx86.Registers.EAX), XSRegisters.OldToNewRegister(CPUx86.Registers.ECX));
                    // divide low part
                    new CPUx86.Divide {
                        DestinationReg = CPUx86.Registers.ESI
                    };
                    // save low result
                    new CPUx86.Push {
                        DestinationValue = 0
                    };
                    new CPUx86.Push {
                        DestinationReg = CPUx86.Registers.EDX
                    };

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

                    new CPUx86.Divide {
                        DestinationReg = CPUx86.Registers.ECX
                    };                                                       // => EAX / ECX
                    new CPUx86.Push {
                        DestinationReg = CPUx86.Registers.EDX
                    };
                }
            }
        }
Пример #5
0
        /* void Copy(Array sourceArray,			ebp + 0x1C
         *			 int sourceIndex,			ebp + 0x18
         *			 Array destinationArray,	ebp + 0x14
         *			 int destinationIndex,		ebp + 0x10
         *			 int length,				ebp + 0xC
         *			 bool reliable);			ebp + 0x8
         */
        public override void AssembleNew(Assembler.Assembler aAssembler, object aMethodInfo)
        {
            new CPUx86.Mov {
                DestinationReg = CPUx86.Registers.EAX, SourceReg = CPUx86.Registers.EBP, SourceIsIndirect = true, SourceDisplacement = SourceArrayDisplacement
            };
            new CPUx86.Mov {
                DestinationReg = CPUx86.Registers.EAX, SourceReg = CPUx86.Registers.EAX, SourceIsIndirect = true
            };                                                                                                                   // dereference memory handle to pointer
            new CPUx86.Push {
                DestinationReg = CPUx86.Registers.EAX
            };
            new CPUx86.Add {
                DestinationReg = CPUx86.Registers.ESP, DestinationIsIndirect = true, SourceValue = 12, Size = 32
            };                                                                                                                   // pointer is at the element size
            new CPUx86.Pop {
                DestinationReg = CPUx86.Registers.EAX
            };
            new CPUx86.Mov {
                DestinationReg = CPUx86.Registers.EAX, SourceReg = CPUx86.Registers.EAX, SourceIsIndirect = true
            };                                                                                                                   // element size
            new CPUx86.Mov {
                DestinationReg = CPUx86.Registers.EBX, SourceReg = CPUx86.Registers.EBP, SourceIsIndirect = true, SourceDisplacement = SourceIndexDisplacement
            };
            new CPUx86.Multiply {
                DestinationReg = CPUx86.Registers.EBX
            };
            new CPUx86.Add {
                DestinationReg = CPUx86.Registers.EAX, SourceValue = 16
            };
            new CPUx86.Mov {
                DestinationReg = CPUx86.Registers.ESI, SourceReg = CPUx86.Registers.EBP, SourceIsIndirect = true, SourceDisplacement = SourceArrayDisplacement
            };
            new CPUx86.Mov {
                DestinationReg = CPUx86.Registers.ESI, SourceReg = CPUx86.Registers.ESI, SourceIsIndirect = true
            };                                                                                                                   // dereference memory handle to pointer
            new CPUx86.Add {
                DestinationReg = CPUx86.Registers.ESI, SourceReg = CPUx86.Registers.EAX
            };                                                                                          // source ptr
            new CPUx86.Mov {
                DestinationReg = CPUx86.Registers.EDX, SourceReg = CPUx86.Registers.EBP, SourceIsIndirect = true, SourceDisplacement = DestinationArrayDisplacement
            };
            new CPUx86.Mov {
                DestinationReg = CPUx86.Registers.EDX, SourceReg = CPUx86.Registers.EDX, SourceIsIndirect = true
            };                                                                                                                   // dereference memory handle to pointer
            new CPUx86.Push {
                DestinationReg = CPUx86.Registers.EDX
            };
            new CPUx86.Add {
                DestinationReg = CPUx86.Registers.ESP, DestinationIsIndirect = true, SourceValue = 12, Size = 32
            };                                                                                                                   // pointer is at element size
            new CPUx86.Pop {
                DestinationReg = CPUx86.Registers.EAX
            };
            new CPUx86.Mov {
                DestinationReg = CPUx86.Registers.EAX, SourceReg = CPUx86.Registers.EAX, SourceIsIndirect = true
            };                                                                                                                   // dereference handle to pointer
            new CPUx86.Mov {
                DestinationReg = CPUx86.Registers.ECX, SourceReg = CPUx86.Registers.EBP, SourceIsIndirect = true, SourceDisplacement = DestinationIndexDisplacement
            };
            new CPUx86.Multiply {
                DestinationReg = CPUx86.Registers.ECX
            };
            new CPUx86.Add {
                DestinationReg = CPUx86.Registers.EAX, SourceValue = 16
            };
            new CPUx86.Mov {
                DestinationReg = CPUx86.Registers.EDI, SourceReg = CPUx86.Registers.EBP, SourceIsIndirect = true, SourceDisplacement = DestinationArrayDisplacement
            };
            new CPUx86.Mov {
                DestinationReg = CPUx86.Registers.EDI, SourceReg = CPUx86.Registers.EDI, SourceIsIndirect = true
            };                                                                                                                   // dereference handle to pointer
            new CPUx86.Add {
                DestinationReg = CPUx86.Registers.EDI, SourceReg = CPUx86.Registers.EAX
            };

            // calculate byte count to copy
            new CPUx86.Mov {
                DestinationReg = CPUx86.Registers.EAX, SourceReg = CPUx86.Registers.EBP, SourceIsIndirect = true, SourceDisplacement = DestinationArrayDisplacement
            };
            new CPUx86.Mov {
                DestinationReg = CPUx86.Registers.EAX, SourceReg = CPUx86.Registers.EAX, SourceIsIndirect = true
            };                                                                                                                   // dereference memory handle to pointer
            new CPUx86.Add {
                DestinationReg = CPUx86.Registers.EAX, SourceValue = 12
            };
            new CPUx86.Mov {
                DestinationReg = CPUx86.Registers.EAX, SourceReg = CPUx86.Registers.EAX, SourceIsIndirect = true
            };
            new CPUx86.Mov {
                DestinationReg = CPUx86.Registers.EDX, SourceReg = CPUx86.Registers.EBP, SourceIsIndirect = true, SourceDisplacement = LengthDisplacement
            };
            new CPUx86.Multiply {
                DestinationReg = CPUx86.Registers.EDX
            };
            XS.Set(XSRegisters.OldToNewRegister(CPUx86.Registers.ECX), XSRegisters.OldToNewRegister(CPUx86.Registers.EAX));
            new CPUx86.Movs {
                Size = 8, Prefixes = CPUx86.InstructionPrefixes.Repeat
            };
        }
Пример #6
0
        public void CreateGDT()
        {
            new Comment(this, "BEGIN - Create GDT");
            var xGDT = new List <byte>();

            // Null Segment - Selector 0x00
            // Not used, but required by many emulators.
            xGDT.AddRange(new byte[8]
            {
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
            });

            // Code Segment
            mGdCode = (byte)xGDT.Count;
            xGDT.AddRange(GdtDescriptor(0x00000000, 0xFFFFFFFF, true));

            // Data Segment - Selector
            mGdData = (byte)xGDT.Count;
            xGDT.AddRange(GdtDescriptor(0x00000000, 0xFFFFFFFF, false));
            DataMembers.Add(new DataMember("_NATIVE_GDT_Contents", xGDT.ToArray()));

            new Comment("Tell CPU about GDT");
            var xGdtPtr = new UInt16[3];

            // Size of GDT Table - 1
            xGdtPtr[0] = (UInt16)(xGDT.Count - 1);
            DataMembers.Add(new DataMember("_NATIVE_GDT_Pointer", xGdtPtr));
            new Mov
            {
                DestinationRef          = Cosmos.Assembler.ElementReference.New("_NATIVE_GDT_Pointer"),
                DestinationIsIndirect   = true,
                DestinationDisplacement = 2,
                SourceRef = Cosmos.Assembler.ElementReference.New("_NATIVE_GDT_Contents")
            };
            new Mov
            {
                DestinationReg = Registers.EAX, SourceRef = Cosmos.Assembler.ElementReference.New("_NATIVE_GDT_Pointer")
            };
            new Lgdt
            {
                DestinationReg = Registers.EAX, DestinationIsIndirect = true
            };

            new Comment("Set data segments");
            new Mov
            {
                DestinationReg = Registers.EAX, SourceValue = mGdData
            };
            XS.Set(XSRegisters.OldToNewRegister(Registers.DS), XSRegisters.OldToNewRegister(Registers.EAX));
            XS.Set(XSRegisters.OldToNewRegister(Registers.ES), XSRegisters.OldToNewRegister(Registers.EAX));
            XS.Set(XSRegisters.OldToNewRegister(Registers.FS), XSRegisters.OldToNewRegister(Registers.EAX));
            XS.Set(XSRegisters.OldToNewRegister(Registers.GS), XSRegisters.OldToNewRegister(Registers.EAX));
            XS.Set(XSRegisters.OldToNewRegister(Registers.SS), XSRegisters.OldToNewRegister(Registers.EAX));

            new Comment("Force reload of code segment");
            new JumpToSegment
            {
                Segment = mGdCode, DestinationLabel = "Boot_FlushCsGDT"
            };
            new Label("Boot_FlushCsGDT");
            new Cosmos.Assembler.Comment(this, "END - Create GDT");
        }
Пример #7
0
        public override void Execute(MethodInfo aMethod, ILOpCode aOpCode)
        {
            var xOpVar        = (OpVar)aOpCode;
            var xDisplacement = Ldarg.GetArgumentDisplacement(aMethod, xOpVar.Value);

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

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

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

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


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

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

//            new Add( Assembler ).Execute( aMethod, aOpCode );
        }
Пример #8
0
        public override void AssembleNew(Cosmos.Assembler.Assembler aAssembler, object aMethodInfo)
        {
            // IDT is already initialized but just for base hooks, and asm only.
            // ie Int 1, 3 and GPF
            // This routine updates the IDT now that we have C# running to allow C# hooks to handle
            // the other INTs

            // We are updating the IDT, disable interrupts
            new CPUx86.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;
                }

                new CPUx86.Mov {
                    DestinationReg = CPUx86.Registers.EAX, SourceRef = CPUAll.ElementReference.New("__ISR_Handler_" + i.ToString("X2"))
                };
                new CPUx86.Mov
                {
                    DestinationRef          = CPUAll.ElementReference.New("_NATIVE_IDT_Contents"),
                    DestinationIsIndirect   = true,
                    DestinationDisplacement = ((i * 8) + 0),
                    SourceReg = CPUx86.Registers.AL
                };
                new CPUx86.Mov
                {
                    DestinationRef          = CPUAll.ElementReference.New("_NATIVE_IDT_Contents"),
                    DestinationIsIndirect   = true,
                    DestinationDisplacement = ((i * 8) + 1),
                    SourceReg = CPUx86.Registers.AH
                };
                new CPUx86.Mov
                {
                    DestinationRef          = CPUAll.ElementReference.New("_NATIVE_IDT_Contents"),
                    DestinationIsIndirect   = true,
                    DestinationDisplacement = ((i * 8) + 2),
                    SourceValue             = 0x8,
                    Size = 8
                };

                new CPUx86.Mov
                {
                    DestinationRef          = CPUAll.ElementReference.New("_NATIVE_IDT_Contents"),
                    DestinationIsIndirect   = true,
                    DestinationDisplacement = ((i * 8) + 5),
                    SourceValue             = 0x8E,
                    Size = 8
                };
                new CPUx86.ShiftRight {
                    DestinationReg = CPUx86.Registers.EAX, SourceValue = 16
                };
                new CPUx86.Mov
                {
                    DestinationRef          = CPUAll.ElementReference.New("_NATIVE_IDT_Contents"),
                    DestinationIsIndirect   = true,
                    DestinationDisplacement = ((i * 8) + 6),
                    SourceReg = CPUx86.Registers.AL
                };
                new CPUx86.Mov
                {
                    DestinationRef          = CPUAll.ElementReference.New("_NATIVE_IDT_Contents"),
                    DestinationIsIndirect   = true,
                    DestinationDisplacement = ((i * 8) + 7),
                    SourceReg = CPUx86.Registers.AH
                };
            }

            new CPUx86.Jump {
                DestinationLabel = "__AFTER__ALL__ISR__HANDLER__STUBS__"
            };
            var xInterruptsWithParam = new int[] { 8, 10, 11, 12, 13, 14 };

            for (int j = 0; j < 256; j++)
            {
                new CPUAll.Label("__ISR_Handler_" + j.ToString("X2"));
                new CPUx86.Call {
                    DestinationLabel = "__INTERRUPT_OCCURRED__"
                };

                if (Array.IndexOf(xInterruptsWithParam, j) == -1)
                {
                    new CPUx86.Push {
                        DestinationValue = 0
                    };
                }
                new CPUx86.Push {
                    DestinationValue = (uint)j
                };
                new CPUx86.Pushad();

                new CPUx86.Sub {
                    DestinationReg = CPUx86.Registers.ESP, SourceValue = 4
                };
                XS.Set(XSRegisters.OldToNewRegister(CPUx86.Registers.EAX), XSRegisters.OldToNewRegister(CPUx86.Registers.ESP)); // preserve old stack address for passing to interrupt handler

                // store floating point data
                new CPUx86.And {
                    DestinationReg = CPUx86.Registers.ESP, SourceValue = 0xfffffff0
                };                                                                                  // fxsave needs to be 16-byte alligned
                new CPUx86.Sub {
                    DestinationReg = CPUx86.Registers.ESP, SourceValue = 512
                };                                                                           // fxsave needs 512 bytes
                new FXSave {
                    DestinationReg = CPUx86.Registers.ESP, DestinationIsIndirect = true
                };                                                                                  // save the registers
                new CPUx86.Mov {
                    DestinationReg = CPUx86.Registers.EAX, DestinationIsIndirect = true, SourceReg = CPUx86.Registers.ESP
                };

                new CPUx86.Push {
                    DestinationReg = CPUx86.Registers.EAX
                };                                                         //
                new CPUx86.Push {
                    DestinationReg = CPUx86.Registers.EAX
                };                                                         // pass old stack address (pointer to InterruptContext struct) to the interrupt handler
                                                                           //new CPUx86.Move("eax",
                                                                           //                "esp");
                                                                           //new CPUx86.Push("eax");
                new CPUx86.JumpToSegment {
                    Segment = 8, DestinationLabel = "__ISR_Handler_" + j.ToString("X2") + "_SetCS"
                };
                new CPUAll.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);
                }
                new CPUx86.Call {
                    DestinationLabel = CPUAll.LabelName.Get(xHandler)
                };
                new CPUx86.Pop {
                    DestinationReg = CPUx86.Registers.EAX
                };
                new FXStore {
                    DestinationReg = CPUx86.Registers.ESP, DestinationIsIndirect = true
                };

                XS.Set(XSRegisters.OldToNewRegister(CPUx86.Registers.ESP), XSRegisters.OldToNewRegister(CPUx86.Registers.EAX)); // this restores the stack for the FX stuff, except the pointer to the FX data
                new CPUx86.Add {
                    DestinationReg = CPUx86.Registers.ESP, SourceValue = 4
                };                                                                         // "pop" the pointer

                new CPUx86.Popad();

                new CPUx86.Add {
                    DestinationReg = CPUx86.Registers.ESP, SourceValue = 8
                };
                new CPUAll.Label("__ISR_Handler_" + j.ToString("X2") + "_END");
                new CPUx86.IRET();
            }
            new CPUAll.Label("__INTERRUPT_OCCURRED__");
            new CPUx86.Return();
            new CPUAll.Label("__AFTER__ALL__ISR__HANDLER__STUBS__");
            new CPUx86.Noop();
            new CPUx86.Mov {
                DestinationReg = CPUx86.Registers.EAX, SourceReg = CPUx86.Registers.EBP, SourceIsIndirect = true, SourceDisplacement = 8
            };
            new CPUx86.Compare {
                DestinationReg = CPUx86.Registers.EAX, SourceValue = 0
            };
            new CPUx86.ConditionalJump {
                Condition = CPUx86.ConditionalTestEnum.Zero, DestinationLabel = ".__AFTER_ENABLE_INTERRUPTS"
            };

            // reload interrupt list
            new CPUx86.Mov {
                DestinationReg = CPUx86.Registers.EAX, SourceRef = Cosmos.Assembler.ElementReference.New("_NATIVE_IDT_Pointer")
            };
            new CPUx86.Mov {
                DestinationRef = CPUAll.ElementReference.New("static_field__Cosmos_Core_CPU_mInterruptsEnabled"), DestinationIsIndirect = true, SourceValue = 1
            };
            new CPUx86.Lidt {
                DestinationReg = CPUx86.Registers.EAX, DestinationIsIndirect = true
            };
            // Reenable interrupts
            new CPUx86.Sti();

            new CPUAll.Label(".__AFTER_ENABLE_INTERRUPTS");
        }
Пример #9
0
        public override void AssembleNew(Cosmos.Assembler.Assembler aAssembler, object aMethodInfo)
        {
            var xAssembler        = (Cosmos.Assembler.Assembler)aAssembler;
            var xMethodInfo       = (Cosmos.IL2CPU.MethodInfo)aMethodInfo;
            var xMethodBaseAsInfo = xMethodInfo.MethodBase as global::System.Reflection.MethodInfo;

            if (xMethodBaseAsInfo.ReturnType != typeof(void))
            {
                throw new Exception("Events with return type not yet supported!");
            }
            new Comment("XXXXXXX");
            new CPUx86.Xchg {
                DestinationReg = CPUx86.Registers.BX, SourceReg = CPUx86.Registers.BX, Size = 16
            };

            /*
             * EAX contains the GetInvocationList() array at the index at which it was last used
             * EDX contains the index at which the EAX is
             * EBX contains the number of items in the array
             * ECX contains the argument size
             */
            new CPUx86.ClearInterruptFlag();
            new Assembler.Label(".DEBUG");
            //new CPU.Label("____DEBUG_FOR_MULTICAST___");
            new Assembler.Comment("move address of delegate to eax");
            new CPUx86.Mov {
                DestinationReg = CPUx86.Registers.EAX, SourceReg = CPUx86.Registers.EBP, SourceIsIndirect = true, SourceDisplacement = Ldarg.GetArgumentDisplacement(xMethodInfo, 0)
            };

            var xGetInvocationListMethod = typeof(MulticastDelegate).GetMethod("GetInvocationList");

            new Assembler.Comment("push address of delgate to stack");
            new CPUx86.Push {
                DestinationReg = CPUx86.Registers.EAX
            };                                                        //addrof this
            new CPUx86.Call {
                DestinationLabel = Assembler.LabelName.Get(xGetInvocationListMethod)
            };
            new Assembler.Comment("get address from return value -> eax");
            new CPUx86.Pop {
                DestinationReg = CPUx86.Registers.EAX
            };
            ;//list
            new Assembler.Comment("eax+=8 is where the offset where an array's count is");
            new CPUx86.Mov {
                DestinationReg = CPUx86.RegistersEnum.EAX, SourceReg = CPUx86.RegistersEnum.EAX, SourceIsIndirect = true
            };
            new CPUx86.Add {
                DestinationReg = CPUx86.Registers.EAX, SourceValue = 8
            };                                                                        //addrof list.Length
            new Assembler.Comment("store count in ebx");
            new CPUx86.Mov {
                DestinationReg = CPUx86.Registers.EBX, SourceReg = CPUx86.Registers.EAX, SourceIsIndirect = true
            };                                                                                                                  //list.count
            new Assembler.Comment("eax+=8 is where the offset where an array's items start");
            new CPUx86.Add {
                DestinationReg = CPUx86.Registers.EAX, SourceValue = 8
            };                                                                         // Put pointer at the first item in the list.
            new CPUx86.Mov {
                DestinationReg = CPUx86.Registers.EDI, SourceValue = 0
            };
            new Assembler.Comment("ecx = ptr to delegate object");
            new CPUx86.Mov {
                DestinationReg = CPUx86.Registers.ECX, SourceReg = CPUx86.Registers.EBP, SourceIsIndirect = true, SourceDisplacement = Ldarg.GetArgumentDisplacement(xMethodInfo, 0)
            };                                                                                                                                                                                      //addrof the delegate
            new Assembler.Comment("ecx points to the size of the delegated methods arguments");
            new CPUx86.Mov {
                DestinationReg = CPUx86.Registers.ECX, SourceReg = CPUx86.Registers.ECX, SourceIsIndirect = true
            };
            new CPUx86.Mov {
                DestinationReg = CPUx86.Registers.ECX, SourceReg = CPUx86.Registers.ECX, SourceIsIndirect = true, SourceDisplacement = Ldfld.GetFieldOffset(xMethodInfo.MethodBase.DeclaringType, "$$ArgSize$$")
            };                                                                                                                                                                                                                  //the size of the arguments to the method? + 12??? -- 12 is the size of the current call stack.. i think
            new CPUx86.Xor {
                DestinationReg = CPUx86.Registers.EDX, SourceReg = CPUx86.Registers.EDX
            };
            ;//make sure edx is 0
            new Assembler.Label(".BEGIN_OF_LOOP");
            {
                new CPUx86.Compare {
                    DestinationReg = CPUx86.Registers.EDX, SourceReg = CPUx86.Registers.EBX
                };                                                                                             //are we at the end of this list
                new CPUx86.ConditionalJump {
                    Condition = CPUx86.ConditionalTestEnum.GreaterThanOrEqualTo, DestinationLabel = ".END_OF_INVOKE_"
                };                                                                                                                               //then we better stop
                new CPUx86.Pushad();
                new Assembler.Comment("esi points to where we will copy the methods argumetns from");
                XS.Set(XSRegisters.OldToNewRegister(CPUx86.Registers.ESI), XSRegisters.OldToNewRegister(CPUx86.Registers.ESP));
                new Comment("edi = ptr to delegate object");
                new CPUx86.Mov {
                    DestinationReg = CPUx86.Registers.EDI, SourceReg = CPUx86.Registers.EBP, SourceIsIndirect = true, SourceDisplacement = Ldarg.GetArgumentDisplacement(xMethodInfo, 0)
                };
                new CPUx86.Mov {
                    DestinationReg = CPUx86.Registers.EDI, SourceReg = CPUx86.Registers.EDI, SourceIsIndirect = true
                };                                                                                                                   // dereference handle
                new Comment("edi = ptr to delegate object should be a pointer to the delgates context ie (this) for the methods ");
                new CPUx86.Mov {
                    DestinationReg = CPUx86.Registers.EDI, SourceReg = CPUx86.Registers.EDI, SourceIsIndirect = true, SourceDisplacement = Ldfld.GetFieldOffset(xMethodInfo.MethodBase.DeclaringType, "System.Object System.Delegate._target")
                };
                new CPUx86.Compare {
                    DestinationReg = CPUx86.Registers.EDI, SourceValue = 0
                };
                new CPUx86.ConditionalJump {
                    Condition = CPUx86.ConditionalTestEnum.Zero, DestinationLabel = ".NO_THIS"
                };
                new CPUx86.Push {
                    DestinationReg = CPUx86.Registers.EDI
                };

                new Label(".NO_THIS");

                new Comment("make space for us to copy the arguments too");
                new CPUx86.Sub {
                    DestinationReg = CPUx86.Registers.ESP, SourceReg = CPUx86.Registers.ECX
                };
                new Comment("move the current delegate to edi");
                new CPUx86.Mov {
                    DestinationReg = CPUx86.Registers.EDI, SourceReg = CPUx86.Registers.EAX, SourceIsIndirect = true
                };
                new CPUx86.Mov {
                    DestinationReg = CPUx86.Registers.EDI, SourceReg = CPUx86.Registers.EDI, SourceIsIndirect = true
                };                                                                                                                   // dereference
                new Comment("move the methodptr from that delegate to edi ");
                new CPUx86.Mov {
                    DestinationReg = CPUx86.Registers.EDI, SourceReg = CPUx86.Registers.EDI, SourceIsIndirect = true, SourceDisplacement = Ldfld.GetFieldOffset(xMethodInfo.MethodBase.DeclaringType, "System.IntPtr System.Delegate._methodPtr")
                };                                                                                                                                                                                                                                               //
                new Comment("save methodptr on the stack");
                new CPUx86.Push {
                    DestinationReg = CPUx86.Registers.EDI
                };
                new Comment("move location to copy args to");
                XS.Set(XSRegisters.OldToNewRegister(CPUx86.Registers.EDI), XSRegisters.OldToNewRegister(CPUx86.Registers.ESP));
                new CPUx86.Add {
                    DestinationReg = CPUx86.Registers.EDI, SourceValue = 4
                };
                //new CPU.Comment("get above the saved methodptr");
                //new CPUx86.Sub { DestinationReg = CPUx86.Registers.ESP, SourceValue = 4 };
                //we allocated the argsize on the stack once, and it we need to get above the original args
                new Comment("we allocated argsize on the stack once");
                new Comment("add 32 for the Pushad + 16 for the current stack + 4 for the return value");
                //uint xToAdd = 32; // skip pushad data
                //xToAdd += 4; // method pointer
                XS.Set(XSRegisters.OldToNewRegister(CPUx86.Registers.ESI), XSRegisters.OldToNewRegister(CPUx86.Registers.EBP));
                new CPUx86.Add {
                    DestinationReg = CPUx86.Registers.ESI, SourceValue = 8
                };                                                                         // ebp+8 is first argument
                new CPUx86.Movs {
                    Size = 8, Prefixes = CPUx86.InstructionPrefixes.Repeat
                };
                new CPUx86.Pop {
                    DestinationReg = CPUx86.Registers.EDI
                };
                new Assembler.Label(".BeforeCall");
                new CPUx86.Call {
                    DestinationReg = CPUx86.Registers.EDI
                };
                new Assembler.Comment("store return -- return stored into edi after popad");
                new Assembler.Comment("edi = ptr to delegate object");
                new CPUx86.Mov {
                    DestinationReg = CPUx86.Registers.EDI, SourceReg = CPUx86.Registers.EBP, SourceIsIndirect = true, SourceDisplacement = Ldarg.GetArgumentDisplacement(xMethodInfo, 0)
                };
                new Assembler.Comment("edi = ptr to delegate object should be a pointer to the delgates context ie (this) for the methods ");
                new CPUx86.Mov {
                    DestinationReg = CPUx86.Registers.EDI, SourceReg = CPUx86.Registers.EDI, SourceIsIndirect = true
                };                                                                                                                   // dereference handle
                new CPUx86.Mov {
                    DestinationReg = CPUx86.Registers.EDI, SourceReg = CPUx86.Registers.EDI, SourceIsIndirect = true, SourceDisplacement = Ldfld.GetFieldOffset(xMethodInfo.MethodBase.DeclaringType, "System.Object System.Delegate._target")
                };                                                                                                                                                                                                                                            //i really dont get the +12, MtW: that's for the object header
                new Assembler.Label(".noTHIStoPop");
                new CPUx86.Popad();
                new CPUx86.INC {
                    DestinationReg = CPUx86.Registers.EDX
                };
                new CPUx86.Add {
                    DestinationReg = CPUx86.Registers.EAX, SourceValue = 4
                };
                new CPUx86.Jump {
                    DestinationLabel = ".BEGIN_OF_LOOP"
                };
            }
            new Assembler.Label(".END_OF_INVOKE_");
            new Assembler.Comment("get the return value");
            new CPUx86.Mov {
                DestinationReg = CPUx86.Registers.EDX, SourceReg = CPUx86.Registers.EBP, SourceIsIndirect = true, SourceDisplacement = Ldarg.GetArgumentDisplacement(xMethodInfo, 0)
            };                                                                                                                                                                                      //addrof the delegate
            new CPUx86.Mov {
                DestinationReg = CPUx86.Registers.EDX, SourceReg = CPUx86.Registers.EDX, SourceIsIndirect = true
            };                                                                                                                   // dereference handle
            new CPUx86.Mov {
                DestinationReg = CPUx86.Registers.EDX, SourceReg = CPUx86.Registers.EDX, SourceIsIndirect = true, SourceDisplacement = Ldfld.GetFieldOffset(xMethodInfo.MethodBase.DeclaringType, "$$ReturnsValue$$")
            };
            new CPUx86.Compare {
                DestinationReg = CPUx86.Registers.EDX, SourceValue = 0
            };
            new CPUx86.ConditionalJump {
                Condition = CPUx86.ConditionalTestEnum.Equal, DestinationLabel = ".noReturn"
            };
            //may have to expand the return... idk
            new CPUx86.Xchg {
                DestinationReg = CPUx86.Registers.EBP, DestinationIsIndirect = true, DestinationDisplacement = 8, SourceReg = CPUx86.Registers.EDX
            };
            new CPUx86.Xchg {
                DestinationReg = CPUx86.Registers.EBP, DestinationIsIndirect = true, DestinationDisplacement = 4, SourceReg = CPUx86.Registers.EDX
            };
            new CPUx86.Xchg {
                DestinationReg = CPUx86.Registers.EBP, DestinationIsIndirect = true, SourceReg = CPUx86.Registers.EDX
            };
            new CPUx86.Push {
                DestinationReg = CPUx86.Registers.EDX
            };                                                        //ebp
            new CPUx86.Mov {
                DestinationReg = CPUx86.Registers.ESP, DestinationIsIndirect = true, DestinationDisplacement = 12, SourceReg = CPUx86.Registers.EDI
            };
            new Assembler.Label(".noReturn");
            new CPUx86.Sti();
        }
Пример #10
0
        public static void InitializeArray(Array array, RuntimeFieldHandle fldHandle)
        {
            // Arguments:
            //    Array aArray, RuntimeFieldHandle aFieldHandle
            new CPUx86.Mov {
                DestinationReg = CPUx86.Registers.EDI, SourceReg = CPUx86.Registers.EBP, SourceIsIndirect = true, SourceDisplacement = 0xC
            };                                                                                                                                             // array
            new CPUx86.Mov {
                DestinationReg = CPUx86.Registers.EDI, SourceReg = CPUx86.Registers.EDI, SourceIsIndirect = true
            };
            new CPUx86.Mov {
                DestinationReg = CPUx86.Registers.ESI, SourceReg = CPUx86.Registers.EBP, SourceIsIndirect = true, SourceDisplacement = 8
            };                                                                                                                                          // aFieldHandle
            new CPUx86.Add {
                DestinationReg = CPUx86.Registers.EDI, SourceValue = 8
            };
            new CPUx86.Push {
                DestinationReg = CPUx86.Registers.EDI, DestinationIsIndirect = true
            };
            new CPUx86.Add {
                DestinationReg = CPUx86.Registers.EDI, SourceValue = 4
            };
            new CPUx86.Mov {
                DestinationReg = CPUx86.Registers.EAX, SourceReg = CPUx86.Registers.EDI, SourceIsIndirect = true
            };
            new CPUx86.Multiply {
                DestinationReg = CPUx86.Registers.ESP, DestinationIsIndirect = true, Size = 32
            };
            new CPUx86.Pop {
                DestinationReg = CPUx86.Registers.ECX
            };
            XS.Set(XSRegisters.OldToNewRegister(CPUx86.Registers.ECX), XSRegisters.OldToNewRegister(CPUx86.Registers.EAX));
            new CPUx86.Mov {
                DestinationReg = CPUx86.Registers.EAX, SourceValue = 0
            };
            new CPUx86.Add {
                DestinationReg = CPUx86.Registers.EDI, SourceValue = 4
            };

            new Label(".StartLoop");
            new CPUx86.Mov {
                DestinationReg = CPUx86.Registers.DL, SourceReg = CPUx86.Registers.ESI, SourceIsIndirect = true
            };
            new CPUx86.Mov {
                DestinationReg = CPUx86.Registers.EDI, DestinationIsIndirect = true, SourceReg = CPUx86.Registers.DL
            };
            new CPUx86.Add {
                DestinationReg = CPUx86.Registers.EAX, SourceValue = 1
            };
            new CPUx86.Add {
                DestinationReg = CPUx86.Registers.ESI, SourceValue = 1
            };
            new CPUx86.Add {
                DestinationReg = CPUx86.Registers.EDI, SourceValue = 1
            };
            new CPUx86.Compare {
                DestinationReg = CPUx86.Registers.EAX, SourceReg = CPUx86.Registers.ECX
            };
            new CPUx86.ConditionalJump {
                Condition = CPUx86.ConditionalTestEnum.Equal, DestinationLabel = ".EndLoop"
            };
            new CPUx86.Jump {
                DestinationLabel = ".StartLoop"
            };

            new Label(".EndLoop");
        }
Пример #11
0
        public override void Execute(MethodInfo aMethod, ILOpCode aOpCode)
        {
            var xStackItem      = aOpCode.StackPopTypes[0];
            var xStackItemSize  = SizeOfType(xStackItem);
            var xStackItem2     = aOpCode.StackPopTypes[0];
            var xStackItem2Size = SizeOfType(xStackItem2);

            if (xStackItemSize == 8)
            {
                // there seem to be an error in MS documentation, there is pushed an int32, but IL shows else
                if (xStackItem2Size != 8)
                {
                    throw new Exception("Cosmos.IL2CPU.x86->IL->Div.cs->Error: Expected a size of 8 for Div!");
                }
                if (TypeIsFloat(xStackItem))
                {// TODO add 0/0 infinity/infinity X/infinity
                    // value 1
                    new CPUx86.x87.FloatLoad {
                        DestinationReg = CPUx86.Registers.ESP, Size = 64, DestinationIsIndirect = true, DestinationDisplacement = 8
                    };
                    // value 2
                    new CPUx86.x87.FloatDivide {
                        DestinationReg = CPUx86.Registers.ESP, DestinationIsIndirect = true, Size = 64
                    };
                    // override value 1
                    new CPUx86.x87.FloatStoreAndPop {
                        DestinationReg = CPUx86.Registers.ESP, Size = 64, DestinationIsIndirect = true, DestinationDisplacement = 8
                    };
                    // pop value 2
                    new CPUx86.Add {
                        DestinationReg = CPUx86.Registers.ESP, SourceValue = 8
                    };
                }
                else
                {
                    string BaseLabel       = GetLabel(aMethod, aOpCode) + ".";
                    string LabelShiftRight = BaseLabel + "ShiftRightLoop";
                    string LabelNoLoop     = BaseLabel + "NoLoop";
                    string LabelEnd        = BaseLabel + "End";

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

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

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

                    new CPUx86.Add {
                        DestinationReg = CPUx86.Registers.ESP, SourceValue = 8
                    };

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

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

                    new Label(LabelShiftRight);

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

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

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

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

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

                    // sign extend
                    new CPUx86.SignExtendAX {
                        Size = 32
                    };

                    // save result to stack
                    new CPUx86.Push {
                        DestinationReg = CPUx86.Registers.EDX
                    };
                    new CPUx86.Push {
                        DestinationReg = CPUx86.Registers.EAX
                    };

                    //TODO: implement proper derivation correction and overflow detection

                    new CPUx86.Jump {
                        DestinationLabel = LabelEnd
                    };

                    new Label(LabelNoLoop);
                    //save high dividend
                    XS.Set(XSRegisters.OldToNewRegister(CPUx86.Registers.ECX), XSRegisters.OldToNewRegister(CPUx86.Registers.EAX));
                    XS.Set(XSRegisters.OldToNewRegister(CPUx86.Registers.EAX), XSRegisters.OldToNewRegister(CPUx86.Registers.EDX));
                    // extend that sign is in edx
                    new CPUx86.SignExtendAX {
                        Size = 32
                    };
                    // divide high part
                    new CPUx86.IDivide {
                        DestinationReg = CPUx86.Registers.ESI
                    };
                    // save high result
                    new CPUx86.Push {
                        DestinationReg = CPUx86.Registers.EAX
                    };
                    XS.Set(XSRegisters.OldToNewRegister(CPUx86.Registers.EAX), XSRegisters.OldToNewRegister(CPUx86.Registers.ECX));
                    // divide low part
                    new CPUx86.Divide {
                        DestinationReg = CPUx86.Registers.ESI
                    };
                    // save low result
                    new CPUx86.Push {
                        DestinationReg = CPUx86.Registers.EAX
                    };

                    new Label(LabelEnd);
                }
            }
            else
            {
                if (TypeIsFloat(xStackItem))
                {
                    new CPUx86.SSE.MoveSS {
                        DestinationReg = CPUx86.Registers.XMM0, SourceReg = CPUx86.Registers.ESP, SourceIsIndirect = true
                    };
                    new CPUx86.Add {
                        DestinationReg = CPUx86.Registers.ESP, SourceValue = 4
                    };
                    new CPUx86.SSE.MoveSS {
                        DestinationReg = CPUx86.Registers.XMM1, SourceReg = CPUx86.Registers.ESP, SourceIsIndirect = true
                    };
                    new CPUx86.SSE.DivSS {
                        DestinationReg = CPUx86.Registers.XMM1, SourceReg = CPUx86.Registers.XMM0
                    };
                    new CPUx86.SSE.MoveSS {
                        DestinationReg = CPUx86.Registers.ESP, DestinationIsIndirect = true, SourceReg = CPUx86.Registers.XMM1
                    };
                }
                else
                {
                    new CPUx86.Pop {
                        DestinationReg = CPUx86.Registers.ECX
                    };
                    new CPUx86.Pop {
                        DestinationReg = CPUx86.Registers.EAX
                    };
                    new CPUx86.SignExtendAX {
                        Size = 32
                    };
                    new CPUx86.IDivide {
                        DestinationReg = CPUx86.Registers.ECX
                    };
                    new CPUx86.Push {
                        DestinationReg = CPUx86.Registers.EAX
                    };
                }
            }
        }