public override void Execute(_MethodInfo aMethod, ILOpCode aOpCode) { OpType xType = (OpType)aOpCode; string xTypeID = GetTypeIDLabel(xType.Value); string xCurrentMethodLabel = GetLabel(aMethod, aOpCode); string xReturnNullLabel = xCurrentMethodLabel + "_ReturnNull"; string xAfterIsInstanceCallLabel = xCurrentMethodLabel + "_After_IsInstance_Call"; string xNextPositionLabel = GetLabel(aMethod, aOpCode.NextPosition); XS.Set(EAX, ESP, sourceIsIndirect: true, sourceDisplacement: 4); XS.Compare(EAX, 0); XS.Jump(ConditionalTestEnum.Zero, xReturnNullLabel); XS.Push(EAX, isIndirect: true); XS.Push(xTypeID, isIndirect: true); XS.Push(Convert.ToUInt32(xType.Value.IsInterface)); Call.DoExecute(Assembler, aMethod, VTablesImplRefs.IsInstanceRef, aOpCode, xCurrentMethodLabel, xAfterIsInstanceCallLabel, DebugEnabled); XS.Label(xAfterIsInstanceCallLabel); XS.Pop(EAX); XS.Compare(EAX, 0); XS.Jump(ConditionalTestEnum.Equal, xReturnNullLabel); XS.Jump(xNextPositionLabel); XS.Label(xReturnNullLabel); XS.Add(ESP, 8); XS.Push(0); XS.Push(0); }
public static void InitializeArray(Array array, RuntimeFieldHandle fldHandle) { // Arguments: // Array aArray, RuntimeFieldHandle aFieldHandle XS.Set(XSRegisters.EDI, XSRegisters.EBP, sourceDisplacement: 0xC); // array XS.Set(EDI, EDI, sourceIsIndirect: true); XS.Set(XSRegisters.ESI, XSRegisters.EBP, sourceDisplacement: 8); // aFieldHandle XS.Add(XSRegisters.EDI, 8); XS.Push(EDI, isIndirect: true); XS.Add(XSRegisters.EDI, 4); XS.Set(EAX, EDI, sourceIsIndirect: true); XS.Multiply(ESP, isIndirect: true, size: RegisterSize.Int32); XS.Pop(XSRegisters.ECX); XS.Set(XSRegisters.ECX, XSRegisters.EAX); XS.Set(XSRegisters.EAX, 0); XS.Add(XSRegisters.EDI, 4); XS.Label(".StartLoop"); XS.Set(DL, ESI, sourceIsIndirect: true); XS.Set(EDI, DL, destinationIsIndirect: true); XS.Add(XSRegisters.EAX, 1); XS.Add(XSRegisters.ESI, 1); XS.Add(XSRegisters.EDI, 1); XS.Compare(XSRegisters.EAX, XSRegisters.ECX); XS.Jump(CPUx86.ConditionalTestEnum.Equal, ".EndLoop"); XS.Jump(".StartLoop"); XS.Label(".EndLoop"); }
public override void Execute(MethodInfo aMethod, ILOpCode aOpCode) { OpType xType = ( OpType )aOpCode; string xTypeID = GetTypeIDLabel(xType.Value); string mReturnNullLabel = GetLabel(aMethod, aOpCode) + "_ReturnNull"; XS.Set(XSRegisters.EAX, XSRegisters.ESP, sourceIsIndirect: true); XS.Compare(XSRegisters.EAX, 0); XS.Jump(CPUx86.ConditionalTestEnum.Zero, mReturnNullLabel); // EAX contains a memory handle now. Lets convert it to a pointer XS.Set(XSRegisters.EAX, XSRegisters.EAX, sourceIsIndirect: true); //XS.Mov(XSRegisters.EAX, XSRegisters.EAX, sourceIsIndirect: true); XS.Push(XSRegisters.EAX, isIndirect: true); XS.Push(xTypeID, isIndirect: true); SysReflection.MethodBase xMethodIsInstance = ReflectionUtilities.GetMethodBase(typeof(VTablesImpl), "IsInstance", "System.UInt32", "System.UInt32"); //, new OpMethod( ILOpCode.Code.Call, aOpCode.Position, aOpCode.NextPosition, xMethodIsInstance, aOpCode.CurrentExceptionHandler)); Call.DoExecute(Assembler, aMethod, xMethodIsInstance, aOpCode, GetLabel(aMethod, aOpCode), GetLabel(aMethod, aOpCode) + "_After_IsInstance_Call", DebugEnabled); new Label(GetLabel(aMethod, aOpCode) + "_After_IsInstance_Call"); XS.Pop(XSRegisters.EAX); XS.Compare(XSRegisters.EAX, 0); XS.Jump(CPUx86.ConditionalTestEnum.Equal, mReturnNullLabel); // push nothing now, as we should return the object instance pointer. new CPUx86.Jump { DestinationLabel = GetLabel(aMethod, aOpCode.NextPosition) }; XS.Label(mReturnNullLabel); XS.Add(XSRegisters.ESP, 4); XS.Push(0); }
public override void Execute(_MethodInfo aMethod, ILOpCode aOpCode) { var xEndLabel = GetLabel(aMethod, aOpCode) + ".End"; // size XS.Pop(ECX); // value XS.Pop(EBX); // address XS.Pop(EDI); XS.Compare(ECX, 0); XS.Jump(ConditionalTestEnum.Equal, xEndLabel); XS.Set(EDI, BL, destinationIsIndirect: true); XS.Compare(ECX, 1); XS.Jump(ConditionalTestEnum.Equal, xEndLabel); XS.Set(ESI, EDI); XS.Increment(EDI); XS.Decrement(ECX); new Movs { Prefixes = InstructionPrefixes.Repeat, Size = 8 }; XS.Label(xEndLabel); }
public override void Execute(_MethodInfo aMethod, ILOpCode aOpCode) { var xType = (OpType)aOpCode; var xTypeID = GetTypeIDLabel(xType.Value); var xCurrentMethodLabel = GetLabel(aMethod, aOpCode); var xAfterIsInstanceCallLabel = xCurrentMethodLabel + "_After_IsInstance_Call"; var xInvalidCastLabel = xCurrentMethodLabel + "_InvalidCast"; var xNextPositionLabel = GetLabel(aMethod, aOpCode.NextPosition); XS.Set(EAX, ESP, sourceDisplacement: 4); XS.Compare(EAX, 0); XS.Jump(ConditionalTestEnum.Zero, xNextPositionLabel); XS.Push(EAX, isIndirect: true); XS.Push(xTypeID, isIndirect: true); XS.Push(Convert.ToUInt32(xType.Value.IsInterface)); MethodBase xMethodIsInstance = VTablesImplRefs.IsInstanceRef; Call.DoExecute(Assembler, aMethod, xMethodIsInstance, aOpCode, xCurrentMethodLabel, xAfterIsInstanceCallLabel, DebugEnabled); XS.Label(xAfterIsInstanceCallLabel); XS.Pop(EAX); XS.Compare(EAX, 0); XS.Jump(ConditionalTestEnum.Equal, xInvalidCastLabel); XS.Jump(xNextPositionLabel); XS.Label(xInvalidCastLabel); XS.Call(LabelName.Get(ExceptionHelperRefs.ThrowInvalidCastExceptionRef)); }
// this code is mostly copied from Newarr.cs in Il2CPU, just the code to find the size and length is different public override void AssembleNew(Assembler aAssembler, object aMethodInfo) { string xTypeID = ILOp.GetTypeIDLabel(typeof(Array)); MethodBase xCtor = typeof(Array).GetConstructors(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance)[0]; string xCtorName = LabelName.Get(xCtor); XS.Set(ECX, EBP, sourceDisplacement: 8); // size XS.Set(EDX, EBP, sourceDisplacement: 12); // length XS.Push(ECX); // size of element XS.Set(EAX, ECX); XS.Multiply(EDX); // total element size XS.Add(EAX, ObjectUtils.FieldDataOffset + 4); // total array size XS.Push(EAX); XS.Call(LabelName.Get(GCImplementationRefs.AllocNewObjectRef)); XS.Label(".AfterAlloc"); XS.Pop(EAX); XS.Pop(ESI); XS.Push(EAX); XS.Push(ESP, isIndirect: true); XS.Push(ESP, isIndirect: true); // it's on the stack 3 times now, once from the return value, twice from the pushes; XS.Pop(EAX); XS.Set(EBX, xTypeID, sourceIsIndirect: true); // array type id XS.Set(EAX, EBX, destinationIsIndirect: true); // array type id XS.Set(EAX, (uint)ObjectUtils.InstanceTypeEnum.Array, destinationDisplacement: 4, destinationIsIndirect: true); XS.Set(EAX, ESI, destinationDisplacement: 8, destinationIsIndirect: true); XS.Set(EAX, ECX); XS.Push(0); XS.Call(xCtorName); XS.Push(0); }
protected static void DoNullReferenceCheck(Assembler.Assembler assembler, bool debugEnabled, int stackOffsetToCheck) { if (stackOffsetToCheck != SignedAlign(stackOffsetToCheck, 4)) { throw new Exception("Stack offset not aligned!"); } if (debugEnabled) { if (!CompilerEngine.UseGen3Kernel) { XS.Compare(XSRegisters.ESP, 0, destinationDisplacement: (int)stackOffsetToCheck); XS.Jump(CPU.ConditionalTestEnum.NotEqual, ".AfterNullCheck"); XS.ClearInterruptFlag(); // don't remove the call. It seems pointless, but we need it to retrieve the EIP value XS.Call(".NullCheck_GetCurrAddress"); XS.Label(".NullCheck_GetCurrAddress"); XS.Pop(XSRegisters.EAX); new CPU.Mov { DestinationRef = ElementReference.New("DebugStub_CallerEIP"), DestinationIsIndirect = true, SourceReg = CPU.RegistersEnum.EAX }; XS.Call("DebugStub_SendNullReferenceOccurred"); } XS.Halt(); XS.Label(".AfterNullCheck"); } }
/* * * public static unsafe void Fill16Blocks( * byte *dest, [ebp + 8] * int value, [ebp + 12] * int BlocksNum) [ebp + 16] */ public override void AssembleNew(Assembler aAssembler, object aMethodInfo) { /* First we copy dest, value and DestSize from EBP (stack) to 3 different registers */ XS.Comment("Destination (int pointer)"); XS.Set(EAX, EBP, sourceDisplacement: DestDisplacement); XS.Comment("Value"); XS.Set(EBX, EBP, sourceDisplacement: ValueDisplacement); XS.Comment("BlocksNum"); XS.Set(ECX, EBP, sourceDisplacement: BlocksNumDisplacement); /* * Now we need to copy 'value' (EBX) to an SSE register but we should not simply do a copy (!) * but all the register with 'value' repeating! * That is in the 16 byte SSE register should go this repeating pattern: * |value|value|value|value * luckily we don't need to do a loop for this there is the SSE3 instruction for this shufps */ XS.SSE2.MoveD(XMM0, EBX); XS.SSE.Shufps(XMM0, XMM0, 0x0000); // This broadcast the first element of XMM0 on the other 3 /* Do the 'loop' */ XS.Xor(EDI, EDI); // EDI is 0 XS.Label(".loop"); //XS.SSE.MoveUPS(EAX, XMM0, destinationIsIndirect: true, destinationDisplacement: EDI); XS.LiteralCode("movups[EAX + EDI], XMM0"); XS.Add(EDI, 16); XS.Sub(ECX, 1); //XS.LiteralCode("jnz .loop"); XS.Jump(ConditionalTestEnum.NotZero, ".loop"); //XS.Return(); }
public override void Execute(MethodInfo aMethod, ILOpCode aOpCode) { // TODO overflow check for float var xType = aOpCode.StackPopTypes[0]; var xSize = SizeOfType(xType); var xIsFloat = TypeIsFloat(xType); if (xSize > 8) { //EmitNotImplementedException( Assembler, aServiceProvider, "Size '" + xSize.Size + "' not supported (add)", aCurrentLabel, aCurrentMethodInfo, aCurrentOffset, aNextLabel ); throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Add_Ovf_Un.cs->Error: StackSize > 8 not supported"); } else { var xBaseLabel = GetLabel(aMethod, aOpCode) + "."; var xSuccessLabel = xBaseLabel + "Success"; if (xSize > 4) { if (xIsFloat) { //TODO overflow check XS.FPU.FloatLoad(ESP, destinationIsIndirect: true, size: RegisterSize.Long64); XS.Add(ESP, 8); XS.FPU.FloatAdd(ESP, isIndirect: true, size: RegisterSize.Long64); XS.FPU.FloatStoreAndPop(ESP, isIndirect: true, size: RegisterSize.Long64); } else { XS.Pop(XSRegisters.EDX); // low part XS.Pop(XSRegisters.EAX); // high part XS.Add(ESP, EDX, destinationIsIndirect: true); XS.AddWithCarry(ESP, EAX, destinationDisplacement: 4); } } else { if (xIsFloat) //float { //TODO overflow check XS.SSE.MoveSS(XMM0, ESP, sourceIsIndirect: true); XS.Add(XSRegisters.ESP, 4); XS.SSE.MoveSS(XMM1, ESP, sourceIsIndirect: true); XS.SSE.AddSS(XMM0, XMM1); XS.SSE.MoveSS(XMM1, ESP, sourceIsIndirect: true); } else //integer { XS.Pop(XSRegisters.EAX); XS.Add(ESP, EAX, destinationIsIndirect: true); } } if (false == xIsFloat) { XS.Jump(ConditionalTestEnum.NotCarry, xSuccessLabel); ThrowOverflowException(); } XS.Label(xSuccessLabel); } }
public override void Execute(_MethodInfo aMethod, ILOpCode aOpCode) { XS.Pop(XSRegisters.ECX); // shift amount var xStackItem_ShiftAmount = aOpCode.StackPopTypes[0]; var xStackItem_Value = aOpCode.StackPopTypes[1]; var xStackItem_Value_Size = SizeOfType(xStackItem_Value); #if DOTNETCOMPATIBLE if (xStackItem_Value.Size == 4) #else if (xStackItem_Value_Size <= 4) #endif { XS.ShiftLeft(XSRegisters.ESP, XSRegisters.CL, destinationIsIndirect: true, size: RegisterSize.Int32); } #if DOTNETCOMPATIBLE else if (xStackItem_Value.Size == 8) #else else if (xStackItem_Value_Size <= 8) #endif { string BaseLabel = GetLabel(aMethod, aOpCode) + "."; string LowPartIsZero = BaseLabel + "LowPartIsZero"; string End_Shl = BaseLabel + "End_Shl"; // [ESP] is low part // [ESP + 4] is high part // move low part to eax XS.Set(EAX, ESP, sourceIsIndirect: true); XS.Compare(XSRegisters.CL, 32, size: RegisterSize.Byte8); XS.Jump(CPUx86.ConditionalTestEnum.AboveOrEqual, LowPartIsZero); // shift higher part XS.ShiftLeftDouble(ESP, EAX, CL, destinationDisplacement: 4); // shift lower part // To retain the sign bit we must use ShiftLeftArithmetic and not ShiftLeft! XS.ShiftLeftArithmetic(XSRegisters.ESP, XSRegisters.CL, destinationIsIndirect: true, size: RegisterSize.Int32); XS.Jump(End_Shl); XS.Label(LowPartIsZero); // remove bits >= 32, so that CL max value could be only 31 XS.And(XSRegisters.CL, 0x1f, size: RegisterSize.Byte8); // shift low part in EAX and move it in high part // To retain the sign bit we must use ShiftLeftArithmetic and not ShiftLeft! XS.ShiftLeftArithmetic(EAX, CL); XS.Set(ESP, EAX, destinationDisplacement: 4); // replace unknown low part with a zero, if <= 32 XS.Set(XSRegisters.ESP, 0, destinationIsIndirect: true); XS.Label(End_Shl); } else { throw new NotSupportedException("A size bigger 8 not supported at Shl!"); } }
public void CreateIDT() { new Comment(this, "BEGIN - Create IDT"); // Create IDT UInt16 xIdtSize = 8 * 256; DataMembers.Add(new DataMember("_NATIVE_IDT_Contents", new byte[xIdtSize])); // if (mComPort > 0) { if (!CompilerEngine.UseGen3Kernel) { SetIdtDescriptor(1, "DebugStub_TracerEntry", false); SetIdtDescriptor(3, "DebugStub_TracerEntry", false); } //for (int i = 0; i < 256; i++) //{ // if (i == 1 || i == 3) // { // continue; // } // SetIdtDescriptor(i, "DebugStub_Interrupt_" + i.ToString(), true); //} } //SetIdtDescriptor(1, "DebugStub_INT0"); - Change to GPF // Set IDT DataMembers.Add(new DataMember("_NATIVE_IDT_Pointer", new UInt16[] { xIdtSize, 0, 0 })); new Mov { DestinationRef = ElementReference.New("_NATIVE_IDT_Pointer"), DestinationIsIndirect = true, DestinationDisplacement = 2, SourceRef = ElementReference.New("_NATIVE_IDT_Contents") }; XS.Set(XSRegisters.EAX, "_NATIVE_IDT_Pointer"); if (mComPort > 0) { if (!CompilerEngine.UseGen3Kernel) { XS.Set("static_field__Cosmos_Core_CPU_mInterruptsEnabled", 1, destinationIsIndirect: true, size: RegisterSize.Byte8); XS.LoadIdt(XSRegisters.EAX, isIndirect: true); } } XS.Label("AfterCreateIDT"); new Comment(this, "END - Create IDT"); }
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())); XS.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 = ElementReference.New("_NATIVE_GDT_Pointer"), DestinationIsIndirect = true, DestinationDisplacement = 2, SourceRef = ElementReference.New("_NATIVE_GDT_Contents") }; XS.Set(XSRegisters.EAX, "_NATIVE_GDT_Pointer"); XS.LoadGdt(XSRegisters.EAX, isIndirect: true); XS.Comment("Set data segments"); XS.Set(XSRegisters.EAX, mGdData); XS.Set(XSRegisters.DS, XSRegisters.AX); XS.Set(XSRegisters.ES, XSRegisters.AX); XS.Set(XSRegisters.FS, XSRegisters.AX); XS.Set(XSRegisters.GS, XSRegisters.AX); XS.Set(XSRegisters.SS, XSRegisters.AX); XS.Comment("Force reload of code segment"); new JumpToSegment { Segment = mGdCode, DestinationLabel = "Boot_FlushCsGDT" }; XS.Label("Boot_FlushCsGDT"); new Comment(this, "END - Create GDT"); }
public override void AssembleNew(Assembler aAssembler, object aMethodInfo) { XS.ClearInterruptFlag(); XS.Set(XSRegisters.EAX, "_NATIVE_GDT_Pointer"); XS.LoadGdt(XSRegisters.EAX, isIndirect: true); XS.Set(XSRegisters.EAX, XSRegisters.CR0); XS.Or(XSRegisters.AL, 1); XS.Set(XSRegisters.CR0, XSRegisters.EAX); XS.JumpToSegment(0x08, "PMode"); XS.Label("PMode"); }
public override void AssembleNew(XSharp.Assembler.Assembler aAssembler, object aMethodInfo) { new LiteralAssemblerCode("%ifdef DEBUGSTUB"); XS.Label(".BeforeArgumentsPrepare"); new LiteralAssemblerCode("mov EBX, [EBP + 12]"); new LiteralAssemblerCode("push dword [EBX + 12]"); new LiteralAssemblerCode("add EBX, 16"); new LiteralAssemblerCode("push dword EBX"); XS.Label(".BeforeCall"); new LiteralAssemblerCode("Call DebugStub_SendText"); new LiteralAssemblerCode("add ESP, 8"); new LiteralAssemblerCode("%endif"); }
public void CreateIDT() { new Comment(this, "BEGIN - Create IDT"); // Create IDT ushort xIdtSize = 8 * 256; DataMembers.Add(new DataMember("_NATIVE_IDT_Contents", new byte[xIdtSize])); // if (mComPort > 0) { SetIdtDescriptor(1, AsmMarker.Labels[AsmMarker.Type.DebugStub_TracerEntry], false); SetIdtDescriptor(3, AsmMarker.Labels[AsmMarker.Type.DebugStub_TracerEntry], false); //for (int i = 0; i < 256; i++) //{ // if (i == 1 || i == 3) // { // continue; // } // SetIdtDescriptor(i, "DebugStub_Interrupt_" + i.ToString(), true); //} } //SetIdtDescriptor(1, "DebugStub_INT0"); - Change to GPF // Set IDT DataMembers.Add(new DataMember("_NATIVE_IDT_Pointer", new ushort[] { xIdtSize, 0, 0 })); new Mov { DestinationRef = ElementReference.New("_NATIVE_IDT_Pointer"), DestinationIsIndirect = true, DestinationDisplacement = 2, SourceRef = ElementReference.New("_NATIVE_IDT_Contents") }; XS.Set(EAX, "_NATIVE_IDT_Pointer"); if (mComPort > 0) { XS.Set(AsmMarker.Labels[AsmMarker.Type.Processor_IntsEnabled], 1, destinationIsIndirect: true, size: RegisterSize.Byte8); XS.LoadIdt(EAX, isIndirect: true); } XS.Label("AfterCreateIDT"); new Comment(this, "END - Create IDT"); }
public override void Execute(_MethodInfo aMethod, ILOpCode aOpCode) { OpType xType = (OpType)aOpCode; string xTypeID = GetTypeIDLabel(xType.Value); string xCurrentMethodLabel = GetLabel(aMethod, aOpCode); string xAfterIsInstanceCallLabel = xCurrentMethodLabel + "_After_IsInstance_Call"; string xReturnNullLabel = xCurrentMethodLabel + "_ReturnNull"; string xNextPositionLabel = GetLabel(aMethod, aOpCode.NextPosition); XS.Set(EAX, ESP, sourceDisplacement: 4); XS.Compare(EAX, 0); XS.Jump(CPUx86.ConditionalTestEnum.Zero, xReturnNullLabel); XS.Push(EAX, isIndirect: true); XS.Push(xTypeID, isIndirect: true); XS.Push(Convert.ToUInt32(xType.Value.IsInterface)); MethodBase xMethodIsInstance = VTablesImplRefs.IsInstanceRef; Call.DoExecute(Assembler, aMethod, xMethodIsInstance, aOpCode, xCurrentMethodLabel, xAfterIsInstanceCallLabel, DebugEnabled); XS.Label(xAfterIsInstanceCallLabel); XS.Pop(EAX); XS.Compare(EAX, 0); XS.Jump(CPUx86.ConditionalTestEnum.Equal, xReturnNullLabel); XS.Jump(xNextPositionLabel); XS.Label(xReturnNullLabel); XS.Add(ESP, 8); //string xAllocInfoLabelName = LabelName.Get( GCImplementationRefs.AllocNewObjectRef ); // TODO: Emit new exceptions //new Newobj( Assembler ).Execute( aMethod, aOpCode ); //Newobj.Assemble( Assembler, // typeof( InvalidCastException ).GetConstructor( new Type[ 0 ] ), // GetService<IMetaDataInfoService>().GetTypeIdLabel( typeof( InvalidCastException ) ), // mThisLabel, // mMethodInfo, // mCurrentILOffset, // mThisLabel + "_After_NewException", // GetService<IMetaDataInfoService>().GetTypeInfo( typeof( InvalidCastException ) ), // GetService<IMetaDataInfoService>().GetMethodInfo( typeof( InvalidCastException ).GetConstructor( new Type[ 0 ] ), false ), // GetServiceProvider(), // xAllocInfo.LabelName ); XS.Label(xCurrentMethodLabel + "_After_NewException"); //Call.EmitExceptionLogic( Assembler, ( uint )mCurrentILOffset, mMethodInfo, mNextOpLabel, false, null ); }
public override void Execute(MethodInfo aMethod, ILOpCode aOpCode) { string xCurrentMethodLabel = GetLabel(aMethod, aOpCode); OpType xType = ( OpType )aOpCode; string xTypeID = GetTypeIDLabel(xType.Value); //mTypeId = GetService<IMetaDataInfoService>().GetTypeIdLabel( mCastAsType ); // todo: throw an exception when the class does not support the cast! string mReturnNullLabel = xCurrentMethodLabel + "_ReturnNull"; XS.Set(XSRegisters.EAX, XSRegisters.ESP, sourceIsIndirect: true); XS.Compare(XSRegisters.EAX, 0); XS.Jump(CPU.ConditionalTestEnum.Zero, mReturnNullLabel); XS.Set(XSRegisters.EAX, XSRegisters.EAX, sourceIsIndirect: true); XS.Push(XSRegisters.EAX, isIndirect: true); XS.Push(xTypeID, isIndirect: true); MethodBase xMethodIsInstance = VTablesImplRefs.IsInstanceRef; // new OpMethod( ILOpCode.Code.Call, 0, 0, xMethodIsInstance, aOpCode.CurrentExceptionHandler ) ); Call.DoExecute(Assembler, aMethod, xMethodIsInstance, aOpCode, xCurrentMethodLabel, xCurrentMethodLabel + "_After_IsInstance_Call", DebugEnabled); XS.Label(xCurrentMethodLabel + "_After_IsInstance_Call"); XS.Pop(XSRegisters.EAX); XS.Compare(XSRegisters.EAX, 0); XS.Jump(CPU.ConditionalTestEnum.Equal, mReturnNullLabel); new CPU.Jump { DestinationLabel = GetLabel(aMethod, aOpCode.NextPosition) }; XS.Label(mReturnNullLabel); XS.Add(XSRegisters.ESP, 4); //string xAllocInfoLabelName = LabelName.Get( GCImplementationRefs.AllocNewObjectRef ); #warning TODO: Emit new exceptions //new Newobj( Assembler ).Execute( aMethod, aOpCode ); //Newobj.Assemble( Assembler, // typeof( InvalidCastException ).GetConstructor( new Type[ 0 ] ), // GetService<IMetaDataInfoService>().GetTypeIdLabel( typeof( InvalidCastException ) ), // mThisLabel, // mMethodInfo, // mCurrentILOffset, // mThisLabel + "_After_NewException", // GetService<IMetaDataInfoService>().GetTypeInfo( typeof( InvalidCastException ) ), // GetService<IMetaDataInfoService>().GetMethodInfo( typeof( InvalidCastException ).GetConstructor( new Type[ 0 ] ), false ), // GetServiceProvider(), // xAllocInfo.LabelName ); XS.Label(xCurrentMethodLabel + "_After_NewException"); //Call.EmitExceptionLogic( Assembler, ( uint )mCurrentILOffset, mMethodInfo, mNextOpLabel, false, null ); }
public override void Execute(_MethodInfo aMethod, ILOpCode aOpCode) { // TODO overflow check for float var xType = aOpCode.StackPopTypes[0]; var xSize = SizeOfType(xType); var xIsFloat = TypeIsFloat(xType); if (xIsFloat) { throw new Exception("Cosmos.IL2CPU.x86->IL->Add_Ovf_Un.cs->Error: Expected unsigned integer operands but get float!"); } if (xSize > 8) { //EmitNotImplementedException( Assembler, aServiceProvider, "Size '" + xSize.Size + "' not supported (add)", aCurrentLabel, aCurrentMethodInfo, aCurrentOffset, aNextLabel ); throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Add_Ovf_Un.cs->Error: StackSize > 8 not supported"); } else { var xBaseLabel = GetLabel(aMethod, aOpCode) + "."; var xSuccessLabel = xBaseLabel + "Success"; if (xSize > 4) // long { XS.Pop(EDX); // low part XS.Pop(EAX); // high part XS.Sub(ESP, EDX, destinationIsIndirect: true); XS.SubWithCarry(ESP, EAX, destinationDisplacement: 4); } else //integer { XS.Pop(EAX); XS.Sub(ESP, EAX, destinationIsIndirect: true); } // Let's check if we add overflow and if so throw OverflowException XS.Jump(ConditionalTestEnum.NotCarry, xSuccessLabel); if (xSize > 4) // Hack to stop stack corruption { XS.Add(ESP, 8); } else { XS.Add(ESP, 4); } Call.DoExecute(Assembler, aMethod, typeof(ExceptionHelper).GetMethod("ThrowOverflow", BindingFlags.Static | BindingFlags.Public), aOpCode, GetLabel(aMethod, aOpCode), xSuccessLabel, DebugEnabled); XS.Label(xSuccessLabel); } }
public override void Execute(_MethodInfo aMethod, ILOpCode aOpCode) { var xType = aOpCode.StackPopTypes[0]; var xSize = SizeOfType(xType); var xIsFloat = TypeIsFloat(xType); if (xIsFloat) { throw new Exception("Cosmos.IL2CPU.x86->IL->Sub_Ovf.cs->Error: Expected signed integer operands but get float!"); } if (xSize > 8) { throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Sub_Ovf.cs->Error: StackSize > 8 not supported"); } else { var xBaseLabel = GetLabel(aMethod, aOpCode) + "."; var xSuccessLabel = xBaseLabel + "Success"; if (xSize > 4) // long { XS.Pop(EAX); //low part XS.Pop(EDX); //high part XS.Sub(ESP, EAX, destinationIsIndirect: true); XS.SubWithCarry(ESP, EDX, destinationDisplacement: 4); } else //integer { XS.Pop(ECX);//first integer XS.Pop(EAX); //second integer XS.Sub(EAX, ECX); XS.Push(EAX); //push result on stack } // Let's check if we add overflow and if so throw OverflowException XS.Jump(ConditionalTestEnum.NoOverflow, xSuccessLabel); if (xSize > 4) // Hack to stop stack corruption { XS.Add(ESP, 8); } else { XS.Add(ESP, 4); } Call.DoExecute(Assembler, aMethod, typeof(ExceptionHelper).GetMethod("ThrowOverflow", BindingFlags.Static | BindingFlags.Public), aOpCode, GetLabel(aMethod, aOpCode), xSuccessLabel, DebugEnabled); XS.Label(xSuccessLabel); } }
public static void DoExecute(Cosmos.Assembler.Assembler assembler, _MethodInfo aMethod, string field, Type declaringType, ILOpCode aCurrentOpCode) { // call cctor: var xCctor = (declaringType.GetConstructors(BindingFlags.Static | BindingFlags.NonPublic) ?? new ConstructorInfo[0]).SingleOrDefault(); if (xCctor != null) { XS.Call(LabelName.Get(xCctor)); if (aCurrentOpCode != null) { ILOp.EmitExceptionLogic(assembler, aMethod, aCurrentOpCode, true, null, ".AfterCCTorExceptionCheck"); XS.Label(".AfterCCTorExceptionCheck"); } } string xDataName = field; XS.Push(xDataName); }
public override void Execute(_MethodInfo aMethod, ILOpCode aOpCode) { DoNullReferenceCheck(Assembler, DebugEnabled, 0); var xType = ((OpType)aOpCode).Value; string xBaseLabel = GetLabel(aMethod, aOpCode) + "."; string xTypeID = GetTypeIDLabel(xType); uint xTypeSize = SizeOfType(xType); string mReturnNullLabel = xBaseLabel + "_ReturnNull"; XS.Compare(XSRegisters.ESP, 0, destinationIsIndirect: true); XS.Jump(CPU.ConditionalTestEnum.Zero, mReturnNullLabel); XS.Set(XSRegisters.EAX, XSRegisters.ESP, sourceIsIndirect: true); XS.Push(XSRegisters.EAX, isIndirect: true); XS.Push(xTypeID, isIndirect: true); XS.Push(Convert.ToUInt32(xType.IsInterface)); Call.DoExecute(Assembler, aMethod, VTablesImplRefs.IsInstanceRef, aOpCode, GetLabel(aMethod, aOpCode), xBaseLabel + "_After_IsInstance_Call", DebugEnabled); XS.Label(xBaseLabel + "_After_IsInstance_Call"); XS.Pop(XSRegisters.EAX); XS.Compare(XSRegisters.EAX, 0); XS.Jump(CPU.ConditionalTestEnum.Equal, mReturnNullLabel); XS.Pop(XSRegisters.EAX); uint xSize = xTypeSize; if (xSize % 4 > 0) { xSize += 4 - (xSize % 4); } int xItems = (int)xSize / 4; for (int i = xItems - 1; i >= 0; i--) { new CPU.Push { DestinationReg = CPU.RegistersEnum.EAX, DestinationIsIndirect = true, DestinationDisplacement = ((i * 4) + ObjectUtils.FieldDataOffset) }; } new CPU.Jump { DestinationLabel = GetLabel(aMethod, aOpCode.NextPosition) }; XS.Label(mReturnNullLabel); XS.Add(XSRegisters.ESP, 4); XS.Push(0); }
public static void Assemble(XSharp.Assembler.Assembler aAssembler, OpType aOpType, uint aElementSize, bool debugEnabled, _MethodInfo aMethod, ILOpCode aOpCode) { XS.Comment("Arraytype: " + aOpType.StackPopTypes.Last().FullName); XS.Comment("Size: " + aElementSize); DoNullReferenceCheck(aAssembler, debugEnabled, 8); //Do check for index out of range var xBaseLabel = GetLabel(aMethod, aOpCode); var xNoIndexOutOfRangeExeptionLabel = xBaseLabel + "_NoIndexOutOfRangeException"; var xIndexOutOfRangeExeptionLabel = xBaseLabel + "_IndexOutOfRangeException"; XS.Pop(EBX); //get Position _, array, 0, index -> _, array, 0 XS.Push(ESP, true, 4); // _, array, 0 => _, array, 0, array XS.Push(ESP, true, 12); // _, array, 0, array => _, array, 0, array, 0 Ldlen.Assemble(aAssembler, debugEnabled, false); // _, array, 0, array, 0 -> _, array, 0, length XS.Pop(EAX); //Length of array _, array, 0, length -> _, array, 0 XS.Compare(EAX, EBX); XS.Jump(CPUx86.ConditionalTestEnum.LessThanOrEqualTo, xIndexOutOfRangeExeptionLabel); XS.Compare(EBX, 0); XS.Jump(CPUx86.ConditionalTestEnum.GreaterThanOrEqualTo, xNoIndexOutOfRangeExeptionLabel); XS.Label(xIndexOutOfRangeExeptionLabel); XS.Pop(EAX); XS.Pop(EAX); Call.DoExecute(aAssembler, aMethod, ExceptionHelperRefs.ThrowIndexOutOfRangeException, aOpCode, xNoIndexOutOfRangeExeptionLabel, debugEnabled); XS.Label(xNoIndexOutOfRangeExeptionLabel); XS.Push(EBX); //_, array, 0 -> _, array, 0, index // calculate element offset into array memory (including header) XS.Pop(EAX); XS.Set(EDX, aElementSize); XS.Multiply(EDX); XS.Add(EAX, (uint)(ObjectUtils.FieldDataOffset + 4)); // pop the array now XS.Add(ESP, 4); XS.Pop(EDX); XS.Add(EDX, EAX); XS.Push(EDX); }
public override void AssembleNew(Assembler.Assembler aAssembler, object aMethodInfo) { XS.ClearDirectionFlag(); XS.Set(XSRegisters.EDI, XSRegisters.EBP, sourceDisplacement: 0xC); //address XS.Set(XSRegisters.ECX, XSRegisters.EBP, sourceDisplacement: 0x8); //length // set EAX to value of fill (zero) XS.Xor(XSRegisters.EAX, XSRegisters.EAX); XS.ShiftRight(XSRegisters.ECX, 1); XS.Jump(Assembler.x86.ConditionalTestEnum.NotBelow, ".step2"); XS.StoreByteInString(); XS.Label(".step2"); XS.ShiftRight(XSRegisters.ECX, 1); XS.Jump(Assembler.x86.ConditionalTestEnum.NotBelow, ".step3"); XS.StoreWordInString(); XS.Label(".step3"); new Assembler.x86.Stos { Size = 32, Prefixes = Assembler.x86.InstructionPrefixes.Repeat }; }
public override void Execute(_MethodInfo aMethod, ILOpCode aOpCode) { var xType = (ILOpCodes.OpType)aOpCode; uint xSize = SizeOfType(xType.Value.GetElementType() ?? xType.Value); string xTypeID = GetTypeIDLabel(xType.Value.GetElementType() ?? xType.Value); MethodBase xCtor = typeof(Array).GetConstructors(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance)[0]; string xCtorName = LabelName.Get(xCtor); XS.Comment("Element Size = " + xSize); XS.Pop(EAX); // element count XS.Push(EAX); XS.Set(EDX, xSize); XS.Multiply(EDX); // total element size XS.Add(EAX, ObjectUtils.FieldDataOffset + 4); // total array size XS.Push(EAX); //XS.Push(0x4E3A44A9); //XS.LiteralCode("Call DebugStub_SendSimpleNumber"); //XS.Pop(EAX); //XS.Push(".AfterAlloc"); //XS.LiteralCode("Call DebugStub_SendSimpleNumber"); //XS.Pop(EAX); XS.Call(LabelName.Get(GCImplementationRefs.AllocNewObjectRef)); XS.Label(".AfterAlloc"); XS.Pop(EAX); // location //XS.LiteralCode("Call DebugStub_SendSimpleNumber"); XS.Pop(ESI); // element count XS.Push(EAX); XS.Push(ESP, isIndirect: true); XS.Push(ESP, isIndirect: true); // it's on the stack 3 times now, once from the return value, twice from the pushes; XS.Pop(EAX); XS.Set(EBX, xTypeID, sourceIsIndirect: true); // array type id XS.Set(EAX, EBX, destinationIsIndirect: true); // array type id XS.Set(EAX, (uint)ObjectUtils.InstanceTypeEnum.Array, destinationDisplacement: 4, destinationIsIndirect: true); XS.Set(EAX, ESI, destinationDisplacement: 8, destinationIsIndirect: true); // element count XS.Set(EAX, xSize, destinationDisplacement: 12, destinationIsIndirect: true); // element size XS.Push(0); XS.Call(xCtorName); XS.Push(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) { XS.Pop(XSRegisters.EAX); // shift amount XS.Pop(XSRegisters.EBX); // value XS.Set(XSRegisters.CL, XSRegisters.AL); XS.ShiftRight(XSRegisters.EBX, CL); XS.Push(XSRegisters.EBX); return; } if (xStackItem_Value_Size <= 8) { XS.Pop(XSRegisters.EDX); XS.Set(XSRegisters.EAX, 0); XS.Label(xBaseLabel + "__StartLoop"); XS.Compare(XSRegisters.EDX, XSRegisters.EAX); XS.Jump(CPUx86.ConditionalTestEnum.Equal, xBaseLabel + "__EndLoop"); XS.Set(EBX, ESP, sourceIsIndirect: true); XS.Set(XSRegisters.CL, 1); XS.ShiftRight(XSRegisters.EBX, CL); XS.Set(ESP, EBX, destinationIsIndirect: true); XS.Set(XSRegisters.CL, 1); XS.RotateThroughCarryRight(ESP, CL, destinationDisplacement: 4, size: RegisterSize.Int32); XS.Add(XSRegisters.EAX, 1); new CPUx86.Jump { DestinationLabel = xBaseLabel + "__StartLoop" }; XS.Label(xBaseLabel + "__EndLoop"); return; } }
public static void CheckOverflowForSmall(uint xResultSize, bool xSourceIsSigned, bool xResultIsSigned, Assembler assembler, _MethodInfo aMethod, ILOpCode aOpCode, string xSuccessLabel, string xOverflowLabel) { XS.Set(EAX, ESP, sourceIsIndirect: true); // only look at bits which are part of result // normally check that they are all either 0 or 1 // if same size but casting between signed and unsigned, then first bit must be zero byte bitCount = (byte)((xResultSize) * 8 - 1); XS.ShiftRight(EAX, bitCount); XS.Compare(EAX, 0); XS.Jump(ConditionalTestEnum.Equal, xSuccessLabel); if (xSourceIsSigned) { if (xResultIsSigned) { XS.Not(EAX); // if negative then all must be 1s XS.Compare(EAX, 0); XS.Jump(ConditionalTestEnum.Equal, xSuccessLabel); } else { XS.Jump(xOverflowLabel); } } else // source was unsigned { if (xResultIsSigned) { XS.Jump(xOverflowLabel); //too big } else { XS.Compare(EAX, 1); // only lowest bit is set, which is heighest of next XS.Jump(ConditionalTestEnum.Equal, xSuccessLabel); } } XS.Label(xOverflowLabel); XS.Pop(EAX); // clear stack Call.DoExecute(assembler, aMethod, ExceptionHelperRefs.ThrowOverflowExceptionRef, aOpCode, xSuccessLabel, false); XS.Label(xSuccessLabel); }
// unsafe private static void Copy128Bytes(byte* dest, byte* src, int blocksNum) public override void AssembleNew(Assembler aAssembler, object aMethodInfo) { XS.Comment("CALLED!"); // Copy Src to ESI XS.Set(ESI, EBP, sourceIsIndirect: true, sourceDisplacement: SrcDisplacement); // Copy Dst to EDI XS.Set(EDI, EBP, sourceIsIndirect: true, sourceDisplacement: DestDisplacement); // Copy BlocksNum to ECX XS.Set(ECX, EBP, sourceDisplacement: BlocksNumDisplacement); /* Do the 'loop' */ XS.Label(".loop"); // move 128 bytes of src to 8 XMM register XS.SSE.MoveDQU(XMM0, ESI, sourceIsIndirect: true); XS.SSE.MoveDQU(XMM1, ESI, sourceIsIndirect: true, sourceDisplacement: 16); XS.SSE.MoveDQU(XMM2, ESI, sourceIsIndirect: true, sourceDisplacement: 32); XS.SSE.MoveDQU(XMM3, ESI, sourceIsIndirect: true, sourceDisplacement: 48); XS.SSE.MoveDQU(XMM4, ESI, sourceIsIndirect: true, sourceDisplacement: 64); XS.SSE.MoveDQU(XMM5, ESI, sourceIsIndirect: true, sourceDisplacement: 80); XS.SSE.MoveDQU(XMM6, ESI, sourceIsIndirect: true, sourceDisplacement: 96); XS.SSE.MoveDQU(XMM7, ESI, sourceIsIndirect: true, sourceDisplacement: 112); // move 128 bytes from the 8 XMM registers to dest XS.SSE.MoveDQU(EDI, XMM0, destinationIsIndirect: true); XS.SSE.MoveDQU(EDI, XMM1, destinationIsIndirect: true, destinationDisplacement: 16); XS.SSE.MoveDQU(EDI, XMM2, destinationIsIndirect: true, destinationDisplacement: 32); XS.SSE.MoveDQU(EDI, XMM3, destinationIsIndirect: true, destinationDisplacement: 48); XS.SSE.MoveDQU(EDI, XMM4, destinationIsIndirect: true, destinationDisplacement: 64); XS.SSE.MoveDQU(EDI, XMM5, destinationIsIndirect: true, destinationDisplacement: 80); XS.SSE.MoveDQU(EDI, XMM6, destinationIsIndirect: true, destinationDisplacement: 96); XS.SSE.MoveDQU(EDI, XMM7, destinationIsIndirect: true, destinationDisplacement: 112); XS.Add(ESI, 128); XS.Add(EDI, 128); XS.Sub(ECX, 1); XS.Jump(ConditionalTestEnum.NotZero, ".loop"); }
public override void Execute(_MethodInfo aMethod, ILOpCode aOpCode) { //TODO: What if the last ILOp in a method was Conv_Ovf_I_Un or an other? var xSource = aOpCode.StackPopTypes[0]; var xSourceSize = SizeOfType(xSource); var xSourceIsFloat = TypeIsFloat(xSource); if (xSourceIsFloat) { ThrowNotImplementedException("Conv_Ovf_I_Un throws an ArgumentException, because float is not implemented!"); } switch (xSourceSize) { case 1: case 2: case 4: break; case 8: { string NoOverflowLabel = GetLabel(aMethod, aOpCode) + "__NoOverflow"; XS.Pop(XSRegisters.EAX); // EBX is high part and should be zero for unsigned, so we test it on zero { XS.Pop(XSRegisters.EBX); XS.Compare(XSRegisters.EBX, 0); XS.Jump(CPUx86.ConditionalTestEnum.Equal, NoOverflowLabel); ThrowNotImplementedException("Conv_Ovf_I_Un throws an overflow exception, which is not implemented!"); } XS.Label(NoOverflowLabel); XS.Push(XSRegisters.EAX); break; } default: ThrowNotImplementedException("Conv_Ovf_I_Un not implemented for this size!"); break; } }
public override void Execute(_MethodInfo aMethod, ILOpCode aOpCode) { var xType = aOpCode.StackPopTypes[0]; var xSize = SizeOfType(xType); var xIsFloat = TypeIsFloat(xType); if (xIsFloat) { throw new Exception("Cosmos.IL2CPU.x86->IL->Add_Ovf.cs->Error: Expected signed integer operands but get float!"); } if (xSize > 8) { //EmitNotImplementedException( Assembler, aServiceProvider, "Size '" + xSize.Size + "' not supported (add)", aCurrentLabel, aCurrentMethodInfo, aCurrentOffset, aNextLabel ); throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Add_Ovf.cs->Error: StackSize > 8 not supported"); } else { var xBaseLabel = GetLabel(aMethod, aOpCode) + "."; var xSuccessLabel = xBaseLabel + "Success"; if (xSize > 4) // long { XS.Pop(EDX); // low part XS.Pop(EAX); // high part XS.Add(ESP, EDX, destinationIsIndirect: true); XS.AddWithCarry(ESP, EAX, destinationDisplacement: 4); } else //integer { XS.Pop(EAX); XS.Add(ESP, EAX, destinationIsIndirect: true); } // Let's check if we add overflow and if so throw OverflowException XS.Jump(ConditionalTestEnum.NoOverflow, xSuccessLabel); ThrowOverflowException(); XS.Label(xSuccessLabel); } }
public static void DoExecute(uint xSourceSize, bool SourceIsSigned, Assembler assembler, _MethodInfo aMethod, ILOpCode aOpCode) { var xBaseLabel = GetLabel(aMethod, aOpCode) + "."; var xSuccessLabel = xBaseLabel + "Success"; switch (xSourceSize) { case 1: case 2: case 4: XS.Pop(EAX); XS.SignExtendAX(RegisterSize.Int32); XS.Push(EDX); XS.Push(EAX); break; case 8: if (SourceIsSigned) { XS.Set(EAX, ESP, sourceIsIndirect: true); XS.And(EAX, 0b1000000000000000000000000000); XS.Compare(EAX, 0); XS.Jump(XSharp.Assembler.x86.ConditionalTestEnum.Equal, xSuccessLabel); XS.Pop(EAX); // remove long from stack XS.Pop(EAX); Call.DoExecute(assembler, aMethod, ExceptionHelperRefs.ThrowOverflowExceptionRef, aOpCode, xSuccessLabel, false); XS.Label(xSuccessLabel); } else { XS.Noop(); } break; default: throw new NotImplementedException(); } }