public static void DoExecute(Cosmos.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 (xArgRealSize < 4) { if (xArgRealSize == 1) { XS.MoveSignExtend(EAX, EBP, sourceIsIndirect: true, sourceDisplacement: xDisplacement, size: RegisterSize.Byte8); } else { XS.MoveSignExtend(EAX, EBP, sourceIsIndirect: true, sourceDisplacement: xDisplacement, size: RegisterSize.Short16); } XS.Push(EAX); } else { for (int i = 0; i < (xArgSize / 4); i++) { XS.Push(EBP, isIndirect: true, displacement: (xDisplacement - (i * 4))); } } }
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))); } } }
/// <summary> /// Emits cleanup code for when an exception occurred inside a method call. /// </summary> public static void EmitExceptionCleanupAfterCall(Assembler.Assembler aAssembler, uint aReturnSize, uint aStackSizeBeforeCall, uint aTotalArgumentSizeOfMethod) { XS.Comment("aStackSizeBeforeCall = " + aStackSizeBeforeCall); XS.Comment("aTotalArgumentSizeOfMethod = " + aTotalArgumentSizeOfMethod); XS.Comment("aReturnSize = " + aReturnSize); if (aReturnSize != 0) { // at least pop return size: XS.Comment("Cleanup return"); // cleanup result values for (int i = 0; i < aReturnSize / 4; i++) { XS.Add(XSRegisters.ESP, 4); } } if (aStackSizeBeforeCall > (aTotalArgumentSizeOfMethod)) { if (aTotalArgumentSizeOfMethod > 0) { var xExtraStack = aStackSizeBeforeCall - aTotalArgumentSizeOfMethod; XS.Comment("Cleanup extra stack"); // cleanup result values for (int i = 0; i < xExtraStack / 4; i++) { XS.Add(XSRegisters.ESP, 4); } } } }
public static void DoExecute(Cosmos.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 (xArgRealSize < 4) { new MoveSignExtend { DestinationReg = RegistersEnum.EAX, Size = (byte)(xArgRealSize * 8), SourceReg = RegistersEnum.EBP, SourceIsIndirect = true, SourceDisplacement = xDisplacement }; XS.Push(XSRegisters.EAX); } else { for (int i = 0; i < (xArgSize / 4); i++) { XS.Push(XSRegisters.EBP, isIndirect: true, displacement: (xDisplacement - (i * 4))); } } }
public static void Assemble(Cosmos.Assembler.Assembler aAssembler, OpType aOpType, uint aElementSize, bool debugEnabled) { XS.Comment("Arraytype: " + aOpType.StackPopTypes.Last().FullName); XS.Comment("Size: " + aElementSize); DoNullReferenceCheck(aAssembler, debugEnabled, 4); // calculate element offset into array memory (including header) XS.Pop(XSRegisters.EAX); XS.Set(XSRegisters.EDX, aElementSize); XS.Multiply(XSRegisters.EDX); XS.Add(XSRegisters.EAX, (uint)(ObjectImpl.FieldDataOffset + 4)); // pop the array now XS.Pop(XSRegisters.EDX); // translate it to actual memory XS.Set(XSRegisters.EDX, XSRegisters.EDX, sourceIsIndirect: true); if (aOpType.StackPopTypes.Last().GetElementType().IsClass) { XS.Set(XSRegisters.EDX, XSRegisters.EDX, sourceIsIndirect: true); } XS.Add(XSRegisters.EDX, XSRegisters.EAX); XS.Push(XSRegisters.EDX); }
/* * * 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 AssembleNew(Cosmos.Assembler.Assembler aAssembler, object aMethodInfo) { // method signature: $this, object @object, IntPtr method var xAssembler = aAssembler; var xMethodInfo = (_MethodInfo)aMethodInfo; XS.Comment("Save target ($this) to field"); XS.Comment("-- ldarg 0"); Ldarg.DoExecute(xAssembler, xMethodInfo, 0); XS.Comment("-- ldarg 1"); Ldarg.DoExecute(xAssembler, xMethodInfo, 1); XS.Comment("-- stfld _target"); Stfld.DoExecute(xAssembler, xMethodInfo, "System.Object System.Delegate._target", xMethodInfo.MethodBase.DeclaringType, true, false); XS.Comment("Save method pointer to field"); XS.Comment("-- ldarg 0"); Ldarg.DoExecute(xAssembler, xMethodInfo, 0); XS.Comment("-- ldarg 2"); Ldarg.DoExecute(xAssembler, xMethodInfo, 2); XS.Comment("-- stfld _methodPtr"); Stfld.DoExecute(xAssembler, xMethodInfo, "System.IntPtr System.Delegate._methodPtr", xMethodInfo.MethodBase.DeclaringType, true, false); XS.Comment("Saving ArgSize to field"); uint xSize = 0; foreach (var xArg in xMethodInfo.MethodBase.DeclaringType.GetMethod("Invoke").GetParameters()) { xSize += ILOp.Align(ILOp.SizeOfType(xArg.ParameterType), 4); } XS.Comment("-- ldarg 0"); Ldarg.DoExecute(xAssembler, xMethodInfo, 0); XS.Comment("-- push argsize"); XS.Push(xSize); XS.Comment("-- stfld ArgSize"); Stfld.DoExecute(xAssembler, xMethodInfo, "$$ArgSize$$", xMethodInfo.MethodBase.DeclaringType, true, false); }
// unsafe private static void Copy64Bytes(byte* dest, byte* src) 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); // move 128 bytes of src to 8 XMM register // move first 16 bytes of data from src to registers XS.SSE.MoveDQU(XMM0, ESI, sourceIsIndirect: true); // move second 16 bytes of data from src to registers XS.SSE.MoveDQU(XMM1, ESI, sourceIsIndirect: true, sourceDisplacement: 16); // move third 16 bytes of data from src to registers XS.SSE.MoveDQU(XMM2, ESI, sourceIsIndirect: true, sourceDisplacement: 32); // move fourth 16 bytes of data from src to registers XS.SSE.MoveDQU(XMM3, ESI, sourceIsIndirect: true, sourceDisplacement: 48); // move data from 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); }
public override void Execute(MethodInfo aMethod, ILOpCode aOpCode) { var xOpCode = (ILOpCodes.OpField)aOpCode; var xField = xOpCode.Value; XS.Comment("Operand type: " + aOpCode.StackPopTypes[1].ToString()); DoExecute(Assembler, aMethod, xField, DebugEnabled, TypeIsReferenceType(aOpCode.StackPopTypes[1])); }
public void CreateGDT() { new Comment(this, "BEGIN - Create GDT"); var xGDT = new List <byte>(); // Null Segment - Selector 0x00 // Not used, but required by many emulators. xGDT.AddRange(new byte[8] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }); // Code Segment mGdCode = (byte)xGDT.Count; xGDT.AddRange(GdtDescriptor(0x00000000, 0xFFFFFFFF, true)); // Data Segment - Selector mGdData = (byte)xGDT.Count; xGDT.AddRange(GdtDescriptor(0x00000000, 0xFFFFFFFF, false)); DataMembers.Add(new DataMember("_NATIVE_GDT_Contents", xGDT.ToArray())); XS.Comment("Tell CPU about GDT"); var xGdtPtr = new UInt16[3]; // Size of GDT Table - 1 xGdtPtr[0] = (UInt16)(xGDT.Count - 1); DataMembers.Add(new DataMember("_NATIVE_GDT_Pointer", xGdtPtr)); new Mov { DestinationRef = ElementReference.New("_NATIVE_GDT_Pointer"), DestinationIsIndirect = true, DestinationDisplacement = 2, SourceRef = ElementReference.New("_NATIVE_GDT_Contents") }; XS.Set(XSRegisters.EAX, "_NATIVE_GDT_Pointer"); XS.LoadGdt(XSRegisters.EAX, isIndirect: true); XS.Comment("Set data segments"); XS.Set(XSRegisters.EAX, mGdData); XS.Set(XSRegisters.DS, XSRegisters.AX); XS.Set(XSRegisters.ES, XSRegisters.AX); XS.Set(XSRegisters.FS, XSRegisters.AX); XS.Set(XSRegisters.GS, XSRegisters.AX); XS.Set(XSRegisters.SS, XSRegisters.AX); XS.Comment("Force reload of code segment"); new JumpToSegment { Segment = mGdCode, DestinationLabel = "Boot_FlushCsGDT" }; XS.Label("Boot_FlushCsGDT"); new Comment(this, "END - Create GDT"); }
public override void Execute(MethodInfo aMethod, ILOpCode aOpCode) { var xOpVar = (OpVar)aOpCode; var xVar = aMethod.MethodBase.GetMethodBody().LocalVariables[xOpVar.Value]; var xStackCount = GetStackCountForLocal(aMethod, xVar); var xEBPOffset = ((int)GetEBPOffsetForLocal(aMethod, xOpVar.Value)); var xSize = SizeOfType(xVar.LocalType); XS.Comment("EBPOffset = " + xEBPOffset); if (xStackCount > 1) { for (int i = 0; i < xStackCount; i++) { XS.Set(XSRegisters.EAX, XSRegisters.EBP, sourceDisplacement: (int)(0 - (xEBPOffset + (i * 4)))); XS.Push(XSRegisters.EAX); } } else { switch (xSize) { case 1: case 2: { bool signed = IsIntegerSigned(xVar.LocalType); if (signed) { new CPUx86.MoveSignExtend { DestinationReg = CPUx86.RegistersEnum.EAX, Size = (byte)(xSize * 8), SourceReg = CPUx86.RegistersEnum.EBP, SourceIsIndirect = true, SourceDisplacement = 0 - xEBPOffset } } ; else { new CPUx86.MoveZeroExtend { DestinationReg = CPUx86.RegistersEnum.EAX, Size = (byte)(xSize * 8), SourceReg = CPUx86.RegistersEnum.EBP, SourceIsIndirect = true, SourceDisplacement = 0 - xEBPOffset } }; XS.Push(XSRegisters.EAX); break; } case 4: { new CPUx86.Push { DestinationReg = CPUx86.RegistersEnum.EBP, DestinationIsIndirect = true, DestinationDisplacement = 0 - xEBPOffset }; break; } } } }
private void DoExecute(Assembler assembler, _MethodInfo aMethod, ILOpCode aOpCode, OpType aTargetType, bool debugEnabled) { var xType = aTargetType.Value; XS.Comment($"Type = {aTargetType.Value}"); if (xType.GetTypeInfo().BaseType == typeof(ValueType)) { } else if (xType.GetTypeInfo().BaseType == typeof(object)) { throw new NotImplementedException($"Constrained not implemented for {aTargetType.Value}"); } }
public static void DoExecute(Cosmos.Assembler.Assembler Assembler, MethodInfo aMethod, ushort aParam) { var xDisplacement = Ldarg.GetArgumentDisplacement(aMethod, aParam); var xType = Ldarg.GetArgumentType(aMethod, aParam); XS.Comment("Arg idx = " + aParam); XS.Comment("Arg type = " + xType); XS.Set(XSRegisters.EAX, XSRegisters.EBP); XS.Set(XSRegisters.EBX, (uint)(xDisplacement)); XS.Add(XSRegisters.EAX, XSRegisters.EBX); XS.Push(XSRegisters.EAX); }
public override void Execute(MethodInfo aMethod, ILOpCode aOpCode) { var xField = aOpCode as ILOpCodes.OpVar; var xFieldInfo = aMethod.MethodBase.GetMethodBody().LocalVariables[xField.Value]; var xEBPOffset = ((int)GetEBPOffsetForLocal(aMethod, xField.Value)); XS.Comment("EBPOffset = " + xEBPOffset); for (int i = (int)GetStackCountForLocal(aMethod, xFieldInfo) - 1; i >= 0; i--) { XS.Pop(XSRegisters.EAX); XS.Set(XSRegisters.EBP, XSRegisters.EAX, destinationDisplacement: (int)((0 - (xEBPOffset + (i * 4))))); } }
public static void Assemble(Cosmos.Assembler.Assembler aAssembler, int aSize, bool debugEnabled) { int xAlignedSize = (int)Align((uint)aSize, 4); XS.Comment("address at: [esp]"); DoNullReferenceCheck(aAssembler, debugEnabled, 0); XS.Pop(XSRegisters.EAX); for (int i = xAlignedSize - 4; i >= 0; i -= 4) { XS.Push(XSRegisters.EAX, isIndirect: true, displacement: i); } }
public static void DoExecute(Cosmos.Assembler.Assembler Assembler, MethodInfo aMethod, ushort aParam) { var xDisplacement = GetArgumentDisplacement(aMethod, aParam); Type xArgType; if (aMethod.MethodBase.IsStatic) { xArgType = aMethod.MethodBase.GetParameters()[aParam].ParameterType; } else { if (aParam == 0u) { xArgType = aMethod.MethodBase.DeclaringType; if (xArgType.IsValueType) { xArgType = xArgType.MakeByRefType(); } } else { xArgType = aMethod.MethodBase.GetParameters()[aParam - 1].ParameterType; } } XS.Comment("Arg idx = " + aParam); uint xArgRealSize = SizeOfType(xArgType); uint xArgSize = Align(xArgRealSize, 4); XS.Comment("Arg type = " + xArgType.ToString()); XS.Comment("Arg real size = " + xArgRealSize + " aligned size = " + xArgSize); if (xArgRealSize < 4) { new CPUx86.MoveSignExtend { DestinationReg = CPUx86.RegistersEnum.EAX, Size = (byte)(xArgRealSize * 8), SourceReg = CPUx86.RegistersEnum.EBP, SourceIsIndirect = true, SourceDisplacement = xDisplacement }; XS.Push(XSRegisters.EAX); } else { for (int i = 0; i < (xArgSize / 4); i++) { new Push { DestinationReg = RegistersEnum.EBP, DestinationIsIndirect = true, DestinationDisplacement = xDisplacement - (i * 4) }; } } }
private static void PushAlignedParameterSize(MethodBase aMethod) { ParameterInfo[] xParams = aMethod.GetParameters(); uint xSize; XS.Comment("[ Newobj.PushAlignedParameterSize start count = " + xParams.Length.ToString() + " ]"); for (int i = 0; i < xParams.Length; i++) { xSize = SizeOfType(xParams[i].ParameterType); XS.Add(XSRegisters.ESP, Align(xSize, 4)); } XS.Comment("[ Newobj.PushAlignedParameterSize end ]"); }
public override void Execute(MethodInfo aMethod, ILOpCode aOpCode) { #if false var xOpVar = (OpVar)aOpCode; var xDisplacement = Ldarg.GetArgumentDisplacement(aMethod, xOpVar.Value); /* * The function GetArgumentDisplacement() does not give the correct displacement for the Ldarga opcode * we need to "fix" it subtracting the argSize and 4 */ Type xArgType; if (aMethod.MethodBase.IsStatic) { xArgType = aMethod.MethodBase.GetParameters()[xOpVar.Value].ParameterType; } else { if (xOpVar.Value == 0u) { xArgType = aMethod.MethodBase.DeclaringType; if (xArgType.IsValueType) { xArgType = xArgType.MakeByRefType(); } } else { xArgType = aMethod.MethodBase.GetParameters()[xOpVar.Value - 1].ParameterType; } } uint xArgRealSize = SizeOfType(xArgType); uint xArgSize = Align(xArgRealSize, 4); XS.Comment("Arg type = " + xArgType.ToString()); XS.Comment("Arg real size = " + xArgRealSize + " aligned size = " + xArgSize); xDisplacement -= (int)(xArgSize - 4); XS.Comment("Real displacement " + xDisplacement); XS.Set(XSRegisters.EBX, (uint)(xDisplacement)); XS.Set(XSRegisters.EAX, XSRegisters.EBP); XS.Add(XSRegisters.EAX, XSRegisters.EBX); XS.Push(XSRegisters.EAX); #endif var xOpVar = (OpVar)aOpCode; DoExecute(Assembler, aMethod, xOpVar.Value); }
public override void Execute(_MethodInfo aMethod, ILOpCode aOpCode) { var xOpVar = (OpVar)aOpCode; var xVar = aMethod.MethodBase.GetLocalVariables()[xOpVar.Value]; var xEBPOffset = GetEBPOffsetForLocal(aMethod, xOpVar.Value); xEBPOffset += (uint)(((int)GetStackCountForLocal(aMethod, xVar.Type) - 1) * 4); XS.Comment("Local type = " + xVar.Type); XS.Comment("Local EBP offset = " + xEBPOffset); XS.Set(EAX, EBP); XS.Sub(EAX, xEBPOffset); XS.Push(EAX); }
public static void Assemble(Cosmos.Assembler.Assembler aAssembler, int aSize, bool debugEnabled) { int xAlignedSize = (int)Align((uint)aSize, 4); XS.Comment($"address at: [esp+{xAlignedSize}]"); DoNullReferenceCheck(aAssembler, debugEnabled, xAlignedSize); XS.Set(XSRegisters.EAX, XSRegisters.ESP, sourceIsIndirect: true, sourceDisplacement: xAlignedSize); for (int i = 0; i < xAlignedSize; i += 4) { XS.Pop(XSRegisters.EBX); XS.Set(XSRegisters.EAX, XSRegisters.EBX, destinationIsIndirect: true, destinationDisplacement: i); } XS.Add(XSRegisters.ESP, 4); }
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 static void DoExecute(Cosmos.Assembler.Assembler Assembler, MethodInfo aMethod, ushort aParam) { var xDisplacement = Ldarg.GetArgumentDisplacement(aMethod, aParam); //var xType = Ldarg.GetArgumentType(aMethod, aParam); /* * The function GetArgumentDisplacement() does not give the correct displacement for the Ldarga opcode * we need to "fix" it subtracting the argSize and 4 */ Type xArgType; if (aMethod.MethodBase.IsStatic) { xArgType = aMethod.MethodBase.GetParameters()[aParam].ParameterType; } else { if (aParam == 0u) { xArgType = aMethod.MethodBase.DeclaringType; if (xArgType.IsValueType) { xArgType = xArgType.MakeByRefType(); } } else { xArgType = aMethod.MethodBase.GetParameters()[aParam - 1].ParameterType; } } uint xArgRealSize = SizeOfType(xArgType); uint xArgSize = Align(xArgRealSize, 4); XS.Comment("Arg idx = " + aParam); XS.Comment("Arg type = " + xArgType); XS.Comment("Arg real size = " + xArgRealSize + " aligned size = " + xArgSize); xDisplacement -= (int)(xArgSize - 4); XS.Comment("Real displacement " + xDisplacement); XS.Set(XSRegisters.EAX, XSRegisters.EBP); XS.Set(XSRegisters.EBX, (uint)(xDisplacement)); XS.Add(XSRegisters.EAX, XSRegisters.EBX); XS.Push(XSRegisters.EAX); }
public override void AssembleNew(Cosmos.Assembler.Assembler aAssembler, object aMethodInfo) { // method signature: $this, object @object, IntPtr method var xMethodInfo = (MethodInfo)aMethodInfo; var xAssembler = (NewAssembler)aAssembler; XS.Comment("Save target ($this) to field"); XS.Comment("-- ldarg 0"); Ldarg.DoExecute(xAssembler, xMethodInfo, 0); //Ldarg.DoExecute(xAssembler, xMethodInfo, 0); XS.Comment("-- ldarg 1"); Ldarg.DoExecute(xAssembler, xMethodInfo, 1); XS.Comment("-- stfld _target"); Stfld.DoExecute(xAssembler, xMethodInfo, "System.Object System.Delegate._target", xMethodInfo.MethodBase.DeclaringType, true, false); XS.Comment("Save method pointer to field"); //Ldarg.DoExecute(xAssembler, xMethodInfo, 0); XS.Comment("-- ldarg 0"); Ldarg.DoExecute(xAssembler, xMethodInfo, 0); XS.Comment("-- ldarg 2"); Ldarg.DoExecute(xAssembler, xMethodInfo, 2); XS.Comment("-- stfld _methodPtr"); Stfld.DoExecute(xAssembler, xMethodInfo, "System.IntPtr System.Delegate._methodPtr", xMethodInfo.MethodBase.DeclaringType, true, false); XS.Comment("Saving ArgSize to field"); uint xSize = 0; foreach (var xArg in xMethodInfo.MethodBase.DeclaringType.GetMethod("Invoke").GetParameters()) { xSize += ILOp.Align(ILOp.SizeOfType(xArg.ParameterType), 4); } XS.Comment("-- ldarg 0"); Ldarg.DoExecute(xAssembler, xMethodInfo, 0); if (xMethodInfo.MethodBase.DeclaringType.FullName.Contains("InterruptDelegate")) { Console.Write(""); } XS.Comment("-- push argsize"); XS.Push(xSize); XS.Comment("-- stfld ArgSize"); Stfld.DoExecute(xAssembler, xMethodInfo, "$$ArgSize$$", xMethodInfo.MethodBase.DeclaringType, true, false); //public static void Ctor(Delegate aThis, object aObject, IntPtr aMethod, //[FieldAccess(Name = "System.Object System.Delegate._target")] ref object aFldTarget, //[FieldAccess(Name = "System.IntPtr System.Delegate._methodPtr")] ref IntPtr aFldMethod) { }
public override void Execute(MethodInfo aMethod, ILOpCode aOpCode) { var xOpVar = (OpVar)aOpCode; var xVar = aMethod.MethodBase.GetMethodBody().LocalVariables[xOpVar.Value]; var xStackCount = (int)GetStackCountForLocal(aMethod, xVar); var xEBPOffset = (int)GetEBPOffsetForLocal(aMethod, xOpVar.Value); var xSize = SizeOfType(xVar.LocalType); XS.Comment("Local type = " + xVar.LocalType); XS.Comment("Local EBP offset = " + xEBPOffset); XS.Comment("Local size = " + xSize); for (int i = xStackCount - 1; i >= 0; i--) { XS.Pop(EAX); XS.Set(EBP, EAX, destinationDisplacement: 0 - (xEBPOffset + (i * 4))); } }
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) { var xType = (ILOpCodes.OpType)aOpCode; uint xSize = SizeOfType(xType.Value.GetElementType() ?? xType.Value); string xTypeID = GetTypeIDLabel(xType.Value.GetElementType() ?? xType.Value); MethodBase xCtor = typeof(Array).GetConstructors(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance)[0]; string xCtorName = LabelName.Get(xCtor); XS.Comment("Element Size = " + xSize); XS.Pop(EAX); // element count XS.Push(EAX); XS.Set(EDX, xSize); XS.Multiply(EDX); // total element size XS.Add(EAX, ObjectUtils.FieldDataOffset + 4); // total array size XS.Push(EAX); //XS.Push(0x4E3A44A9); //XS.LiteralCode("Call DebugStub_SendSimpleNumber"); //XS.Pop(EAX); //XS.Push(".AfterAlloc"); //XS.LiteralCode("Call DebugStub_SendSimpleNumber"); //XS.Pop(EAX); XS.Call(LabelName.Get(GCImplementationRefs.AllocNewObjectRef)); XS.Label(".AfterAlloc"); XS.Pop(EAX); // location //XS.LiteralCode("Call DebugStub_SendSimpleNumber"); XS.Pop(ESI); // element count XS.Push(EAX); XS.Push(ESP, isIndirect: true); XS.Push(ESP, isIndirect: true); // it's on the stack 3 times now, once from the return value, twice from the pushes; XS.Pop(EAX); XS.Set(EBX, xTypeID, sourceIsIndirect: true); // array type id XS.Set(EAX, EBX, destinationIsIndirect: true); // array type id XS.Set(EAX, (uint)ObjectUtils.InstanceTypeEnum.Array, destinationDisplacement: 4, destinationIsIndirect: true); XS.Set(EAX, ESI, destinationDisplacement: 8, destinationIsIndirect: true); // element count XS.Set(EAX, xSize, destinationDisplacement: 12, destinationIsIndirect: true); // element size XS.Push(0); XS.Call(xCtorName); XS.Push(0); }
public static void Assemble(Cosmos.Assembler.Assembler aAssembler, OpType aOpType, uint aElementSize, bool debugEnabled) { XS.Comment("Arraytype: " + aOpType.StackPopTypes.Last().FullName); XS.Comment("Size: " + aElementSize); 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, (uint)(ObjectImpl.FieldDataOffset + 4)); // pop the array now XS.Add(ESP, 4); XS.Pop(EDX); XS.Add(EDX, EAX); XS.Push(EDX); }
public static void DoExecute(XSharp.Assembler.Assembler Assembler, _MethodInfo aMethod, Type aDeclaringType, _FieldInfo aField, bool aDerefValue, bool aDebugEnabled, Type aTypeOnStack) { XS.Comment("Field: " + aField.Id); int xExtraOffset = 0; bool xNeedsGC = aDeclaringType.IsClass && !aDeclaringType.IsValueType; if (xNeedsGC) { xExtraOffset = 12; } if ((!aTypeOnStack.IsPointer) && (aDeclaringType.IsClass)) { DoNullReferenceCheck(Assembler, aDebugEnabled, 4); XS.Add(ESP, 4); } else { DoNullReferenceCheck(Assembler, aDebugEnabled, 0); } if (aDerefValue && aField.IsExternalValue) { XS.Set(ESP, EAX, destinationIsIndirect: true); } else { XS.Pop(EAX); if (aDeclaringType.Name == "RawArrayData" && aField.Field.Name == "Data") { // if we accidently load 64bit assemblies, we get an incorrect extra 4 bytes of offset, so we just hardcode the offset XS.Add(EAX, (uint)(4 + xExtraOffset)); } else { XS.Add(EAX, (uint)(aField.Offset + xExtraOffset)); } XS.Push(EAX); } }
public override void Execute(MethodInfo aMethod, ILOpCode aOpCode) { var xOpVar = (OpVar)aOpCode; var xVar = aMethod.MethodBase.GetMethodBody().LocalVariables[xOpVar.Value]; var xStackCount = (int)GetStackCountForLocal(aMethod, xVar); var xEBPOffset = (int)GetEBPOffsetForLocal(aMethod, xOpVar.Value); var xSize = SizeOfType(xVar.LocalType); XS.Comment("Local type = " + xVar.LocalType); XS.Comment("Local EBP offset = " + xEBPOffset); XS.Comment("Local size = " + xSize); switch (xSize) { case 1: case 2: bool xSigned = IsIntegerSigned(xVar.LocalType); if (xSigned) { new CPUx86.MoveSignExtend { DestinationReg = CPUx86.RegistersEnum.EAX, Size = (byte)(xSize * 8), SourceReg = CPUx86.RegistersEnum.EBP, SourceIsIndirect = true, SourceDisplacement = (int)(0 - xEBPOffset) }; } else { new CPUx86.MoveZeroExtend { DestinationReg = CPUx86.RegistersEnum.EAX, Size = (byte)(xSize * 8), SourceReg = CPUx86.RegistersEnum.EBP, SourceIsIndirect = true, SourceDisplacement = (int)(0 - xEBPOffset) }; } 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; } }
// 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"); }