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, }; }
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; } }
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 }; } }
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 }; } } }
/* 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 }; }
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"); }
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 ); }
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"); }
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(); }
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"); }
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 }; } } }