public override void Execute( MethodInfo aMethod, ILOpCode aOpCode ) { var xFieldSize = SizeOfType(aOpCode.StackPopTypes[0]); var xRoundedSize = Align(xFieldSize, 4); DoNullReferenceCheck(Assembler, DebugEnabled, (int)xRoundedSize); XS.Set(XSRegisters.ECX, XSRegisters.ESP, sourceDisplacement: checked((int)xRoundedSize)); for( int i = 0; i < ( xFieldSize / 4 ); i++ ) { XS.Pop(XSRegisters.EAX); XS.Set(XSRegisters.ECX, XSRegisters.EAX, destinationDisplacement: i * 4); } switch( xFieldSize % 4 ) { case 1: { XS.Pop(XSRegisters.EAX); new CPUx86.Mov { DestinationReg = CPUx86.RegistersEnum.ECX, DestinationIsIndirect = true, DestinationDisplacement = checked((int)( xFieldSize / 4 ) * 4 ), SourceReg = CPUx86.RegistersEnum.AL }; break; } case 2: { XS.Pop(XSRegisters.EAX); new CPUx86.Mov { DestinationReg = CPUx86.RegistersEnum.ECX, DestinationIsIndirect = true, DestinationDisplacement = checked((int)( xFieldSize / 4 ) * 4 ), SourceReg = CPUx86.RegistersEnum.AX }; break; } case 0: { break; } default: throw new Exception( "Remainder size " + ( xFieldSize % 4 ) + " not supported!" ); } XS.Add(XSRegisters.ESP, 4); }
public static void DoExecute(uint aSize, bool aIsFloat) { if (aSize <= 4) { if (aIsFloat) { XS.SSE.MoveSS(XMM0, ESP, sourceIsIndirect: true); XS.SSE.ConvertSS2SIAndTruncate(EAX, XMM0); XS.Set(ESP, EAX, destinationIsIndirect: true); } } else if (aSize <= 8) { if (aIsFloat) { XS.SSE2.MoveSD(XMM0, ESP, sourceIsIndirect: true); XS.Add(ESP, 4); XS.SSE2.ConvertSD2SIAndTruncate(EAX, XMM0); XS.Set(ESP, EAX, destinationIsIndirect: true); } else { XS.Pop(EAX); XS.Add(ESP, 4); XS.Push(EAX); } } else { throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Conv_U4.cs->Error: StackSize > 8 not supported"); } }
public static void InitializeArray(Array array, RuntimeFieldHandle fldHandle) { // Arguments: // Array aArray, RuntimeFieldHandle aFieldHandle XS.Set(XSRegisters.EDI, XSRegisters.EBP, sourceDisplacement: 0xC); // array XS.Set(EDI, EDI, sourceIsIndirect: true); XS.Set(XSRegisters.ESI, XSRegisters.EBP, sourceDisplacement: 8); // aFieldHandle XS.Add(XSRegisters.EDI, 8); XS.Push(EDI, isIndirect: true); XS.Add(XSRegisters.EDI, 4); XS.Set(EAX, EDI, sourceIsIndirect: true); XS.Multiply(ESP, isIndirect: true, size: RegisterSize.Int32); XS.Pop(XSRegisters.ECX); XS.Set(XSRegisters.ECX, XSRegisters.EAX); XS.Set(XSRegisters.EAX, 0); XS.Add(XSRegisters.EDI, 4); XS.Label(".StartLoop"); XS.Set(DL, ESI, sourceIsIndirect: true); XS.Set(EDI, DL, destinationIsIndirect: true); XS.Add(XSRegisters.EAX, 1); XS.Add(XSRegisters.ESI, 1); XS.Add(XSRegisters.EDI, 1); XS.Compare(XSRegisters.EAX, XSRegisters.ECX); XS.Jump(CPUx86.ConditionalTestEnum.Equal, ".EndLoop"); XS.Jump(".StartLoop"); XS.Label(".EndLoop"); }
public override void Execute(MethodInfo aMethod, ILOpCode aOpCode) { OpType xType = ( OpType )aOpCode; string xTypeID = GetTypeIDLabel(xType.Value); string mReturnNullLabel = GetLabel(aMethod, aOpCode) + "_ReturnNull"; XS.Set(XSRegisters.EAX, XSRegisters.ESP, sourceIsIndirect: true); XS.Compare(XSRegisters.EAX, 0); XS.Jump(CPUx86.ConditionalTestEnum.Zero, mReturnNullLabel); // EAX contains a memory handle now. Lets convert it to a pointer XS.Set(XSRegisters.EAX, XSRegisters.EAX, sourceIsIndirect: true); //XS.Mov(XSRegisters.EAX, XSRegisters.EAX, sourceIsIndirect: true); XS.Push(XSRegisters.EAX, isIndirect: true); XS.Push(xTypeID, isIndirect: true); SysReflection.MethodBase xMethodIsInstance = ReflectionUtilities.GetMethodBase(typeof(VTablesImpl), "IsInstance", "System.UInt32", "System.UInt32"); //, new OpMethod( ILOpCode.Code.Call, aOpCode.Position, aOpCode.NextPosition, xMethodIsInstance, aOpCode.CurrentExceptionHandler)); Call.DoExecute(Assembler, aMethod, xMethodIsInstance, aOpCode, GetLabel(aMethod, aOpCode), GetLabel(aMethod, aOpCode) + "_After_IsInstance_Call", DebugEnabled); new Label(GetLabel(aMethod, aOpCode) + "_After_IsInstance_Call"); XS.Pop(XSRegisters.EAX); XS.Compare(XSRegisters.EAX, 0); XS.Jump(CPUx86.ConditionalTestEnum.Equal, mReturnNullLabel); // push nothing now, as we should return the object instance pointer. new CPUx86.Jump { DestinationLabel = GetLabel(aMethod, aOpCode.NextPosition) }; XS.Label(mReturnNullLabel); XS.Add(XSRegisters.ESP, 4); XS.Push(0); }
public override void AssembleNew(Assembler aAssembler, object aMethodInfo) { // load element size into eax // load length into ebx // calculate entire size into eax and move to exc // load start into edi // clear ecx bytes starting at edi // load element size into eax XS.Set(EAX, EBP, sourceDisplacement: SourceArrayDisplacement); XS.Add(EAX, 8); XS.Set(EAX, EAX, sourceIsIndirect: true); // load length into ebx XS.Set(EBX, EBP, sourceDisplacement: SourceArrayDisplacement); XS.Add(EBX, 12); XS.Set(EBX, EBX, sourceIsIndirect: true); // calculate size in bytes and move to ecx XS.Multiply(EBX); XS.Set(ECX, EAX); // load start into esi XS.Set(EDI, EBP, sourceDisplacement: SourceArrayDisplacement); XS.Add(EDI, 16); // clear eax bytes starting at esi XS.Set(EAX, 0); XS.LiteralCode("rep stosb"); }
public override void Execute(_MethodInfo aMethod, ILOpCode aOpCode) { // todo: implement exception support. var xSize = SizeOfType(aOpCode.StackPopTypes[0]); XS.Add(ESP, Align(xSize, 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 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; } // 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, ObjectUtils.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 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); }
// this code is mostly copied from Newarr.cs in Il2CPU, just the code to find the size and length is different public override void AssembleNew(Assembler aAssembler, object aMethodInfo) { string xTypeID = ILOp.GetTypeIDLabel(typeof(Array)); MethodBase xCtor = typeof(Array).GetConstructors(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance)[0]; string xCtorName = LabelName.Get(xCtor); XS.Set(ECX, EBP, sourceDisplacement: 8); // size XS.Set(EDX, EBP, sourceDisplacement: 12); // length XS.Push(ECX); // size of element XS.Set(EAX, ECX); XS.Multiply(EDX); // total element size XS.Add(EAX, ObjectUtils.FieldDataOffset + 4); // total array size XS.Push(EAX); XS.Call(LabelName.Get(GCImplementationRefs.AllocNewObjectRef)); XS.Label(".AfterAlloc"); XS.Pop(EAX); XS.Pop(ESI); XS.Push(EAX); XS.Push(ESP, isIndirect: true); XS.Push(ESP, isIndirect: true); // it's on the stack 3 times now, once from the return value, twice from the pushes; XS.Pop(EAX); XS.Set(EBX, xTypeID, sourceIsIndirect: true); // array type id XS.Set(EAX, EBX, destinationIsIndirect: true); // array type id XS.Set(EAX, (uint)ObjectUtils.InstanceTypeEnum.Array, destinationDisplacement: 4, destinationIsIndirect: true); XS.Set(EAX, ESI, destinationDisplacement: 8, destinationIsIndirect: true); XS.Set(EAX, ECX); XS.Push(0); XS.Call(xCtorName); XS.Push(0); }
/// <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 override void Execute(MethodInfo aMethod, ILOpCode aOpCode) { var xStackTop = aOpCode.StackPopTypes[0]; var xStackTop2 = aOpCode.StackPopTypes[0]; var xStackTopSize = SizeOfType(xStackTop); var xStackTop2Size = SizeOfType(xStackTop2); if (xStackTopSize != xStackTop2Size) { throw new Exception("Different size for substract: " + aMethod.MethodBase + "!"); } var xStackTopIsFloat = TypeIsFloat(xStackTop); switch (xStackTopSize) { case 1: case 2: case 4: if (xStackTopIsFloat) { XS.SSE.MoveSS(XMM0, ESP, sourceIsIndirect: true); XS.Add(ESP, 4); XS.SSE.MoveSS(XMM1, ESP, sourceIsIndirect: true); //XS.LiteralCode("movss XMM1, [ESP + 4]"); XS.SSE.SubSS(XMM1, XMM0); XS.SSE.MoveSS(ESP, XMM1, destinationIsIndirect: true); } else { XS.Pop(XSRegisters.ECX); XS.Pop(XSRegisters.EAX); XS.Sub(XSRegisters.EAX, XSRegisters.ECX); XS.Push(XSRegisters.EAX); } break; case 8: if (xStackTopIsFloat) { XS.SSE2.MoveSD(XMM0, ESP, sourceIsIndirect: true); XS.Add(ESP, 8); XS.SSE2.MoveSD(XMM1, ESP, sourceIsIndirect: true); XS.SSE2.SubSD(XMM1, XMM0); XS.SSE2.MoveSD(ESP, XMM1, destinationIsIndirect: true); } else { XS.Pop(EAX); XS.Pop(EDX); XS.Sub(ESP, EAX, destinationIsIndirect: true); XS.SubWithCarry(ESP, EDX, destinationDisplacement: 4); } break; default: throw new NotImplementedException("not implemented"); } }
public static void Assemble(Cosmos.Assembler.Assembler aAssembler, int aSize, bool debugEnabled) { DoNullReferenceCheck(aAssembler, debugEnabled, Align((uint)aSize, 4)); new Comment(aAssembler, "address at: [esp + " + aSize + "]"); int xStorageSize = aSize; if (xStorageSize < 4) { xStorageSize = 4; } XS.Set(XSRegisters.EBX, XSRegisters.ESP, sourceDisplacement: xStorageSize); for (int i = 0; i < (aSize / 4); i++) { XS.Set(XSRegisters.EAX, XSRegisters.ESP, sourceDisplacement: i * 4); XS.Set(XSRegisters.EBX, XSRegisters.EAX, destinationDisplacement: i * 4); } switch (aSize % 4) { case 0: { break; } case 1: { XS.Set(XSRegisters.EAX, XSRegisters.ESP, sourceDisplacement: ((aSize / 4) * 4)); new CPUx86.Mov { DestinationReg = CPUx86.RegistersEnum.EBX, DestinationIsIndirect = true, SourceDisplacement = ((aSize / 4) * 4), SourceReg = CPUx86.RegistersEnum.AL }; break; } case 2: { XS.Set(XSRegisters.EAX, XSRegisters.ESP, sourceDisplacement: ((aSize / 4) * 4)); new CPUx86.Mov { DestinationReg = CPUx86.RegistersEnum.EBX, DestinationIsIndirect = true, DestinationDisplacement = ((aSize / 4) * 4), SourceReg = CPUx86.RegistersEnum.AX }; break; } case 3: { XS.Set(XSRegisters.EAX, XSRegisters.ESP, sourceDisplacement: ((aSize / 4) * 4)); new CPUx86.Mov { DestinationReg = CPUx86.RegistersEnum.EBX, DestinationIsIndirect = true, DestinationDisplacement = ((aSize / 4) * 4), SourceReg = CPUx86.RegistersEnum.AX }; XS.Set(XSRegisters.EAX, XSRegisters.ESP, sourceDisplacement: (((aSize / 4) * 4) + 2)); new CPUx86.Mov { DestinationReg = CPUx86.RegistersEnum.EBX, DestinationIsIndirect = true, DestinationDisplacement = (((aSize / 4) * 4) + 2), SourceReg = CPUx86.RegistersEnum.AL }; break; } default: throw new Exception("Error, shouldn't occur"); } XS.Add(XSRegisters.ESP, ( uint )(xStorageSize + 4)); }
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) { DoNullReferenceCheck(Assembler, DebugEnabled, 0); XS.Pop(XSRegisters.EAX); XS.Set(XSRegisters.EAX, XSRegisters.EAX, sourceIsIndirect: true); XS.Add(XSRegisters.EAX, 8); XS.Push(XSRegisters.EAX, isIndirect: true); }
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) { var xSource = aOpCode.StackPopTypes[0]; var xSourceSize = SizeOfType(xSource); var xSourceIsFloat = TypeIsFloat(xSource); if (IsReferenceType(xSource)) { // todo: Stop GC tracking XS.Add(ESP, SizeOfType(typeof(IntPtr))); // todo: x64 XS.Pop(EAX); XS.Push(0); XS.Push(EAX); } else if (IsByRef(xSource)) { // todo: Stop GC tracking throw new NotImplementedException($"Error compiling '{GetLabel(aMethod)}': conv.i8 not implemented for byref types!"); } else if (xSourceSize <= 4) { if (xSourceIsFloat) { /* * Sadly for x86 there is no way using SSE to convert a float to an Int64... in x64 we could use ConvertPD2DQAndTruncate with * x64 register as a destination... so this one of the few cases in which we need the legacy FPU! */ XS.FPU.FloatLoad(ESP, destinationIsIndirect: true, size: RegisterSize.Int32); XS.Sub(ESP, 4); XS.FPU.IntStoreWithTruncate(ESP, isIndirect: true, size: RegisterSize.Long64); } else { XS.Pop(EAX); XS.SignExtendAX(RegisterSize.Int32); XS.Push(EDX); XS.Push(EAX); } } else if (xSourceSize <= 8) { if (xSourceIsFloat) { /* * Sadly for x86 there is no way using SSE to convert a double to an Int64... in x64 we could use ConvertPD2DQAndTruncate with * x64 register as a destination... so only in this case we need the legacy FPU! */ XS.FPU.FloatLoad(ESP, destinationIsIndirect: true, size: RegisterSize.Long64); XS.FPU.IntStoreWithTruncate(ESP, isIndirect: true, size: RegisterSize.Long64); } } else { throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Conv_I8.cs->Error: StackSize > 8 not supported"); } }
public override void AssembleNew(Cosmos.Assembler.Assembler aAssembler, object aMethodInfo) { XS.Mov(XSRegisters.EAX, CPUAll.ElementReference.New("MultiBootInfo_Memory_High"), sourceIsIndirect: true); XS.Xor(XSRegisters.EDX, XSRegisters.CPUx86.Registers.EDX); XS.Mov(XSRegisters.ECX, 1024); XS.Divide(XSRegisters.ECX); XS.Add(XSRegisters.EAX, 1); XS.Push(XSRegisters.EAX); }
public override void AssembleNew(Cosmos.Assembler.Assembler aAssembler, object aMethodInfo) { XS.Set(XSRegisters.EAX, "MultiBootInfo_Memory_High", sourceIsIndirect: true); XS.Xor(XSRegisters.EDX, XSRegisters.EDX); XS.Set(XSRegisters.ECX, 1024); XS.Divide(XSRegisters.ECX); XS.Add(XSRegisters.EAX, 1); XS.Push(XSRegisters.EAX); }
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 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) { // TODO: Implement exception DoNullReferenceCheck(Assembler, DebugEnabled, 4); XS.Add(ESP, 4); XS.Pop(EAX); XS.Set(LabelName.GetStaticFieldName(ExceptionHelperRefs.CurrentExceptionRef), EAX, destinationIsIndirect: true); XS.Call("SystemExceptionOccurred"); XS.Set(ECX, 3); EmitExceptionLogic(Assembler, aMethod, aOpCode, false, null); }
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) { if (xSourceSize <= 2 || IsIntegerSigned(xSource)) { XS.SSE.ConvertSI2SS(XMM0, ESP, sourceIsIndirect: true); XS.SSE.MoveSS(ESP, XMM0, destinationIsIndirect: true); } else { throw new NotSupportedException(); } } } else if (xSourceSize <= 8) { if (xSourceIsFloat) { XS.SSE2.ConvertSD2SS(XMM0, ESP, sourceIsIndirect: true); XS.Add(ESP, 4); XS.SSE.MoveSS(ESP, XMM0, destinationIsIndirect: true); } else { if (IsIntegerSigned(xSource)) { /* * Again there is no SSE instruction in x86 to do this conversion as we need a 64 Bit register to do this! So we are forced * to use the legacy x87 FPU to do this operation. In x64 the SSE instruction ConvertSIQ2SS should exist. */ XS.FPU.IntLoad(ESP, isIndirect: true, size: RegisterSize.Long64); XS.Add(ESP, 4); /* This instruction is not needed FloatStoreAndPop does already the conversion */ // XS.SSE2.ConvertSD2SS(XMM0, ESP, sourceIsIndirect: true); XS.FPU.FloatStoreAndPop(ESP, isIndirect: true, size: RegisterSize.Int32); } else { throw new NotSupportedException(); } } } else { throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Conv_R4.cs->Error: StackSize > 8 not supported"); } }
public static void Assemble(Assembler aAssembler, bool debugEnabled, bool doNullReferenceCheck = true) { if (doNullReferenceCheck) { DoNullReferenceCheck(aAssembler, debugEnabled, 4); } XS.Add(ESP, 4); XS.Pop(EAX); XS.Push(EAX, displacement: 8); }
public override void Execute(_MethodInfo aMethod, ILOpCode aOpCode) { #warning TODO: Implement exception DoNullReferenceCheck(Assembler, DebugEnabled, 4); XS.Add(XSRegisters.ESP, 4); XS.Pop(XSRegisters.EAX); new CPUx86.Mov { DestinationRef = Cosmos.Assembler.ElementReference.New(DataMember.GetStaticFieldName(ExceptionHelperRefs.CurrentExceptionRef)), DestinationIsIndirect = true, SourceReg = CPUx86.RegistersEnum.EAX }; XS.Call("SystemExceptionOccurred"); XS.Set(XSRegisters.ECX, 3); Call.EmitExceptionLogic(Assembler, aMethod, aOpCode, false, null); }
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 xSource = aOpCode.StackPopTypes[0]; var xSourceSize = SizeOfType(xSource); var xSourceIsFloat = TypeIsFloat(xSource); if (IsReferenceType(xSource)) { // todo: Stop GC tracking XS.Add(ESP, SizeOfType(typeof(UIntPtr))); // todo: x64 XS.Pop(EAX); XS.Push(0); XS.Push(EAX); } else if (IsByRef(xSource)) { // todo: Stop GC tracking throw new NotImplementedException($"Error compiling '{GetLabel(aMethod)}': conv.u8 not implemented for byref types!"); } else if (xSourceSize <= 4) { if (xSourceIsFloat) { XS.FPU.FloatLoad(ESP, destinationIsIndirect: true, size: RegisterSize.Int32); XS.Sub(ESP, 4); XS.FPU.IntStoreWithTruncate(ESP, isIndirect: true, size: RegisterSize.Long64); } else { XS.Pop(EAX); XS.Push(0); XS.Push(EAX); } } else if (xSourceSize <= 8) { if (xSourceIsFloat) { XS.FPU.FloatLoad(ESP, destinationIsIndirect: true, size: RegisterSize.Long64); /* The sign of the value should not be changed a negative value is simply converted to its corresponding ulong value */ //XS.FPU.FloatAbs(); XS.FPU.IntStoreWithTruncate(ESP, isIndirect: true, size: RegisterSize.Long64); } } else { throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Conv_U8.cs->Error: StackSize > 8 not supported"); } }
public override void AssembleNew(Cosmos.Assembler.Assembler aAssembler, object aMethodInfo) { XS.Set(XSRegisters.EAX, XSRegisters.EBP, sourceDisplacement: 20, sourceIsIndirect: true); XS.Push(XSRegisters.EAX); XS.Set(XSRegisters.EAX, XSRegisters.EBP, sourceDisplacement: 16, sourceIsIndirect: true); XS.Push(XSRegisters.EAX); XS.Set(XSRegisters.EAX, XSRegisters.EBP, sourceDisplacement: 12, sourceIsIndirect: true); XS.Push(XSRegisters.EAX); XS.Set(XSRegisters.EAX, XSRegisters.EBP, sourceDisplacement: 8, sourceIsIndirect: true); XS.Push(XSRegisters.EAX); XS.Set(XSRegisters.EAX, XSRegisters.EBP, sourceDisplacement: 24, sourceIsIndirect: true); XS.Call(XSRegisters.EAX); XS.Add(XSRegisters.ESP, 8); }
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 ]"); }