public override void Execute( MethodInfo aMethod, ILOpCode aOpCode ) { OpType xType = ( OpType )aOpCode; string xTypeID = GetTypeIDLabel(xType.Value); string mReturnNullLabel = GetLabel( aMethod, aOpCode ) + "_ReturnNull"; new CPUx86.Mov { DestinationReg = CPUx86.Registers.EAX, SourceReg = CPUx86.Registers.ESP, SourceIsIndirect = true }; new CPUx86.Compare { DestinationReg = CPUx86.Registers.EAX, SourceValue = 0 }; new CPUx86.ConditionalJump { Condition = CPUx86.ConditionalTestEnum.Zero, DestinationLabel = mReturnNullLabel }; // EAX contains a memory handle now. Lets convert it to a pointer new CPUx86.Mov { DestinationReg = CPUx86.Registers.EAX, SourceReg = CPUx86.Registers.EAX, SourceIsIndirect = true }; //new CPUx86.Mov {DestinationReg = CPUx86.Registers.EAX, SourceReg = CPUx86.Registers.EAX, SourceIsIndirect = true}; new CPUx86.Push { DestinationReg = CPUx86.Registers.EAX, DestinationIsIndirect = true }; new CPUx86.Push { DestinationRef = Cosmos.Assembler.ElementReference.New( xTypeID ), DestinationIsIndirect = 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" ); new CPUx86.Pop { DestinationReg = CPUx86.Registers.EAX }; new CPUx86.Compare { DestinationReg = CPUx86.Registers.EAX, SourceValue = 0 }; new CPUx86.ConditionalJump { Condition = CPUx86.ConditionalTestEnum.Equal, DestinationLabel = mReturnNullLabel }; // push nothing now, as we should return the object instance pointer. new CPUx86.Jump { DestinationLabel = GetLabel(aMethod, aOpCode.NextPosition) }; new Label( mReturnNullLabel ); new CPUx86.Add { DestinationReg = CPUx86.Registers.ESP, SourceValue = 4 }; new CPUx86.Push { DestinationValue = 0 }; }
public override void Execute( MethodInfo aMethod, ILOpCode aOpCode ) { var xStackContent = aOpCode.StackPopTypes[0]; var xStackContentSecond = aOpCode.StackPopTypes[1]; var xStackContentSize = SizeOfType(xStackContent); var xStackContentSecondSize = SizeOfType(xStackContentSecond); var xSize = Math.Max(xStackContentSize, xStackContentSecondSize); if (ILOp.Align(xStackContentSize, 4u) != ILOp.Align(xStackContentSecondSize, 4u)) { throw new NotSupportedException("Operands have different size!"); } if (xSize > 8) { throw new NotImplementedException("StackSize>8 not supported"); } if (xSize > 4) { // [ESP] is low part // [ESP + 4] is high part // [ESP + 8] is low part // [ESP + 12] is high part XS.Pop(XSRegisters.EAX); XS.Pop(XSRegisters.EDX); // [ESP] is low part // [ESP + 4] is high part XS.Or(XSRegisters.ESP, XSRegisters.EAX, destinationIsIndirect: true); XS.Or(XSRegisters.ESP, XSRegisters.EDX, destinationDisplacement: 4); } else { XS.Pop(XSRegisters.EAX); XS.Or(XSRegisters.ESP, XSRegisters.EAX, destinationIsIndirect: true); } }
public override void Execute( MethodInfo aMethod, ILOpCode aOpCode ) { DoNullReferenceCheck(Assembler, DebugEnabled, 0); new CPUx86.Pop { DestinationReg = CPUx86.Registers.ECX }; new CPUx86.MoveZeroExtend { DestinationReg = CPUx86.Registers.EAX, Size = 16, SourceReg = CPUx86.Registers.ECX, SourceIsIndirect = true }; new CPUx86.Push { DestinationReg = CPUx86.Registers.EAX }; }
public override void Execute( MethodInfo aMethod, ILOpCode aOpCode ) { OpToken xToken = ( OpToken )aOpCode; string xTokenAddress = null; if (xToken.ValueIsType) { xTokenAddress = ILOp.GetTypeIDLabel(xToken.ValueType); } if (xToken.ValueIsField) { xTokenAddress= DataMember.GetStaticFieldName(xToken.ValueField); } if (String.IsNullOrEmpty(xTokenAddress)) { throw new Exception("Ldtoken not implemented!"); } //if( mType != null ) //{ // mTokenAddress = GetService<IMetaDataInfoService>().GetTypeIdLabel( mType ); //} //XS.Push(xToken.Value); XS.Push(xTokenAddress); XS.Push(0); }
public override void Execute( MethodInfo aMethod, ILOpCode aOpCode ) { DoNullReferenceCheck(Assembler, DebugEnabled, 0); XS.Pop(XSRegisters.ECX); new CPUx86.MoveSignExtend { DestinationReg = CPUx86.RegistersEnum.EAX, Size = 8, SourceReg = CPUx86.RegistersEnum.ECX, SourceIsIndirect = true }; XS.Push(XSRegisters.EAX); }
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"; new CPUx86.Pop { DestinationReg = CPUx86.Registers.EAX }; // EBX is high part and should be zero for unsigned, so we test it on zero { new CPUx86.Pop { DestinationReg = CPUx86.Registers.EBX }; new CPUx86.Compare { DestinationReg = CPUx86.Registers.EBX, SourceValue = 0 }; new CPUx86.ConditionalJump { Condition = CPUx86.ConditionalTestEnum.Equal, DestinationLabel = NoOverflowLabel }; ThrowNotImplementedException("Conv_Ovf_I_Un throws an overflow exception, which is not implemented!"); } new Label(NoOverflowLabel); new CPUx86.Push { DestinationReg = CPUx86.Registers.EAX }; break; } default: ThrowNotImplementedException("Conv_Ovf_I_Un not implemented for this size!"); break; } }
public override void Execute( MethodInfo aMethod, ILOpCode aOpCode ) { var xValue = aOpCode.StackPopTypes[0]; var xValueIsFloat = TypeIsFloat(xValue); var xValueSize = SizeOfType(xValue); if (xValueSize > 8) { //EmitNotImplementedException( Assembler, aServiceProvider, "Size '" + xSize.Size + "' not supported (add)", aCurrentLabel, aCurrentMethodInfo, aCurrentOffset, aNextLabel ); throw new NotImplementedException(); } //TODO if on stack a float it is first truncated, http://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.conv_r_un.aspx if (!xValueIsFloat) { switch (xValueSize) { case 1: case 2: case 4: new CPUx86.Mov { SourceReg = CPUx86.RegistersEnum.ESP, DestinationReg = CPUx86.RegistersEnum.EAX, SourceIsIndirect = true }; XS.SSE.ConvertSI2SS(XSRegisters.XMM0, XSRegisters.EAX); XS.SSE.MoveSS(XSRegisters.ESP, XSRegisters.XMM0, destinationIsIndirect: true); break; case 8: //XS.Add(XSRegisters.ESP, 4); //break; default: //EmitNotImplementedException( Assembler, GetServiceProvider(), "Conv_I: SourceSize " + xSource + " not supported!", mCurLabel, mMethodInformation, mCurOffset, mNextLabel ); throw new NotImplementedException(); } } else { throw new NotImplementedException(); } }
public override void Execute(MethodInfo aMethod, ILOpCode aOpCode) { var xStackContent = aOpCode.StackPopTypes[0]; var xStackContentSize = SizeOfType(xStackContent); string BaseLabel = GetLabel(aMethod, aOpCode) + "."; DoExecute(xStackContentSize, BaseLabel); }
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 xSource = aOpCode.StackPopTypes[0]; var xSourceSize = SizeOfType(xSource); switch (xSourceSize) { case 1: case 2: case 4: if (TypeIsFloat(xSource)) { new CPUx86.SSE.ConvertSS2SD { DestinationReg = CPUx86.Registers.XMM0, SourceReg = CPUx86.Registers.ESP, SourceIsIndirect = true }; } else { new CPUx86.SSE.ConvertSI2SD { DestinationReg = CPUx86.Registers.XMM0, SourceReg = CPUx86.Registers.ESP, SourceIsIndirect = true }; } // expand stack, that moved data is valid stack new CPUx86.Sub { DestinationReg = CPUx86.Registers.ESP, SourceValue = 4 }; new CPUx86.SSE.MoveSD { DestinationReg = CPUx86.Registers.ESP, DestinationIsIndirect = true, SourceReg = CPUx86.Registers.XMM0 }; break; case 8: { if (!TypeIsFloat(xSource)) { new CPUx86.x87.IntLoad { DestinationReg = CPUx86.Registers.ESP, Size = 64, DestinationIsIndirect = true }; new CPUx86.x87.FloatStoreAndPop { DestinationReg = CPUx86.Registers.ESP, Size = 64, DestinationIsIndirect = true}; } break; } default: //EmitNotImplementedException( Assembler, GetServiceProvider(), "Conv_U8: SourceSize " + xSource + " not supported!", mCurLabel, mMethodInformation, mCurOffset, mNextLabel ); throw new NotImplementedException(); } }
public override void Execute( MethodInfo aMethod, ILOpCode aOpCode ) { var xFieldSize = SizeOfType(aOpCode.StackPopTypes[0]); var xRoundedSize = Align(xFieldSize, 4); DoNullReferenceCheck(Assembler, DebugEnabled, xRoundedSize); new CPUx86.Mov { DestinationReg = CPUx86.Registers.ECX, SourceReg = CPUx86.Registers.ESP, SourceIsIndirect = true, SourceDisplacement = checked((int)xRoundedSize) }; for( int i = 0; i < ( xFieldSize / 4 ); i++ ) { new CPUx86.Pop { DestinationReg = CPUx86.Registers.EAX }; new CPUx86.Mov { DestinationReg = CPUx86.Registers.ECX, DestinationIsIndirect = true, DestinationDisplacement = i * 4, SourceReg = CPUx86.Registers.EAX }; } switch( xFieldSize % 4 ) { case 1: { new CPUx86.Pop { DestinationReg = CPUx86.Registers.EAX }; new CPUx86.Mov { DestinationReg = CPUx86.Registers.ECX, DestinationIsIndirect = true, DestinationDisplacement = checked((int)( xFieldSize / 4 ) * 4 ), SourceReg = CPUx86.Registers.AL }; break; } case 2: { new CPUx86.Pop { DestinationReg = CPUx86.Registers.EAX }; new CPUx86.Mov { DestinationReg = CPUx86.Registers.ECX, DestinationIsIndirect = true, DestinationDisplacement = checked((int)( xFieldSize / 4 ) * 4 ), SourceReg = CPUx86.Registers.AX }; break; } case 0: { break; } default: throw new Exception( "Remainder size " + ( xFieldSize % 4 ) + " not supported!" ); } new CPUx86.Add { DestinationReg = CPUx86.Registers.ESP, SourceValue = 4 }; }
public override void Execute(MethodInfo aMethod, ILOpCode aOpCode) { OpDouble xOp = (OpDouble)aOpCode; byte[] xBytes = BitConverter.GetBytes(xOp.Value); new CPU.Push { DestinationValue = BitConverter.ToUInt32(xBytes, 4) }; new CPU.Push { DestinationValue = BitConverter.ToUInt32(xBytes, 0) }; }
public override void Execute( MethodInfo aMethod, ILOpCode aOpCode ) { DoNullReferenceCheck(Assembler, DebugEnabled, 0); new CPUx86.Pop { DestinationReg = CPUx86.Registers.EAX }; new CPUx86.Add { DestinationReg = CPUx86.Registers.EAX, SourceValue = 8 }; new CPUx86.Push { DestinationReg = CPUx86.Registers.EAX, DestinationIsIndirect = true }; }
public override void Execute(MethodInfo aMethod, ILOpCode aOpCode) { //TODO: Return Jump_End(aMethod); // Need to jump to end of method. Assembler can emit this label for now //XS.Jump(MethodFooterOp.EndOfMethodLabelNameNormal); }
public override void Execute(MethodInfo aMethod, ILOpCode aOpCode) { var xSource = aOpCode.StackPopTypes[0]; var xSourceSize = SizeOfType(xSource); switch (xSourceSize) { case 1: case 2: case 4: if (TypeIsFloat(xSource)) { XS.SSE.ConvertSS2SD(XMM0, ESP, sourceIsIndirect: true); } else { XS.SSE2.ConvertSI2SD(XMM0, ESP, sourceIsIndirect: true); } // expand stack, that moved data is valid stack XS.Sub(XSRegisters.ESP, 4); XS.SSE2.MoveSD(ESP, XMM0, destinationIsIndirect: true); break; case 8: { if (!TypeIsFloat(xSource)) { XS.FPU.IntLoad(ESP, isIndirect: true, size: RegisterSize.Long64); XS.FPU.FloatStoreAndPop(ESP, isIndirect: true, size: RegisterSize.Long64); } break; } default: //EmitNotImplementedException( Assembler, GetServiceProvider(), "Conv_U8: SourceSize " + xSource + " not supported!", mCurLabel, mMethodInformation, mCurOffset, mNextLabel ); throw new NotImplementedException(); } }
public override void Execute(MethodInfo aMethod, ILOpCode aOpCode) { var xOpString = aOpCode as OpString; string xDataName = GetContentsArrayName(xOpString.Value); new Comment(Assembler, "String Value: " + xOpString.Value.Replace("\r", "\\r").Replace("\n", "\\n")); var xRefName = GetFakeHandleForLiteralArray(xDataName); new Mov { DestinationReg = RegistersEnum.EAX, SourceRef = Cosmos.Assembler.ElementReference.New(xRefName) }; new Push { DestinationReg = RegistersEnum.EAX }; // DEBUG VERIFICATION: leave it here for now. we have issues with fields ordering. // if that changes, we need to change the code below! // We also need to change the debugstub to fix this then. #region Debug verification var xFields = GetFieldsInfo(typeof(string), false).Where(i => !i.IsStatic).ToArray(); if (xFields[0].Id != "System.Int32 System.String.m_stringLength" || xFields[0].Offset != 0) { throw new Exception("Fields changed!"); } if (xFields[1].Id != "System.Char System.String.m_firstChar" || xFields[1].Offset != 4) { throw new Exception("Fields changed!"); } #endregion }
public override void Execute( MethodInfo aMethod, ILOpCode aOpCode ) { DoNullReferenceCheck(Assembler, DebugEnabled, 0); XS.Pop(XSRegisters.EAX); new CPUx86.Push { DestinationReg = CPUx86.RegistersEnum.EAX, DestinationIsIndirect = true, DestinationDisplacement = 4 }; XS.Push(XSRegisters.EAX, isIndirect: true); }
public override void Execute( MethodInfo aMethod, ILOpCode aOpCode ) { var xOp = (OpInt64)aOpCode; // push high part new CPUx86.Push { DestinationValue = BitConverter.ToUInt32(BitConverter.GetBytes(xOp.Value), 4) }; // push low part new CPUx86.Push { DestinationValue = BitConverter.ToUInt32(BitConverter.GetBytes(xOp.Value), 0) }; }
public override void Execute(MethodInfo aMethod, ILOpCode aOpCode) { DoNullReferenceCheck(Assembler, DebugEnabled, 0); XS.Pop(XSRegisters.EAX); XS.Push(XSRegisters.EAX, isIndirect: true, displacement: 4); XS.Push(XSRegisters.EAX, isIndirect: true); }
public override void Execute( MethodInfo aMethod, ILOpCode aOpCode ) { var xType = aOpCode.StackPopTypes[0]; var xSize = SizeOfType(xType); var xIsFloat = TypeIsFloat(xType); DoExecute(xSize, xIsFloat); }
public override void Execute( MethodInfo aMethod, ILOpCode aOpCode ) { var xOpType = (OpType)aOpCode; var xSize = SizeOfType(xOpType.Value); Stelem_Ref.Assemble(Assembler, (uint)xSize, aMethod, aOpCode, DebugEnabled); }
public override void Execute( MethodInfo aMethod, ILOpCode aOpCode ) { var xStackContent = aOpCode.StackPopTypes[0]; var xStackContentSecond = aOpCode.StackPopTypes[1]; var xStackContentSize = SizeOfType(xStackContent); var xStackContentSecondSize = SizeOfType(xStackContentSecond); var xSize = Math.Max(xStackContentSize, xStackContentSecondSize); if (ILOp.Align(xStackContentSize, 4u) != ILOp.Align(xStackContentSecondSize, 4u)) { throw new NotSupportedException("Operands have different size!"); } if (xSize > 8) { throw new NotImplementedException("StackSize>8 not supported"); } if (xSize > 4) { // [ESP] is low part // [ESP + 4] is high part // [ESP + 8] is low part // [ESP + 12] is high part new CPUx86.Pop { DestinationReg = CPUx86.Registers.EAX }; new CPUx86.Pop { DestinationReg = CPUx86.Registers.EDX }; // [ESP] is low part // [ESP + 4] is high part new CPUx86.Or { DestinationReg = CPUx86.Registers.ESP, DestinationIsIndirect = true, SourceReg = CPUx86.Registers.EAX }; new CPUx86.Or { DestinationReg = CPUx86.Registers.ESP, DestinationIsIndirect = true, DestinationDisplacement = 4, SourceReg = CPUx86.Registers.EDX }; } else { new CPUx86.Pop { DestinationReg = CPUx86.Registers.EAX }; new CPUx86.Or { DestinationReg = CPUx86.Registers.ESP, DestinationIsIndirect = true, SourceReg = CPUx86.Registers.EAX }; } }
public override void Execute( MethodInfo aMethod, ILOpCode aOpCode ) { OpToken xToken = ( OpToken )aOpCode; string xTokenAddress = null; if (xToken.ValueIsType) { xTokenAddress = ILOp.GetTypeIDLabel(xToken.ValueType); } if (xToken.ValueIsField) { xTokenAddress= DataMember.GetStaticFieldName(xToken.ValueField); } if (String.IsNullOrEmpty(xTokenAddress)) { throw new Exception("Ldtoken not implemented!"); } //if( mType != null ) //{ // mTokenAddress = GetService<IMetaDataInfoService>().GetTypeIdLabel( mType ); //} //new CPUx86.Push { DestinationValue = xToken.Value }; new CPU.Push { DestinationRef = Cosmos.Assembler.ElementReference.New( xTokenAddress ) }; }
public override void Execute( MethodInfo aMethod, ILOpCode aOpCode ) { var xSize = Math.Max(SizeOfType(aOpCode.StackPopTypes[0]), SizeOfType(aOpCode.StackPopTypes[1])); XS.Pop(XSRegisters.EAX); XS.Pop(XSRegisters.EDX); XS.Xor(XSRegisters.EAX, XSRegisters.EDX); XS.Push(XSRegisters.EAX); }
public override void Execute( MethodInfo aMethod, ILOpCode aOpCode ) { var xSize = Math.Max(SizeOfType(aOpCode.StackPopTypes[0]), SizeOfType(aOpCode.StackPopTypes[1])); new CPUx86.Pop { DestinationReg = CPUx86.Registers.EAX }; new CPUx86.Pop { DestinationReg = CPUx86.Registers.EDX }; new CPUx86.Xor { DestinationReg = CPUx86.Registers.EAX, SourceReg = CPUx86.Registers.EDX }; new CPUx86.Push { DestinationReg = CPUx86.Registers.EAX }; }
public override void Execute( MethodInfo aMethod, ILOpCode aOpCode ) { DoNullReferenceCheck(Assembler, DebugEnabled, 4); XS.Add(XSRegisters.ESP, 4); XS.Pop(XSRegisters.EAX); XS.Push(XSRegisters.EAX, displacement: 8); }
public override void Execute(MethodInfo aMethod, ILOpCode aOpCode) { OpMethod xMethod = (OpMethod)aOpCode; string xCurrentLabel = GetLabel(aMethod, aOpCode); var xType = xMethod.Value.DeclaringType; Assemble(Assembler, aMethod, xMethod, xCurrentLabel, xType, xMethod.Value); }
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.cs->Error: StackSize > 8 not supported"); } else { var xBaseLabel = GetLabel(aMethod, aOpCode) + "."; var xSuccessLabel = xBaseLabel + "Success"; if (xSize > 4) { if (xIsFloat) { //TODO overflow check new CPUx86.x87.FloatLoad { DestinationReg=Registers.ESP,Size=64, DestinationIsIndirect=true }; new CPUx86.Add { SourceValue = 8, DestinationReg = Registers.ESP }; new CPUx86.x87.FloatAdd { DestinationReg = CPUx86.Registers.ESP, DestinationIsIndirect=true, Size=64 }; new CPUx86.x87.FloatStoreAndPop { DestinationReg = Registers.ESP, Size = 64, DestinationIsIndirect = true }; } else { new CPUx86.Pop { DestinationReg = CPUx86.Registers.EDX }; // low part new CPUx86.Pop { DestinationReg = CPUx86.Registers.EAX }; // high part new CPUx86.Add { DestinationReg = CPUx86.Registers.ESP, DestinationIsIndirect = true, SourceReg = CPUx86.Registers.EDX }; new CPUx86.AddWithCarry { DestinationReg = CPUx86.Registers.ESP, DestinationIsIndirect = true, DestinationDisplacement = 4, SourceReg = CPUx86.Registers.EAX }; } } else { if (xIsFloat) //float { //TODO overflow check 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.AddSS { DestinationReg = CPUx86.Registers.XMM1, SourceReg = CPUx86.Registers.XMM0 }; new CPUx86.SSE.MoveSS { DestinationReg = CPUx86.Registers.ESP, DestinationIsIndirect = true, SourceReg = CPUx86.Registers.XMM1 }; } else //integer { new CPUx86.Pop { DestinationReg = CPUx86.Registers.EAX }; new CPUx86.Add { DestinationReg = CPUx86.Registers.ESP, DestinationIsIndirect = true, SourceReg = CPUx86.Registers.EAX }; } } if (false == xIsFloat) { new CPUx86.ConditionalJump { Condition = ConditionalTestEnum.NoOverflow, DestinationLabel = xSuccessLabel }; ThrowOverflowException(); } new Label(xSuccessLabel); } }
public static void Assemble(Assembler.Assembler aAssembler, uint aElementSize, MethodInfo aMethod, ILOpCode aOpCode, bool debugEnabled) { // stack == the new value // stack + 1 == the index // stack + 2 == the array DoNullReferenceCheck(aAssembler, debugEnabled, (int)(8 + Align(aElementSize, 4))); uint xStackSize = aElementSize; if (xStackSize % 4 != 0) { xStackSize += 4 - xStackSize % 4; } // calculate element offset into array memory (including header) XS.Set(XSRegisters.EAX, XSRegisters.ESP, sourceDisplacement: (int)xStackSize); // the index XS.Set(XSRegisters.EDX, aElementSize); XS.Multiply(XSRegisters.EDX); XS.Add(XSRegisters.EAX, ObjectImpl.FieldDataOffset + 4); XS.Set(XSRegisters.EDX, XSRegisters.ESP, sourceDisplacement: (int)xStackSize + 8); // the array XS.Add(XSRegisters.EDX, XSRegisters.EAX); XS.Push(XSRegisters.EDX); XS.Pop(XSRegisters.ECX); for (int i = (int)(aElementSize / 4) - 1; i >= 0; i -= 1) { new Comment(aAssembler, "Start 1 dword"); XS.Pop(XSRegisters.EBX); XS.Set(XSRegisters.ECX, XSRegisters.EBX, destinationIsIndirect: true); XS.Add(XSRegisters.ECX, 4); } switch (aElementSize % 4) { case 1: { new Comment(aAssembler, "Start 1 byte"); XS.Pop(XSRegisters.EBX); XS.Set(XSRegisters.ECX, XSRegisters.BL, destinationIsIndirect: true); break; } case 2: { new Comment(aAssembler, "Start 1 word"); XS.Pop(XSRegisters.EBX); XS.Set(XSRegisters.ECX, XSRegisters.BX, destinationIsIndirect: true); break; } case 0: { break; } default: throw new Exception("Remainder size " + (aElementSize % 4) + " not supported!"); } XS.Add(XSRegisters.ESP, 12); }
public override void Execute(MethodInfo aMethod, ILOpCode aOpCode) { #warning TODO: This needs to either be implemented, or needs to throw a NotImplementedException! // todo: Implement correct Constrained support //throw new NotImplementedException("Constrained used in '" + aMethod.MethodBase.GetFullName() + "'"); var xOpType = aOpCode as OpType; DoExecute(Assembler, aMethod, aOpCode, xOpType, DebugEnabled); }
public override void Execute(_MethodInfo aMethod, ILOpCode aOpCode) { var xValue = aOpCode.StackPopTypes[0]; var xValueIsFloat = TypeIsFloat(xValue); var xValueSize = SizeOfType(xValue); if (!xValueIsFloat) { switch (xValueSize) { case 1: case 2: case 4: /* * Code generated by C# / Visual Studio 2015 * mov eax,dword ptr [anInt] * mov dword ptr [ebp-0E0h],eax * cvtsi2sd xmm0,dword ptr [ebp-0E0h] * mov ecx,dword ptr [ebp-0E0h] * shr ecx,1Fh * addsd xmm0,mmword ptr __xmm@41f00000000000000000000000000000 (01176B40h)[ecx*8] * movsd mmword ptr [aDouble],xmm0 # This for now means to copy our converted double to ESP */ string BaseLabel = GetLabel(aMethod, aOpCode) + "."; string LabelSign_Bit_Unset = BaseLabel + "LabelSign_Bit_Unset"; XS.Set(EAX, ESP, sourceIsIndirect: true); XS.Set(EBP, EAX, destinationDisplacement: -0xE0, destinationIsIndirect: true); XS.SSE2.ConvertSI2SD(XMM0, EBP, sourceDisplacement: -0xE0, sourceIsIndirect: true); XS.Set(ECX, EBP, sourceDisplacement: -0xE0, sourceIsIndirect: true); // OK now we put in ECX the last bit of our unsigned value, we call it "SIGN_BIT" but is a little improper... XS.ShiftRight(ECX, 31); /* * if the 'SIGN_BIT' is 0 it means that our uint could have been placed in a normal int so ConvertSI2SD did already * the right thing: we have finished * if the value is 1 we need to do that addition with that weird constant to obtain the real value as double */ XS.Compare(ECX, 0x00); XS.Jump(ConditionalTestEnum.Equal, LabelSign_Bit_Unset); XS.LiteralCode(@"addsd xmm0, [__uint2double_const]"); XS.Label(LabelSign_Bit_Unset); // We have converted our value to double put it on ESP // expand stack, that moved data is valid stack XS.Sub(ESP, 4); XS.SSE2.MoveSD(ESP, XMM0, destinationIsIndirect: true); break; case 8: BaseLabel = GetLabel(aMethod, aOpCode) + "."; LabelSign_Bit_Unset = BaseLabel + "LabelSign_Bit_Unset"; /* * mov EAX, ESP + 4 * fild qword ptr [esp] * shr EAX, 31 * cmp ESP, 0 * jpe LabelSign_Bit_Unset * LabelSign_Bit_Unset: * fadd dword ptr __ulong2double_const2 * fstp ESP */ // Save the high part of the ulong in EAX (we cannot move all of ESP as it has 64 bit size) XS.Set(EAX, ESP, sourceIsIndirect: true, sourceDisplacement: 4); XS.FPU.IntLoad(ESP, isIndirect: true, size: RegisterSize.Long64); XS.Test(EAX, EAX); XS.Jump(ConditionalTestEnum.NotSign, LabelSign_Bit_Unset); // If the sign is set we remove it using the constant __ulong2double_const4 XS.LiteralCode(@"fadd dword [__ulong2double_const]"); XS.Label(LabelSign_Bit_Unset); // Convert the value to double and move it into the stack XS.FPU.FloatStoreAndPop(ESP, isIndirect: true, size: RegisterSize.Long64); break; default: //EmitNotImplementedException( Assembler, GetServiceProvider(), "Conv_I: SourceSize " + xSource + " not supported!", mCurLabel, mMethodInformation, mCurOffset, mNextLabel ); throw new NotImplementedException("Conv_R_Un with type " + xValue + " not supported!"); } } else { throw new NotImplementedException("Conv_R_Un with type " + xValue + " not supported!"); } }
internal BranchInfo(int ilOffset, LabelHandle label, ILOpCode opCode) { ILOffset = ilOffset; Label = label; _opCode = (byte)opCode; }
public override void Execute(_MethodInfo aMethod, ILOpCode aOpCode) { Assemble(Assembler, 8, aMethod, aOpCode, DebugEnabled); }
public static void Assemble(Assembler aAssembler, uint aElementSize, _MethodInfo aMethod, ILOpCode aOpCode, bool debugEnabled) { // stack == the new value // stack + 1 == the index // stack + 2 == the array DoNullReferenceCheck(aAssembler, debugEnabled, (int)(8 + Align(aElementSize, 4))); uint xStackSize = aElementSize; if (xStackSize % 4 != 0) { xStackSize += 4 - xStackSize % 4; } // Do index out of range check var xBaseLabel = GetLabel(aMethod, aOpCode); var xNoIndexOutOfRangeExeptionLabel = xBaseLabel + "_NoIndexOutOfRangeException"; var xIndexOutOfRangeExeptionLabel = xBaseLabel + "_IndexOutOfRangeException"; if (xStackSize == 4) { XS.Pop(ECX); //get value _, array, 0, index, value -> _, array, 0, index } else if (xStackSize == 8) { XS.Pop(ECX); //get value _, array, 0, index, value0, value1 -> _, array, 0, index, value0 XS.Pop(EDX); //get value _, array, 0, index, value0 -> _, array, 0, index } else { throw new NotImplementedException(); } 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 if (xStackSize == 4) { XS.Push(ECX); //_, array, 0 -> _, array, 0, index, value } else if (xStackSize == 8) { XS.Push(EDX); //_, array, 0, index -> _, array, 0, index, value0 XS.Push(ECX); //_, array, 0, index, value0 -> _, array, 0, index, value0, value1 } // calculate element offset into array memory (including header) XS.Set(EAX, ESP, sourceDisplacement: (int)xStackSize); // the index XS.Set(EDX, aElementSize); XS.Multiply(EDX); XS.Add(EAX, ObjectUtils.FieldDataOffset + 4); XS.Set(EDX, ESP, sourceDisplacement: (int)xStackSize + 8); // the array XS.Add(EDX, EAX); XS.Push(EDX); XS.Pop(ECX); for (int i = (int)(aElementSize / 4) - 1; i >= 0; i -= 1) { new Comment(aAssembler, "Start 1 dword"); XS.Pop(EBX); XS.Set(ECX, EBX, destinationIsIndirect: true); XS.Add(ECX, 4); } switch (aElementSize % 4) { case 1: { new Comment(aAssembler, "Start 1 byte"); XS.Pop(EBX); XS.Set(ECX, BL, destinationIsIndirect: true); break; } case 2: { new Comment(aAssembler, "Start 1 word"); XS.Pop(EBX); XS.Set(ECX, BX, destinationIsIndirect: true); break; } case 0: { break; } default: throw new Exception("Remainder size " + (aElementSize % 4) + " not supported!"); } XS.Add(ESP, 12); }
public override void Execute(MethodInfo aMethod, ILOpCode aOpCode) { var xOpCode = (ILOpCodes.OpField)aOpCode; DoExecute(Assembler, xOpCode.Value.DeclaringType, xOpCode.Value.GetFullName(), true, DebugEnabled, aOpCode.StackPopTypes[0]); }
public override void Execute(_MethodInfo aMethod, ILOpCode aOpCode) { var xOpMethod = aOpCode as OpMethod; DoExecute(Assembler, aMethod, xOpMethod.Value, xOpMethod.ValueUID, aOpCode, DebugEnabled); }
public void SetBranch(object newLabel, ILOpCode branchCode, ILOpCode revBranchCode) { this.SetBranch(newLabel, branchCode); this.RevBranchCode = revBranchCode; }
public override void Execute(ILOpCode instr, MethodBase aMethod) { //This is branch type IL var xOffset = ((OpBranch)instr).Value; var xSize = Core.vStack.Pop().Size; var xTrueLabel = ILHelper.GetLabel(aMethod, xOffset); var xFalseLabel = ILHelper.GetLabel(aMethod, instr.Position) + "._bne_un_false"; //Make a pop because exactly we are popping up two items Core.vStack.Pop(); /* * value1 is pushed onto the stack. * value2 is pushed onto the stack. * value2 and value1 are popped from the stack; * if value1 is not equal to value2, the branch operation is performed. --> value1 ≠ value2 */ switch (ILCompiler.CPUArchitecture) { #region _x86_ case CPUArch.x86: { if (xSize <= 4) { //***What we are going to do is*** //1) Pop Value 2 into EAX //2) Pop Value 1 into EBX //3) Compare EAX and EBX, Jump to Branch when the result is not zero Core.AssemblerCode.Add(new Pop { DestinationReg = Registers.EAX }); //Value 2 Core.AssemblerCode.Add(new Pop { DestinationReg = Registers.EBX }); //Value 1 Core.AssemblerCode.Add(new Cmp { DestinationReg = Registers.EAX, SourceReg = Registers.EBX }); Core.AssemblerCode.Add(new Jmp { Condition = ConditionalJumpEnum.JNE, DestinationRef = xTrueLabel }); } else if (xSize <= 8) { //***What we are going to do is*** //1) Pop Value 2 low into EAX and high into EBX //2) Pop Value 1 low into ECX and high into EDX //3) Compare low values and check if zero than continue else if not than jump to Not Equal //4) Compare high values and check if zero than jump to Branch else continue //Value 2 EBX:EAX Core.AssemblerCode.Add(new Pop { DestinationReg = Registers.EAX }); //low Core.AssemblerCode.Add(new Pop { DestinationReg = Registers.EBX }); //high //Value 1 EDX:ECX Core.AssemblerCode.Add(new Pop { DestinationReg = Registers.ECX }); //low Core.AssemblerCode.Add(new Pop { DestinationReg = Registers.EDX }); //high Core.AssemblerCode.Add(new Cmp { DestinationReg = Registers.EAX, SourceReg = Registers.ECX }); Core.AssemblerCode.Add(new Jmp { Condition = ConditionalJumpEnum.JNE, DestinationRef = xTrueLabel }); Core.AssemblerCode.Add(new Cmp { DestinationReg = Registers.EBX, SourceReg = Registers.EDX }); Core.AssemblerCode.Add(new Jmp { Condition = ConditionalJumpEnum.JNE, DestinationRef = xTrueLabel }); Core.AssemblerCode.Add(new Label(xFalseLabel)); } else { //Not called usually throw new Exception("@Bne_Un: Branch operation bne_un for size > 8 is not yet implemented"); } } break; #endregion #region _x64_ case CPUArch.x64: { } break; #endregion #region _ARM_ case CPUArch.ARM: { } break; #endregion } }
public override void Execute(_MethodInfo aMethod, ILOpCode aOpCode) { throw new NotImplementedException(); }
public static void DoExecute(Assembler Assembler, _MethodInfo aMethod, MethodBase aTargetMethod, uint aTargetMethodUID, ILOpCode aOp, bool debugEnabled) { string xCurrentMethodLabel = GetLabel(aMethod, aOp.Position); Type xPopType = aOp.StackPopTypes.Last(); string xNormalAddress = ""; if (aTargetMethod.IsStatic || !aTargetMethod.IsVirtual || aTargetMethod.IsFinal) { xNormalAddress = LabelName.Get(aTargetMethod); } uint xReturnSize = 0; var xMethodInfo = aTargetMethod as MethodInfo; if (xMethodInfo != null) { xReturnSize = Align(SizeOfType(xMethodInfo.ReturnType), 4); } var xExtraStackSize = Call.GetStackSizeToReservate(aTargetMethod, xPopType); uint xThisOffset = 0; var xParameters = aTargetMethod.GetParameters(); foreach (var xItem in xParameters) { xThisOffset += Align(SizeOfType(xItem.ParameterType), 4); } // This is finding offset to self? It looks like we dont need offsets of other // arguments, but only self. If so can calculate without calculating all fields // Might have to go to old data structure for the offset... // Can we add this method info somehow to the data passed in? // mThisOffset = mTargetMethodInfo.Arguments[0].Offset; XS.Comment("ThisOffset = " + xThisOffset); if (IsReferenceType(xPopType)) { DoNullReferenceCheck(Assembler, debugEnabled, (int)xThisOffset + 4); } else { DoNullReferenceCheck(Assembler, debugEnabled, (int)xThisOffset); } if (!String.IsNullOrEmpty(xNormalAddress)) { if (xExtraStackSize > 0) { XS.Sub(ESP, xExtraStackSize); } XS.Call(xNormalAddress); } else { /* * On the stack now: * $esp Params * $esp + mThisOffset This */ if ((xPopType.IsPointer) || (xPopType.IsByRef)) { xPopType = xPopType.GetElementType(); string xTypeId = GetTypeIDLabel(xPopType); XS.Push(xTypeId, isIndirect: true); } else { XS.Set(EAX, ESP, sourceDisplacement: (int)xThisOffset + 4); XS.Push(EAX, isIndirect: true); } XS.Push(aTargetMethodUID); XS.Call(LabelName.Get(VTablesImplRefs.GetMethodAddressForTypeRef)); if (xExtraStackSize > 0) { xThisOffset -= xExtraStackSize; } /* * On the stack now: * $esp Params * $esp + mThisOffset This */ XS.Pop(ECX); XS.Label(xCurrentMethodLabel + ".AfterAddressCheck"); if (IsReferenceType(xPopType)) { /* * On the stack now: * $esp + 0 Params * $esp + mThisOffset This */ // we need to see if $this is a boxed object, and if so, we need to unbox it XS.Set(EAX, ESP, sourceDisplacement: (int)xThisOffset + 4); XS.Compare(EAX, (int)ObjectUtils.InstanceTypeEnum.BoxedValueType, destinationIsIndirect: true, destinationDisplacement: 4, size: RegisterSize.Int32); /* * On the stack now: * $esp Params * $esp + mThisOffset This * * ECX contains the method to call * EAX contains the type pointer (not the handle!!) */ XS.Jump(CPU.ConditionalTestEnum.NotEqual, xCurrentMethodLabel + ".NotBoxedThis"); /* * On the stack now: * $esp Params * $esp + mThisOffset This * * ECX contains the method to call * EAX contains the type pointer (not the handle!!) */ XS.Add(EAX, ObjectUtils.FieldDataOffset); XS.Set(ESP, EAX, destinationDisplacement: (int)xThisOffset + 4); var xHasParams = xThisOffset != 0; var xNeedsExtraStackSize = xReturnSize >= xThisOffset + 8; if (xHasParams || !xNeedsExtraStackSize) { XS.Add(ESP, xThisOffset + 4); } for (int i = 0; i < xThisOffset / 4; i++) { XS.Push(ESP, displacement: -4); } if (xHasParams && xNeedsExtraStackSize) { XS.Sub(ESP, 4); } /* * On the stack now: * $esp Params * $esp + mThisOffset Pointer to address inside box * * ECX contains the method to call */ } XS.Label(xCurrentMethodLabel + ".NotBoxedThis"); if (xExtraStackSize > 0) { XS.Sub(ESP, xExtraStackSize); } XS.Call(ECX); XS.Label(xCurrentMethodLabel + ".AfterNotBoxedThis"); } EmitExceptionLogic(Assembler, aMethod, aOp, true, delegate { var xStackOffsetBefore = aOp.StackOffsetBeforeExecution.Value; uint xPopSize = 0; foreach (var type in aOp.StackPopTypes) { xPopSize += Align(SizeOfType(type), 4); } var xResultSize = xReturnSize; if (xResultSize % 4 != 0) { xResultSize += 4 - (xResultSize % 4); } EmitExceptionCleanupAfterCall(Assembler, xResultSize, xStackOffsetBefore, xPopSize); }); XS.Label(xCurrentMethodLabel + ".NoExceptionAfterCall"); XS.Comment("Argument Count = " + xParameters.Length); }
public override void Execute(_MethodInfo aMethod, ILOpCode aOpCode) { var xType = aMethod.MethodBase.DeclaringType; var xOpCode = (ILOpCodes.OpField)aOpCode; FieldInfo xField = xOpCode.Value; var xIsReferenceType = TypeIsReferenceType(xField.FieldType); // call cctor: var xCctor = (xField.DeclaringType.GetConstructors(BindingFlags.Static | BindingFlags.NonPublic)).SingleOrDefault(); if (xCctor != null) { XS.Call(LabelName.Get(xCctor)); ILOp.EmitExceptionLogic(Assembler, aMethod, aOpCode, true, null, ".AfterCCTorExceptionCheck"); XS.Label(".AfterCCTorExceptionCheck"); } //int aExtraOffset;// = 0; //bool xNeedsGC = xField.FieldType.IsClass && !xField.FieldType.IsValueType; uint xSize = SizeOfType(xField.FieldType); //if( xNeedsGC ) //{ // aExtraOffset = 12; //} new Comment(Assembler, "Type = '" + xField.FieldType.FullName /*+ "', NeedsGC = " + xNeedsGC*/); uint xOffset = 0; var xFields = xField.DeclaringType.GetFields(); foreach (FieldInfo xInfo in xFields) { if (xInfo == xField) { break; } xOffset += SizeOfType(xInfo.FieldType); } string xDataName = DataMember.GetStaticFieldName(xField); if (xIsReferenceType) { XS.Add(XSRegisters.ESP, 4); XS.Pop(XSRegisters.EAX); XS.Set(ElementReference.New(xDataName).Name, XSRegisters.EAX, destinationIsIndirect: true, destinationDisplacement: 4); return; } for (int i = 0; i < (xSize / 4); i++) { XS.Pop(XSRegisters.EAX); new CPUx86.Mov { DestinationRef = ElementReference.New(xDataName, i * 4), DestinationIsIndirect = true, SourceReg = CPUx86.RegistersEnum.EAX }; } switch (xSize % 4) { case 1: { XS.Pop(XSRegisters.EAX); new CPUx86.Mov { DestinationRef = ElementReference.New(xDataName, (int)((xSize / 4) * 4)), DestinationIsIndirect = true, SourceReg = CPUx86.RegistersEnum.AL }; break; } case 2: { XS.Pop(XSRegisters.EAX); new CPUx86.Mov { DestinationRef = Cosmos.Assembler.ElementReference.New(xDataName, (int)((xSize / 4) * 4)), DestinationIsIndirect = true, SourceReg = CPUx86.RegistersEnum.AX }; break; } case 0: { break; } default: //EmitNotImplementedException(Assembler, GetServiceProvider(), "Ldsfld: Remainder size " + (xSize % 4) + " not supported!", mCurLabel, mMethodInformation, mCurOffset, mNextLabel); throw new NotImplementedException(); //break; } }
public override void Execute(ILOpCode instr, MethodBase aMethod) { //Do Nothing //COMPILER HACK ^^ }
public override void Execute(_MethodInfo aMethod, ILOpCode aOpCode) { var xIsSingleCompare = true; switch (aOpCode.OpCode) { case ILOpCode.Code.Beq: case ILOpCode.Code.Bge: case ILOpCode.Code.Bgt: case ILOpCode.Code.Bge_Un: case ILOpCode.Code.Bgt_Un: case ILOpCode.Code.Ble: case ILOpCode.Code.Ble_Un: case ILOpCode.Code.Bne_Un: case ILOpCode.Code.Blt: case ILOpCode.Code.Blt_Un: xIsSingleCompare = false; break; } var xStackContent = aOpCode.StackPopTypes[0]; var xStackContentSize = SizeOfType(xStackContent); if (xStackContentSize > 8) { throw new Exception("Cosmos.IL2CPU.x86->IL->Branch.cs->Error: StackSize > 8 not supported"); } CPU.ConditionalTestEnum xTestOp; // all conditions are inverted here? switch (aOpCode.OpCode) { case ILOpCode.Code.Beq: xTestOp = CPU.ConditionalTestEnum.Zero; break; case ILOpCode.Code.Bge: xTestOp = CPU.ConditionalTestEnum.GreaterThanOrEqualTo; break; case ILOpCode.Code.Bgt: xTestOp = CPU.ConditionalTestEnum.GreaterThan; break; case ILOpCode.Code.Ble: xTestOp = CPU.ConditionalTestEnum.LessThanOrEqualTo; break; case ILOpCode.Code.Blt: xTestOp = CPU.ConditionalTestEnum.LessThan; break; case ILOpCode.Code.Bne_Un: xTestOp = CPU.ConditionalTestEnum.NotEqual; break; case ILOpCode.Code.Bge_Un: xTestOp = CPU.ConditionalTestEnum.AboveOrEqual; break; case ILOpCode.Code.Bgt_Un: xTestOp = CPU.ConditionalTestEnum.Above; break; case ILOpCode.Code.Ble_Un: xTestOp = CPU.ConditionalTestEnum.BelowOrEqual; break; case ILOpCode.Code.Blt_Un: xTestOp = CPU.ConditionalTestEnum.Below; break; case ILOpCode.Code.Brfalse: xTestOp = CPU.ConditionalTestEnum.Zero; break; case ILOpCode.Code.Brtrue: xTestOp = CPU.ConditionalTestEnum.NotZero; break; default: throw new Exception("Cosmos.IL2CPU.x86->IL->Branch.cs->Error: Unknown OpCode for conditional branch."); } if (!xIsSingleCompare) { if (xStackContentSize <= 4) { //if (xStackContent.IsFloat) //{ // throw new Exception("Cosmos.IL2CPU.x86->IL->Branch.cs->Error: Comparison of floats (System.Single) is not yet supported!"); //} //else //{ XS.Pop(XSRegisters.EAX); XS.Pop(XSRegisters.EBX); XS.Compare(XSRegisters.EBX, XSRegisters.EAX); new ConditionalJump { Condition = xTestOp, DestinationLabel = AppAssembler.TmpBranchLabel(aMethod, aOpCode) }; //} } else { //if (xStackContent.IsFloat) //{ // throw new Exception("Cosmos.IL2CPU.x86->IL->Branch.cs->Error: Comparison of doubles (System.Double) is not yet supported!"); //} //else //{ var xNoJump = GetLabel(aMethod, aOpCode) + "__NoBranch"; // value 2 EBX:EAX XS.Pop(XSRegisters.EAX); XS.Pop(XSRegisters.EBX); // value 1 EDX:ECX XS.Pop(XSRegisters.ECX); XS.Pop(XSRegisters.EDX); switch (xTestOp) { case ConditionalTestEnum.Zero: // Equal case ConditionalTestEnum.NotEqual: // NotZero XS.Xor(XSRegisters.EAX, XSRegisters.ECX); new ConditionalJump { Condition = xTestOp, DestinationLabel = AppAssembler.TmpBranchLabel(aMethod, aOpCode) }; XS.Xor(XSRegisters.EBX, XSRegisters.EDX); new ConditionalJump { Condition = xTestOp, DestinationLabel = AppAssembler.TmpBranchLabel(aMethod, aOpCode) }; break; case ConditionalTestEnum.GreaterThanOrEqualTo: XS.Compare(XSRegisters.EDX, XSRegisters.EBX); XS.Jump(ConditionalTestEnum.LessThan, xNoJump); new ConditionalJump { Condition = ConditionalTestEnum.GreaterThan, DestinationLabel = AppAssembler.TmpBranchLabel(aMethod, aOpCode) }; XS.Compare(XSRegisters.ECX, XSRegisters.EAX); XS.Jump(ConditionalTestEnum.Below, xNoJump); break; case ConditionalTestEnum.GreaterThan: XS.Compare(XSRegisters.EDX, XSRegisters.EBX); XS.Jump(ConditionalTestEnum.LessThan, xNoJump); new ConditionalJump { Condition = ConditionalTestEnum.GreaterThan, DestinationLabel = AppAssembler.TmpBranchLabel(aMethod, aOpCode) }; XS.Compare(XSRegisters.ECX, XSRegisters.EAX); XS.Jump(ConditionalTestEnum.BelowOrEqual, xNoJump); break; case ConditionalTestEnum.LessThanOrEqualTo: XS.Compare(XSRegisters.EDX, XSRegisters.EBX); new ConditionalJump { Condition = ConditionalTestEnum.LessThan, DestinationLabel = AppAssembler.TmpBranchLabel(aMethod, aOpCode) }; XS.Jump(ConditionalTestEnum.GreaterThan, xNoJump); XS.Compare(XSRegisters.ECX, XSRegisters.EAX); new ConditionalJump { Condition = ConditionalTestEnum.BelowOrEqual, DestinationLabel = AppAssembler.TmpBranchLabel(aMethod, aOpCode) }; break; case ConditionalTestEnum.LessThan: XS.Compare(XSRegisters.EDX, XSRegisters.EBX); new ConditionalJump { Condition = ConditionalTestEnum.LessThan, DestinationLabel = AppAssembler.TmpBranchLabel(aMethod, aOpCode) }; XS.Jump(ConditionalTestEnum.GreaterThan, xNoJump); XS.Compare(XSRegisters.ECX, XSRegisters.EAX); new ConditionalJump { Condition = ConditionalTestEnum.Below, DestinationLabel = AppAssembler.TmpBranchLabel(aMethod, aOpCode) }; break; // from here all unsigned case ConditionalTestEnum.AboveOrEqual: XS.Compare(XSRegisters.EDX, XSRegisters.EBX); new ConditionalJump { Condition = ConditionalTestEnum.Above, DestinationLabel = AppAssembler.TmpBranchLabel(aMethod, aOpCode) }; XS.Compare(XSRegisters.ECX, XSRegisters.EAX); XS.Jump(ConditionalTestEnum.Below, xNoJump); break; case ConditionalTestEnum.Above: XS.Compare(XSRegisters.EDX, XSRegisters.EBX); new ConditionalJump { Condition = ConditionalTestEnum.Above, DestinationLabel = AppAssembler.TmpBranchLabel(aMethod, aOpCode) }; XS.Compare(XSRegisters.ECX, XSRegisters.EAX); XS.Jump(ConditionalTestEnum.BelowOrEqual, xNoJump); break; case ConditionalTestEnum.BelowOrEqual: XS.Compare(XSRegisters.EDX, XSRegisters.EBX); new ConditionalJump { Condition = ConditionalTestEnum.Above, DestinationLabel = AppAssembler.TmpBranchLabel(aMethod, aOpCode) }; XS.Jump(ConditionalTestEnum.Below, xNoJump); XS.Compare(XSRegisters.ECX, XSRegisters.EAX); new ConditionalJump { Condition = ConditionalTestEnum.Above, DestinationLabel = AppAssembler.TmpBranchLabel(aMethod, aOpCode) }; break; case ConditionalTestEnum.Below: XS.Compare(XSRegisters.EDX, XSRegisters.EBX); new ConditionalJump { Condition = ConditionalTestEnum.Above, DestinationLabel = AppAssembler.TmpBranchLabel(aMethod, aOpCode) }; XS.Jump(ConditionalTestEnum.Below, xNoJump); XS.Compare(XSRegisters.ECX, XSRegisters.EAX); new ConditionalJump { Condition = ConditionalTestEnum.AboveOrEqual, DestinationLabel = AppAssembler.TmpBranchLabel(aMethod, aOpCode) }; break; default: throw new Exception("Unknown OpCode for conditional branch in 64-bit."); } XS.Label(xNoJump); //} } } else { //if (xStackContent.IsFloat) //{ // throw new Exception("Cosmos.IL2CPU.x86->IL->Branch.cs->Error: Simple comparison of floating point numbers is not yet supported!"); //} //else //{ // todo: improve code clarity if (xStackContentSize <= 4) { XS.Pop(XSRegisters.EAX); if (xTestOp == ConditionalTestEnum.Zero) { XS.Compare(XSRegisters.EAX, 0); new ConditionalJump { Condition = ConditionalTestEnum.Equal, DestinationLabel = AppAssembler.TmpBranchLabel(aMethod, aOpCode) }; } else if (xTestOp == ConditionalTestEnum.NotZero) { XS.Compare(XSRegisters.EAX, 0); new ConditionalJump { Condition = ConditionalTestEnum.NotEqual, DestinationLabel = AppAssembler.TmpBranchLabel(aMethod, aOpCode) }; } else { throw new NotSupportedException("Cosmos.IL2CPU.x86->IL->Branch.cs->Error: Situation not supported yet! (In the Simple Comparison)"); } } else { if (IsReferenceType(xStackContent)) { XS.Add(XSRegisters.ESP, 4); XS.Pop(XSRegisters.EAX); } else { XS.Pop(XSRegisters.EAX); XS.Pop(XSRegisters.EBX); } switch (xTestOp) { case ConditionalTestEnum.Zero: // Equal case ConditionalTestEnum.NotZero: // NotEqual if (IsReferenceType(xStackContent)) { XS.Xor(XSRegisters.EAX, 0); new ConditionalJump { Condition = xTestOp, DestinationLabel = AppAssembler.TmpBranchLabel(aMethod, aOpCode) }; } else { XS.Xor(XSRegisters.EAX, 0); new ConditionalJump { Condition = xTestOp, DestinationLabel = AppAssembler.TmpBranchLabel(aMethod, aOpCode) }; XS.Xor(XSRegisters.EBX, 0); new ConditionalJump { Condition = xTestOp, DestinationLabel = AppAssembler.TmpBranchLabel(aMethod, aOpCode) }; } break; default: throw new NotImplementedException("Cosmos.IL2CPU.X86.IL.Branch: Simple branch " + aOpCode.OpCode + " not implemented for operand "); } } } //} }
public override void Execute(_MethodInfo aMethod, ILOpCode aOpCode) { Ldelem_Ref.Assemble(Assembler, 1, true, aMethod, aOpCode, DebugEnabled); }
public override void Execute(ILOpCode instr, MethodBase aMethod) { //This is branch type IL var xOffset = ((OpBranch)instr).Value; var xSize = Core.vStack.Pop().Size; var xTrueLabel = ILHelper.GetLabel(aMethod, xOffset); var xFalseLabel = ILHelper.GetLabel(aMethod, instr.Position) + "._bge_false"; //Make a pop because exactly we are popping up two items Core.vStack.Pop(); /* * value1 is pushed onto the stack. * value2 is pushed onto the stack. * value2 and value1 are popped from the stack; * if value1 is greater than or equal to value2, the branch operation is performed. --> value1 ≥ value2 */ switch (ILCompiler.CPUArchitecture) { #region _x86_ case CPUArch.x86: { if (xSize <= 4) { //***What we are going to do is*** //1) Pop Value 2 into EAX //2) Pop Value 1 into EBX //3) Compare EBX and EAX and jump if greator than equals to Core.AssemblerCode.Add(new Pop { DestinationReg = Registers.EAX }); //value 2 Core.AssemblerCode.Add(new Pop { DestinationReg = Registers.EBX }); //value 1 Core.AssemblerCode.Add(new Cmp { DestinationReg = Registers.EBX, SourceReg = Registers.EAX }); //value1 - value2 Core.AssemblerCode.Add(new Jmp { Condition = ConditionalJumpEnum.JGE, DestinationRef = xTrueLabel }); } else if (xSize <= 8) { //***What we are going to do is*** //1) Pop value 2 low into EAX and high into EBX //2) Pop value 1 low into ECX and high into EDX //3) Compare High parts of value 1 and value 2, if less than false else if greator than jump true //4) Compare Low parts of value 1 and value 2, if greator than jump true else continue //Value 2 EBX:EAX Core.AssemblerCode.Add(new Pop { DestinationReg = Registers.EAX }); //low Core.AssemblerCode.Add(new Pop { DestinationReg = Registers.EBX }); //high //Value 1 EDX:ECX Core.AssemblerCode.Add(new Pop { DestinationReg = Registers.ECX }); //low Core.AssemblerCode.Add(new Pop { DestinationReg = Registers.EDX }); //high Core.AssemblerCode.Add(new Cmp { DestinationReg = Registers.EDX, SourceReg = Registers.EBX }); //value1_HI - value2_HI Core.AssemblerCode.Add(new Jmp { Condition = ConditionalJumpEnum.JL, DestinationRef = xFalseLabel }); Core.AssemblerCode.Add(new Jmp { Condition = ConditionalJumpEnum.JG, DestinationRef = xTrueLabel }); Core.AssemblerCode.Add(new Xor { DestinationReg = Registers.ECX, SourceReg = Registers.EAX }); //value1_LO - value2_LO Core.AssemblerCode.Add(new Jmp { Condition = ConditionalJumpEnum.JGE, DestinationRef = xTrueLabel }); Core.AssemblerCode.Add(new Label(xFalseLabel)); } else { //Not called usually throw new Exception("@Bge: Branch operation bge for size > 8 is not yet implemented"); } } break; #endregion #region _x64_ case CPUArch.x64: { } break; #endregion #region _ARM_ case CPUArch.ARM: { } break; #endregion } }
public override void Execute(_MethodInfo aMethod, ILOpCode aOpCode) { var xOpVar = (OpVar)aOpCode; DoExecute(Assembler, aMethod, xOpVar.Value); }
public override void Execute(ILOpCode instr, MethodBase aMethod) { var xSource = Core.vStack.Pop(); //Convert to int8, pushing int32 on stack. //Mean Just Convert Last 1 byte to Int32 switch (ILCompiler.CPUArchitecture) { #region _x86_ case CPUArch.x86: { switch (xSource.Size) { case 1: case 2: case 4: { if (xSource.IsFloat) { throw new Exception("Conv_I2 -> Size 4 : Float"); } else { //Just Pop into EAX, zero extend and push it. Core.AssemblerCode.Add(new Pop { DestinationReg = Registers.EAX }); Core.AssemblerCode.Add(new Movzx { DestinationReg = Registers.EAX, SourceReg = Registers.AX, Size = 16 }); Core.AssemblerCode.Add(new Push { DestinationReg = Registers.EAX }); } } break; case 8: { if (xSource.IsFloat) { throw new Exception("Conv_I2 -> Size 8 : Float"); } else { //Just Erase The 8 byte as we want only first 4 byte manily 2 byte of it. Core.AssemblerCode.Add(new Pop { DestinationReg = Registers.EAX }); Core.AssemblerCode.Add(new Add { DestinationReg = Registers.ESP, SourceRef = "0x4" }); Core.AssemblerCode.Add(new Movzx { DestinationReg = Registers.EAX, SourceReg = Registers.AX, Size = 16 }); Core.AssemblerCode.Add(new Push { DestinationReg = Registers.EAX }); } } break; default: throw new Exception("Not Yet Implemented Conv_I2 : Size" + xSource.Size); } } break; #endregion #region _x64_ case CPUArch.x64: { } break; #endregion #region _ARM_ case CPUArch.ARM: { } break; #endregion } Core.vStack.Push(4, typeof(short)); }
public override void Execute(ILOpCode instr, MethodBase aMethod) { var xSource = Core.vStack.Pop(); //Convert to int8, pushing int32 on stack. //Mean Just Convert Last 1 byte to Int32 switch (ILCompiler.CPUArchitecture) { #region _x86_ case CPUArch.x86: { switch (xSource.Size) { case 1: case 2: case 4: { if (xSource.IsFloat) { throw new Exception("Conv_I4 -> Size 4 : Float"); } else { //Not Required because it is already what we want, So Never called } } break; case 8: { if (xSource.IsFloat) { throw new Exception("Conv_I4 -> Size 8 : Float"); } else { //Just Erase The 8 byte as we want only first 4 byte. Core.AssemblerCode.Add(new Pop { DestinationReg = Registers.EAX }); Core.AssemblerCode.Add(new Add { DestinationReg = Registers.ESP, SourceRef = "0x4" }); Core.AssemblerCode.Add(new Push { DestinationReg = Registers.EAX }); } } break; default: throw new Exception("Not Yet Implemented Conv_I4 : Size" + xSource.Size); } } break; #endregion #region _x64_ case CPUArch.x64: { } break; #endregion #region _ARM_ case CPUArch.ARM: { } break; #endregion } Core.vStack.Push(4, typeof(Int32)); }