public override void Execute(_MethodInfo aMethod, ILOpCode aOpCode) { DoNullReferenceCheck(Assembler, DebugEnabled, 0); XS.Pop(ECX); XS.MoveZeroExtend(EAX, ECX, sourceIsIndirect: true, size: RegisterSize.Short16); XS.Push(EAX); }
public static void DoExecute(XSharp.Assembler.Assembler Assembler, _MethodInfo aMethod, ushort aParam) { var xDisplacement = GetArgumentDisplacement(aMethod, aParam); var xType = GetArgumentType(aMethod, aParam); uint xArgRealSize = SizeOfType(xType); uint xArgSize = Align(xArgRealSize, 4); XS.Comment("Arg idx = " + aParam); XS.Comment("Arg type = " + xType); XS.Comment("Arg real size = " + xArgRealSize + " aligned size = " + xArgSize); if (IsIntegralType(xType) && xArgRealSize == 1 || xArgRealSize == 2) { if (TypeIsSigned(xType)) { XS.MoveSignExtend(EAX, EBP, sourceIsIndirect: true, sourceDisplacement: xDisplacement, size: (RegisterSize)(8 * xArgRealSize)); } else { XS.MoveZeroExtend(EAX, EBP, sourceIsIndirect: true, sourceDisplacement: xDisplacement, size: (RegisterSize)(8 * xArgRealSize)); } XS.Push(EAX); } else { for (int i = 0; i < (xArgSize / 4); i++) { XS.Push(EBP, isIndirect: true, displacement: (xDisplacement - (i * 4))); } } }
public override void Execute(_MethodInfo aMethod, ILOpCode aOpCode) { var xSource = aOpCode.StackPopTypes[0]; var xSourceIsFloat = TypeIsFloat(xSource); var xSourceSize = SizeOfType(xSource); if (xSourceIsFloat) { if (xSourceSize == 4) { XS.SSE.MoveSS(XMM0, ESP, sourceIsIndirect: true); XS.SSE.ConvertSS2SIAndTruncate(EAX, XMM0); XS.Set(ESP, EAX, destinationIsIndirect: true); } else if (xSourceSize == 8) { XS.SSE2.MoveSD(XMM0, ESP, sourceIsIndirect: true); XS.SSE2.ConvertSD2SIAndTruncate(EAX, XMM0); // We need to move the stack pointer of 4 Byte to "eat" the second double that is yet in the stack or we get a corrupted stack! XS.Add(ESP, 4); XS.Set(ESP, EAX, destinationIsIndirect: true); } else { throw new Exception("Cosmos.IL2CPU.x86->IL->Conv_U1.cs->Unknown size of floating point value."); } } else { switch (xSourceSize) { case 1: case 2: case 4: { XS.Pop(EAX); XS.MoveZeroExtend(EAX, AL); XS.Push(EAX); break; } case 8: { XS.Pop(EAX); XS.Pop(ECX); XS.MoveZeroExtend(EAX, AL); XS.Push(EAX); break; } default: //EmitNotImplementedException( Assembler, GetServiceProvider(), "Conv_I1: SourceSize " + xSource + " not supported", mCurLabel, mMethodInformation, mCurOffset, mNextLabel ); throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Conv_U1.cs->Unknown size of variable on the top of the stack."); } } }
public override void Execute(MethodInfo aMethod, ILOpCode aOpCode) { var xSource = aOpCode.StackPopTypes[0]; var xSourceIsFloat = TypeIsFloat(xSource); var xSourceSize = SizeOfType(xSource); if (xSourceIsFloat) { if (xSourceSize == 4) { new CPUx86.SSE.MoveSS { SourceReg = CPUx86.RegistersEnum.ESP, DestinationReg = CPUx86.RegistersEnum.XMM0, SourceIsIndirect = true }; XS.SSE.ConvertSS2SIAndTruncate(XSRegisters.EAX, XSRegisters.XMM0); XS.Set(XSRegisters.ESP, XSRegisters.EAX, destinationIsIndirect: true); } else if (xSourceSize == 8) { XS.SSE3.MoveDoubleAndDuplicate(XSRegisters.XMM0, XSRegisters.ESP, sourceIsIndirect: true); XS.SSE2.ConvertSD2SIAndTruncate(XSRegisters.EAX, XSRegisters.XMM0); XS.Set(XSRegisters.ESP, XSRegisters.EAX, destinationIsIndirect: true); } else { throw new Exception("Cosmos.IL2CPU.x86->IL->Conv_U1.cs->Unknown size of floating point value."); } } else { switch (xSourceSize) { case 1: case 2: case 4: { XS.Pop(XSRegisters.EAX); XS.MoveZeroExtend(XSRegisters.EAX, XSRegisters.AL); XS.Push(XSRegisters.EAX); break; } case 8: { XS.Pop(XSRegisters.EAX); XS.Pop(XSRegisters.ECX); XS.MoveZeroExtend(XSRegisters.EAX, XSRegisters.AL); XS.Push(XSRegisters.EAX); break; } default: //EmitNotImplementedException( Assembler, GetServiceProvider(), "Conv_I1: SourceSize " + xSource + " not supported", mCurLabel, mMethodInformation, mCurOffset, mNextLabel ); throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Conv_U1.cs->Unknown size of variable on the top of the stack."); } } }
public static void DoExecute(uint xSourceSize, bool xSourceIsFloat, bool xSourceIsSigned, bool checkOverflow, Assembler assembler, _MethodInfo aMethod, ILOpCode aOpCode) { var xBaseLabel = GetLabel(aMethod, aOpCode) + "."; var xSuccessLabel = xBaseLabel + "Success"; var xOverflowLabel = xBaseLabel + "Overflow"; var xPositiveLabel = xBaseLabel + "Positive"; var xNegativeLabel = xBaseLabel + "Negative"; if (xSourceSize <= 4) { if (xSourceIsFloat) { XS.SSE.MoveSS(XMM0, ESP, sourceIsIndirect: true); XS.SSE.ConvertSS2SIAndTruncate(EAX, XMM0); XS.MoveZeroExtend(EAX, AX); XS.Set(ESP, EAX, destinationIsIndirect: true); } else { if (checkOverflow) { ConvOverflowChecks.CheckOverflowForSmall(2, xSourceIsSigned, false, assembler, aMethod, aOpCode, xSuccessLabel, xOverflowLabel); } XS.Pop(EAX); XS.MoveZeroExtend(EAX, AX); XS.Push(EAX); } } else if (xSourceSize <= 8) { if (xSourceIsFloat) { XS.SSE2.MoveSD(XMM0, ESP, sourceIsIndirect: true); XS.Add(ESP, 4); XS.SSE2.ConvertSD2SIAndTruncate(EAX, XMM0); XS.MoveZeroExtend(EAX, AX); XS.Set(ESP, EAX, destinationIsIndirect: true); } else { if (checkOverflow) { ConvOverflowChecks.CheckOverflowForLong(2, xSourceIsSigned, false, assembler, aMethod, aOpCode, xSuccessLabel, xOverflowLabel, xPositiveLabel, xNegativeLabel); } XS.Pop(EAX); XS.Add(ESP, 4); XS.MoveZeroExtend(EAX, AX); XS.Push(EAX); } } else { throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Conv_U2.cs->Error: StackSize > 8 not supported"); } }
public override void Execute(_MethodInfo aMethod, ILOpCode aOpCode) { var xOpVar = (OpVar)aOpCode; var xVar = aMethod.MethodBase.GetLocalVariables()[xOpVar.Value]; var xStackCount = (int)GetStackCountForLocal(aMethod, xVar.LocalType); var xEBPOffset = (int)GetEBPOffsetForLocal(aMethod, xOpVar.Value); var xSize = SizeOfType(xVar.LocalType); bool xSigned = IsIntegerSigned(xVar.LocalType); XS.Comment("Local type = " + xVar.LocalType); XS.Comment("Local EBP offset = " + xEBPOffset); XS.Comment("Local size = " + xSize); switch (xSize) { case 1: if (xSigned) { XS.MoveSignExtend(EAX, EBP, sourceIsIndirect: true, sourceDisplacement: (0 - xEBPOffset), size: RegisterSize.Byte8); } else { XS.MoveZeroExtend(EAX, EBP, sourceIsIndirect: true, sourceDisplacement: (0 - xEBPOffset), size: RegisterSize.Byte8); } XS.Push(EAX); break; case 2: if (xSigned) { XS.MoveSignExtend(EAX, EBP, sourceIsIndirect: true, sourceDisplacement: (0 - xEBPOffset), size: RegisterSize.Short16); } else { XS.MoveZeroExtend(EAX, EBP, sourceIsIndirect: true, sourceDisplacement: (0 - xEBPOffset), size: RegisterSize.Short16); } XS.Push(EAX); break; default: for (int i = 0; i < xStackCount; i++) { XS.Set(EAX, EBP, sourceDisplacement: 0 - (xEBPOffset + (i * 4))); XS.Push(EAX); } break; } }
public override void Execute(_MethodInfo aMethod, ILOpCode aOpCode) { var xSource = aOpCode.StackPopTypes[0]; var xSourceSize = SizeOfType(xSource); var xSourceIsFloat = TypeIsFloat(xSource); if (xSourceSize <= 4) { if (xSourceIsFloat) { XS.SSE.MoveSS(XMM0, ESP, sourceIsIndirect: true); XS.SSE.ConvertSS2SIAndTruncate(EAX, XMM0); XS.MoveZeroExtend(EAX, AX); XS.Set(ESP, EAX, destinationIsIndirect: true); } else { XS.Pop(EAX); XS.MoveZeroExtend(EAX, AX); XS.Push(EAX); } } else if (xSourceSize <= 8) { if (xSourceIsFloat) { XS.SSE2.MoveSD(XMM0, ESP, sourceIsIndirect: true); XS.Add(ESP, 4); XS.SSE2.ConvertSD2SIAndTruncate(EAX, XMM0); XS.MoveZeroExtend(EAX, AX); XS.Set(ESP, EAX, destinationIsIndirect: true); } else { XS.Pop(EAX); XS.Add(ESP, 4); XS.MoveZeroExtend(EAX, AX); XS.Push(EAX); } } else { throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Conv_U2.cs->Error: StackSize > 8 not supported"); } }
public override void Execute(_MethodInfo aMethod, ILOpCode aOpCode) { DoNullReferenceCheck(Assembler, DebugEnabled, 0); XS.Pop(EAX); switch (aOpCode.OpCode) { case ILOpCode.Code.Ldind_I1: XS.MoveSignExtend(EAX, EAX, sourceIsIndirect: true, size: RegisterSize.Byte8); XS.Push(EAX); break; case ILOpCode.Code.Ldind_I2: XS.MoveSignExtend(EAX, EAX, sourceIsIndirect: true, size: RegisterSize.Short16); XS.Push(EAX); break; case ILOpCode.Code.Ldind_U1: XS.MoveZeroExtend(EAX, EAX, sourceIsIndirect: true, size: RegisterSize.Byte8); XS.Push(EAX); break; case ILOpCode.Code.Ldind_U2: XS.MoveZeroExtend(EAX, EAX, sourceIsIndirect: true, size: RegisterSize.Short16); XS.Push(EAX); break; case ILOpCode.Code.Ldind_I: case ILOpCode.Code.Ldind_I4: case ILOpCode.Code.Ldind_U4: case ILOpCode.Code.Ldind_R4: XS.Push(EAX, isIndirect: true); break; case ILOpCode.Code.Ldind_I8: case ILOpCode.Code.Ldind_R8: case ILOpCode.Code.Ldind_Ref: XS.Push(EAX, displacement: 4); XS.Push(EAX, isIndirect: true); break; } }
public override void Execute(_MethodInfo aMethod, ILOpCode aOpCode) { var xOpCode = (OpField)aOpCode; var xStackType = aOpCode.StackPopTypes[0]; var xFieldInfo = ResolveField(xOpCode.Value); var xDeclaringType = xFieldInfo.DeclaringType; var xFieldType = xFieldInfo.FieldType; var xOffset = GetFieldOffset(xFieldInfo); XS.Comment("Field: " + xFieldInfo.Id); XS.Comment("Type: " + xFieldInfo.FieldType.ToString()); XS.Comment("Size: " + xFieldInfo.Size); XS.Comment("DeclaringType: " + xDeclaringType.FullName); XS.Comment("TypeOnStack: " + xStackType.FullName); XS.Comment("Offset: " + xOffset + " (includes object header)"); if (xDeclaringType.IsValueType && MemberInfoComparer.Instance.Equals(xDeclaringType, xStackType)) { var xDeclaringTypeStackSize = Align(SizeOfType(xDeclaringType), 4); var xFieldSize = xFieldInfo.Size; var xStackOffset = (int)(-xDeclaringTypeStackSize + xOffset + xFieldSize - 4); XS.Add(ESP, xDeclaringTypeStackSize); if ((xFieldInfo.Size < 4 && IsIntegerBasedType(xFieldType)) || xFieldType == typeof(bool) || xFieldType == typeof(char)) { if (TypeIsSigned(xFieldType)) { XS.MoveSignExtend(EAX, ESP, sourceDisplacement: xStackOffset + (4 - (int)xFieldSize), size: (RegisterSize)(8 * xFieldSize)); XS.Push(EAX); } else { XS.MoveZeroExtend(EAX, ESP, sourceDisplacement: xStackOffset + (4 - (int)xFieldSize), size: (RegisterSize)(8 * xFieldSize)); XS.Push(EAX); } return; } for (int i = 0; i < xFieldSize / 4; i++) { XS.Push(ESP, displacement: xStackOffset); } switch (xFieldSize % 4) { case 0: break; case 1: XS.Xor(EAX, EAX); XS.Set(AL, ESP, sourceDisplacement: xStackOffset + 3); XS.Push(EAX); break; case 2: XS.Xor(EAX, EAX); XS.Set(AX, ESP, sourceDisplacement: xStackOffset + 2); XS.Push(EAX); break; case 3: XS.Xor(EAX, EAX); XS.Set(AX, ESP, sourceDisplacement: xStackOffset + 2); XS.ShiftLeft(EAX, 4); XS.Set(AL, ESP, sourceDisplacement: xStackOffset + 1); XS.Push(EAX); break; default: throw new NotImplementedException(); } return; } // pushed size is always 4 or 8 var xSize = xFieldInfo.Size; if (IsReferenceType(xStackType)) { DoNullReferenceCheck(Assembler, DebugEnabled, 4); XS.Add(ESP, 4); } else { DoNullReferenceCheck(Assembler, DebugEnabled, 0); } XS.Pop(ECX); XS.Add(ECX, (uint)(xOffset)); if (xFieldInfo.IsExternalValue) { XS.Set(ECX, ECX, sourceIsIndirect: true); } for (int i = 1; i <= (xSize / 4); i++) { XS.Set(EAX, ECX, sourceDisplacement: (int)(xSize - (i * 4))); XS.Push(EAX); } if (xSize % 4 != 0) { XS.Set(EAX, 0); } switch (xSize % 4) { case 1: XS.Set(AL, ECX, sourceIsIndirect: true); XS.Push(EAX); break; case 2: XS.Set(AX, ECX, sourceIsIndirect: true); XS.Push(EAX); break; case 3: //For Release XS.Set(EAX, ECX, sourceIsIndirect: true); XS.ShiftRight(EAX, 8); XS.Push(EAX); break; case 0: { break; } default: throw new Exception(string.Format("Remainder size {0} {1:D} not supported!", xFieldInfo.FieldType.ToString(), xSize)); } }
public static void Assemble(Assembler aAssembler, uint aElementSize, bool isSigned, _MethodInfo aMethod, ILOpCode aOpCode, bool debugEnabled) { // stack = index // stack + 2 = array DoNullReferenceCheck(aAssembler, debugEnabled, 8); // calculate element offset into array memory (including header) XS.Pop(EAX); XS.Set(EDX, aElementSize); XS.Multiply(EDX); XS.Add(EAX, ObjectUtils.FieldDataOffset + 4); if (aElementSize > 4) { // we start copying the last bytes XS.Add(EAX, aElementSize - 4); } // pop the array now XS.Add(ESP, 4); XS.Pop(EDX); XS.Add(EDX, EAX); var xSizeLeft = aElementSize; while (xSizeLeft > 0) { var xCurrentStep = Math.Min(xSizeLeft, 4); if (xSizeLeft % 4 != 0) { xCurrentStep = xSizeLeft % 4; } xSizeLeft = xSizeLeft - xCurrentStep; switch (xCurrentStep) { case 1: if (isSigned) { XS.MoveSignExtend(ECX, EDX, sourceIsIndirect: true, size: RegisterSize.Byte8); } else { XS.MoveZeroExtend(ECX, EDX, sourceIsIndirect: true, size: RegisterSize.Byte8); } XS.Push(ECX); break; case 2: if (isSigned) { XS.MoveSignExtend(ECX, EDX, sourceIsIndirect: true, size: RegisterSize.Short16); } else { XS.MoveZeroExtend(ECX, EDX, sourceIsIndirect: true, size: RegisterSize.Short16); } XS.Push(ECX); break; case 4: // copy a full dword XS.Push(EDX, true); XS.Sub(EDX, 4); // move to previous 4 bytes break; //case 8: // new CPUx86.Push {DestinationReg = CPUx86.Registers.EDX, DestinationDisplacement = 4, DestinationIsIndirect = true}; // XS.Push(XSRegisters.EDX, isIndirect: true); // break; } } }
public static void Assemble(Assembler aAssembler, uint aElementSize, bool isSigned, _MethodInfo aMethod, ILOpCode aOpCode, bool debugEnabled) { // stack = index // stack + 2 = array DoNullReferenceCheck(aAssembler, debugEnabled, 8); 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, ObjectUtils.FieldDataOffset + 4); if (aElementSize > 4) { // we start copying the last bytes XS.Add(EAX, aElementSize - 4); } // pop the array now XS.Add(ESP, 4); XS.Pop(EDX); XS.Add(EDX, EAX); var xSizeLeft = aElementSize; while (xSizeLeft > 0) { var xCurrentStep = Math.Min(xSizeLeft, 4); if (xSizeLeft % 4 != 0) { xCurrentStep = xSizeLeft % 4; } xSizeLeft = xSizeLeft - xCurrentStep; switch (xCurrentStep) { case 1: if (isSigned) { XS.MoveSignExtend(ECX, EDX, sourceIsIndirect: true, size: RegisterSize.Byte8); } else { XS.MoveZeroExtend(ECX, EDX, sourceIsIndirect: true, size: RegisterSize.Byte8); } XS.Push(ECX); break; case 2: if (isSigned) { XS.MoveSignExtend(ECX, EDX, sourceIsIndirect: true, size: RegisterSize.Short16); } else { XS.MoveZeroExtend(ECX, EDX, sourceIsIndirect: true, size: RegisterSize.Short16); } XS.Push(ECX); break; case 4: // copy a full dword XS.Push(EDX, true); XS.Sub(EDX, 4); // move to previous 4 bytes break; //case 8: // new CPUx86.Push {DestinationReg = CPUx86.Registers.EDX, DestinationDisplacement = 4, DestinationIsIndirect = true}; // XS.Push(XSRegisters.EDX, isIndirect: true); // break; } } }