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); }
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 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 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) { 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 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 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)); }
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 override void Execute(_MethodInfo aMethod, ILOpCode aOpCode) { ILOpCodes.OpSwitch OpSw = (ILOpCodes.OpSwitch)aOpCode; XS.Pop(XSRegisters.EAX); for (int i = 0; i < OpSw.BranchLocations.Length; i++) { XS.Compare(XSRegisters.EAX, ( uint )i); //string DestLabel = AssemblerNasm.TmpBranchLabel( aMethod, new ILOpCodes.OpBranch( ILOpCode.Code.Jmp, aOpCode.Position, OpSw.BranchLocations[ i ] ) ); string xDestLabel = AppAssembler.TmpPosLabel(aMethod, OpSw.BranchLocations[i]); XS.Jump(CPUx86.ConditionalTestEnum.Equal, xDestLabel); } }
public override void Execute(_MethodInfo aMethod, ILOpCode aOpCode) { // apparently, Roslyn changed something to the output. We now have to figure out where to jump to. if (aOpCode.CurrentExceptionRegion.Kind.HasFlag(ExceptionRegionKind.Finally) && aOpCode.CurrentExceptionRegion.HandlerOffset > aOpCode.Position) { XS.Set(aMethod.MethodBase.GetFullName() + "_" + "LeaveAddress_" + aOpCode.CurrentExceptionRegion.HandlerOffset.ToString("X2"), Assembler.CurrentIlLabel + "." + (Assembler.AsmIlIdx + 2).ToString("X2"), destinationIsIndirect: true, size: RegisterSize.Int32); XS.Jump(AppAssembler.TmpPosLabel(aMethod, aOpCode.CurrentExceptionRegion.HandlerOffset)); } XS.Jump(AppAssembler.TmpBranchLabel(aMethod, aOpCode)); }
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) { 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 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) { string jumpTarget = AppAssembler.TmpBranchLabel(aMethod, aOpCode); // apparently, Roslyn changed something to the output. We now have to figure out where to jump to. if (aOpCode.CurrentExceptionRegion.Kind.HasFlag(ExceptionRegionKind.Finally) && aOpCode.CurrentExceptionRegion.HandlerOffset > aOpCode.Position) { string destination = $"{aMethod.MethodBase.GetFullName()}_LeaveAddress_{aOpCode.CurrentExceptionRegion.HandlerOffset:X2}"; string source = AppAssembler.TmpBranchLabel(aMethod, aOpCode); XS.Set(destination, source, destinationIsIndirect: true, size: RegisterSize.Int32); XS.Jump(AppAssembler.TmpPosLabel(aMethod, aOpCode.CurrentExceptionRegion.HandlerOffset)); } else { XS.Jump(jumpTarget); } }
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 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 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 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 override void Execute(_MethodInfo aMethod, ILOpCode aOpCode) { var xStackType = aOpCode.StackPopTypes[0]; var xNoThrowLabel = GetLabel(aMethod, aOpCode) + ".NoThrow"; switch (SizeOfType(xStackType)) { case 4: XS.Pop(EAX); XS.And(EAX, 0x7FFFFFFF); XS.Compare(EAX, 0x7F800000); XS.Jump(ConditionalTestEnum.Below, xNoThrowLabel); XS.SSE2.ConvertSS2SD(XMM0, EAX); XS.Sub(ESP, 8); XS.SSE2.MoveSD(ESP, XMM0, true); break; case 8: XS.Set(EAX, ESP, sourceDisplacement: 4); XS.And(EAX, 0x7FFFFFFF); XS.Compare(EAX, 0x7F800000); XS.Jump(ConditionalTestEnum.Below, xNoThrowLabel); break; default: throw new NotImplementedException(); } XS.Call(LabelName.Get(ExceptionHelperRefs.ThrowNotFiniteNumberExceptionRef)); XS.Label(xNoThrowLabel); }
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(); } }
protected static void DoNullReferenceCheck(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); XS.Set(AsmMarker.Labels[AsmMarker.Type.DebugStub_CallerEIP], XSRegisters.EAX, destinationIsIndirect: true); XS.Call(AsmMarker.Labels[AsmMarker.Type.DebugStub_SendNullRefEvent]); //} XS.Halt(); XS.Label(".AfterNullCheck"); } }
public override void AssembleNew(Assembler aAssembler, object aMethodInfo) { XS.ClearDirectionFlag(); XS.Set(EDI, EBP, sourceDisplacement: 0xC); //address XS.Set(ECX, EBP, sourceDisplacement: 0x8); //length //XS.Set(EAX, 0x1000); //XS.Compare(EAX, ECX); //XS.Jump(x86.ConditionalTestEnum.GreaterThan, ".AfterSizeCheck"); //XS.Exchange(BX, BX); //XS.Label(".AfterSizeCheck"); // set EAX to value of fill (zero) XS.Xor(EAX, EAX); XS.ShiftRight(ECX, 1); XS.Jump(x86.ConditionalTestEnum.NotBelow, ".step2"); XS.StoreByteInString(); XS.Label(".step2"); XS.ShiftRight(ECX, 1); XS.Jump(x86.ConditionalTestEnum.NotBelow, ".step3"); XS.StoreWordInString(); XS.Label(".step3"); new x86.Stos { Size = 32, Prefixes = x86.InstructionPrefixes.Repeat }; }
public override void AssembleNew(Cosmos.Assembler.Assembler aAssembler, object aMethodInfo) { new CPUx86.ClrInterruptFlag(); /* Clear all keyboard buffers (output and command buffers) */ new CPUAll.Label(".waitBuffer"); XS.Mov(XSRegisters.DX, 0x64); XS.InFromDX(XSRegisters.AL); XS.Test(XSRegisters.AL, 2); XS.Jump(ConditionalTestEnum.NotEqual, ".waitBuffer"); XS.Mov(XSRegisters.AL, 0xD1); XS.Mov(XSRegisters.DX, 0x64); XS.OutToDX(XSRegisters.AL); new CPUAll.Label(".clearBuffer"); XS.Mov(XSRegisters.DX, 0x64); XS.InFromDX(XSRegisters.AL); XS.Test(XSRegisters.AL, 2); XS.Jump(ConditionalTestEnum.NotEqual, ".clearBuffer"); XS.Mov(XSRegisters.AL, 0xFE); XS.Mov(XSRegisters.DX, 0x60); XS.OutToDX(XSRegisters.AL); new CPUAll.Label(".loop");//failed... halt XS.Halt(); XS.Jump(".loop"); }
public override void Execute(MethodInfo aMethod, ILOpCode aOpCode) { var xStackItem_ShiftAmount = aOpCode.StackPopTypes[0]; var xStackItem_Value = aOpCode.StackPopTypes[1]; var xStackItem_Value_Size = SizeOfType(xStackItem_Value); XS.Pop(XSRegisters.ECX); // shift amount #if DOTNETCOMPATIBLE if (xStackItem_Value.Size == 4) #else if (xStackItem_Value_Size <= 4) #endif { XS.ShiftRight(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 HighPartIsZero = BaseLabel + "HighPartIsZero"; string End_Shr = BaseLabel + "End_Shr"; // [ESP] is low part // [ESP + 4] is high part // move high part in EAX XS.Set(XSRegisters.EAX, XSRegisters.ESP, sourceDisplacement: 4); XS.Compare(XSRegisters.CL, 32, size: RegisterSize.Byte8); XS.Jump(CPU.ConditionalTestEnum.AboveOrEqual, HighPartIsZero); // shift lower part XS.ShiftRightDouble(ESP, EAX, CL, destinationIsIndirect: true); // shift higher part XS.ShiftRight(ESP, CL, destinationDisplacement: 4, size: RegisterSize.Int32); XS.Jump(End_Shr); XS.Label(HighPartIsZero); // remove bits >= 32, so that CL max value could be only 31 XS.And(XSRegisters.CL, 0x1f, size: RegisterSize.Byte8); // shift high part and move it in low part XS.ShiftRight(XSRegisters.EAX, XSRegisters.CL); XS.Set(ESP, EAX, destinationIsIndirect: true); // replace unknown high part with a zero new CPUx86.Mov { DestinationReg = CPUx86.RegistersEnum.ESP, DestinationIsIndirect = true, DestinationDisplacement = 4, SourceValue = 0 }; XS.Label(End_Shr); } else { throw new NotSupportedException("A size bigger 8 not supported at Shr!"); } /*string xLabelName = AppAssembler.TmpPosLabel(aMethod, aOpCode); * var xStackItem_ShiftAmount = Assembler.Stack.Pop(); * var xStackItem_Value = Assembler.Stack.Peek(); * if( xStackItem_Value.Size <= 4 ) * { * XS.Pop(XSRegisters.ECX); // shift amount * XS.ShiftRight(XSRegisters.ESP, XSRegisters.CL, destinationIsIndirect: true); * } * else if( xStackItem_Value.Size <= 8 ) * { * XS.Pop(XSRegisters.ECX); // shift amount * // [ESP] is high part * // [ESP + 4] is low part * XS.Mov(XSRegisters.EAX, XSRegisters.ESP, sourceDisplacement: 4); * // shift low part * new CPUx86.ShiftRightDouble { DestinationReg = CPUx86.Registers.ESP, DestinationIsIndirect = true, SourceReg = CPUx86.Registers.EAX, ArgumentReg = CPUx86.Registers.CL }; * // shift high part * XS.ShiftRight(XSRegisters.ESP, XSRegisters.CL, destinationIsIndirect: true, size: RegisterSize.Int32); * }*/ #if false XS.Pop(XSRegisters.ECX); // shift amount 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) { string BaseLabel = GetLabel(aMethod, aOpCode) + "."; string HighPartIsZero = BaseLabel + "HighPartIsZero"; string End_Shr = BaseLabel + "End_Shr"; // [ESP] is low part // [ESP + 4] is high part // move high part in EAX XS.Set(XSRegisters.EAX, XSRegisters.ESP, sourceDisplacement: 4); XS.Compare(XSRegisters.CL, 32, size: RegisterSize.Byte8); XS.Jump(CPU.ConditionalTestEnum.AboveOrEqual, HighPartIsZero); // shift lower part XS.ShiftRightDouble(ESP, EAX, CL, destinationIsIndirect: true); // shift higher part XS.ShiftRight(ESP, CL, destinationDisplacement: 4, size: RegisterSize.Int32); XS.Jump(End_Shr); XS.Label(HighPartIsZero); // remove bits >= 32, so that CL max value could be only 31 XS.And(XSRegisters.CL, 0x1f, size: RegisterSize.Byte8); // shift high part and move it in low part XS.ShiftRight(XSRegisters.EAX, XSRegisters.CL); XS.Set(ESP, EAX, destinationIsIndirect: true); // replace unknown high part with a zero, if <= 32 new CPUx86.Mov { DestinationReg = CPUx86.RegistersEnum.ESP, DestinationIsIndirect = true, DestinationDisplacement = 4, SourceValue = 0 }; XS.Label(End_Shr); #if false 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"); #endif return; #endif } }