/* * * public static unsafe void Fill16Blocks( * byte *dest, [ebp + 16] * int value, [ebp + 12] * int BlocksNum) [ebp + 8] */ 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.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) { var xStackItem = aOpCode.StackPopTypes[0]; var xStackItemSize = SizeOfType(xStackItem); var xStackItemIsFloat = TypeIsFloat(xStackItem); if (xStackItemSize > 8) { throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Clt_Un.cs->Error: StackSizes > 8 not supported"); } string BaseLabel = GetLabel(aMethod, aOpCode) + "."; string LabelTrue = BaseLabel + "True"; string LabelFalse = BaseLabel + "False"; if (xStackItemSize > 4) { // Using SSE registers (that do NOT branch!) This is needed only for long now #if false XS.Set(XSRegisters.ESI, 1); // esi = 1 XS.Xor(XSRegisters.EDI, XSRegisters.EDI); // edi = 0 #endif if (xStackItemIsFloat) { // Please note that SSE supports double operations only from version 2 XS.SSE2.MoveSD(XMM0, ESP, sourceIsIndirect: true); // Increment ESP to get the value of the next double XS.Add(ESP, 8); XS.SSE2.MoveSD(XMM1, ESP, sourceIsIndirect: true); XS.SSE2.CompareSD(XMM1, XMM0, comparision: LessThan); XS.MoveD(EBX, XMM1); XS.And(EBX, 1); // 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, EBX, destinationIsIndirect: true); } else { XS.Set(ESI, 1); // esi = 1 XS.Xor(EDI, EDI); // edi = 0 XS.Pop(EAX); XS.Pop(EDX); //value2: EDX:EAX XS.Pop(EBX); XS.Pop(ECX); //value1: ECX:EBX XS.Sub(EBX, EAX); XS.SubWithCarry(ECX, EDX); //result = value1 - value2 new ConditionalMove { Condition = ConditionalTestEnum.Below, DestinationReg = RegistersEnum.EDI, SourceReg = RegistersEnum.ESI }; XS.Push(XSRegisters.EDI); } } else { if (xStackItemIsFloat) { XS.Comment("TEST TODO"); XS.SSE.MoveSS(XMM0, ESP, sourceIsIndirect: true); XS.Add(ESP, 4); XS.SSE.MoveSS(XMM1, ESP, sourceIsIndirect: true); XS.SSE.CompareSS(XMM1, XMM0, comparision: LessThan); XS.MoveD(EBX, XMM1); XS.And(ESP, 1, destinationIsIndirect: true); XS.Set(ESP, EBX, destinationIsIndirect: true); } else { XS.Pop(ECX); XS.Pop(XSRegisters.EAX); XS.Push(XSRegisters.ECX); XS.Compare(EAX, ESP, sourceIsIndirect: true); XS.Jump(ConditionalTestEnum.Below, LabelTrue); XS.Jump(LabelFalse); XS.Label(LabelTrue); XS.Add(XSRegisters.ESP, 4); XS.Push(1); new Jump { DestinationLabel = GetLabel(aMethod, aOpCode.NextPosition) }; XS.Label(LabelFalse); XS.Add(XSRegisters.ESP, 4); XS.Push(0); } } }
public override void Execute(_MethodInfo aMethod, ILOpCode aOpCode) { var xStackItem = aOpCode.StackPopTypes[0]; var xStackItemSize = SizeOfType(xStackItem); var xStackItemIsFloat = TypeIsFloat(xStackItem); if (xStackItemSize > 8) { //EmitNotImplementedException( Assembler, GetServiceProvider(), "Cgt: StackSizes>8 not supported", CurInstructionLabel, mMethodInfo, mCurrentOffset, NextInstructionLabel ); throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Cgt.cs->Error: StackSizes > 8 not supported"); //return; } string BaseLabel = GetLabel(aMethod, aOpCode) + "."; string LabelTrue = BaseLabel + "True"; string LabelFalse = BaseLabel + "False"; var xNextLabel = GetLabel(aMethod, aOpCode.NextPosition); if (xStackItemSize > 4) { // Using SSE registers (that do NOT branch!) This is needed only for long now #if false XS.Set(XSRegisters.ESI, 1); // esi = 1 XS.Xor(XSRegisters.EDI, XSRegisters.EDI); // edi = 0 #endif if (xStackItemIsFloat) { // Please note that SSE supports double operations only from version 2 XS.SSE2.MoveSD(XMM0, ESP, sourceIsIndirect: true); // Increment ESP to get the value of the next double XS.Add(ESP, 8); XS.SSE2.MoveSD(XMM1, ESP, sourceIsIndirect: true); XS.SSE2.CompareSD(XMM1, XMM0, comparision: NotLessThanOrEqualTo); XS.MoveD(EBX, XMM1); XS.And(EBX, 1); // 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, EBX, destinationIsIndirect: true); } else { XS.Set(ESI, 1); // esi = 1 XS.Xor(EDI, EDI); // edi = 0 XS.Pop(EAX); XS.Pop(EDX); //value2: EDX:EAX XS.Pop(EBX); XS.Pop(ECX); //value1: ECX:EBX XS.Compare(ECX, EDX); XS.Jump(ConditionalTestEnum.GreaterThan, LabelTrue); XS.Jump(ConditionalTestEnum.LessThan, LabelFalse); XS.Compare(EBX, EAX); XS.Label(LabelTrue); new ConditionalMove { Condition = ConditionalTestEnum.GreaterThan, DestinationReg = RegistersEnum.EDI, SourceReg = RegistersEnum.ESI }; XS.Label(LabelFalse); XS.Push(EDI); } /* * XS.Jump(ConditionalTestEnum.GreaterThan, LabelTrue); * XS.Label(LabelFalse); * XS.Push(0); * XS.Jump(xNextLabel); * XS.Label(LabelTrue ); * XS.Push(1);*/ } else { if (xStackItemIsFloat) { XS.SSE.MoveSS(XMM0, ESP, sourceIsIndirect: true); XS.Add(XSRegisters.ESP, 4); XS.SSE.MoveSS(XMM1, ESP, sourceIsIndirect: true); XS.SSE.CompareSS(XMM1, XMM0, comparision: NotLessThanOrEqualTo); XS.MoveD(EBX, XMM1); XS.And(XSRegisters.EBX, 1); XS.Set(ESP, EBX, destinationIsIndirect: true); } else { XS.Pop(EAX); XS.Compare(EAX, ESP, sourceIsIndirect: true); XS.Jump(ConditionalTestEnum.LessThan, LabelTrue); XS.Jump(LabelFalse); XS.Label(LabelTrue); XS.Add(XSRegisters.ESP, 4); XS.Push(1); XS.Jump(xNextLabel); XS.Label(LabelFalse); XS.Add(XSRegisters.ESP, 4); XS.Push(0); } } }
public override void Execute(_MethodInfo aMethod, ILOpCode aOpCode) { var xStackItem = aOpCode.StackPopTypes[0]; var xStackItemSize = SizeOfType(xStackItem); var xStackItemIsFloat = TypeIsFloat(xStackItem); var xStackItem2 = aOpCode.StackPopTypes[1]; var xStackItem2Size = SizeOfType(xStackItem2); var xStackItem2IsFloat = TypeIsFloat(xStackItem2); var xSize = Math.Max(xStackItemSize, xStackItem2Size); var xNextLabel = GetLabel(aMethod, aOpCode.NextPosition); if (xSize > 8) { throw new Exception("Cosmos.IL2CPU.x86->IL->Ceq.cs->Error: StackSizes > 8 not supported"); } else if (xSize <= 4) { if (xStackItemIsFloat) // float { XS.SSE.MoveSS(XMM0, ESP, sourceIsIndirect: true); XS.Add(ESP, 4); XS.SSE.MoveSS(XMM1, ESP, sourceIsIndirect: true); XS.SSE.CompareSS(XMM1, XMM0, comparision: Equal); XS.MoveD(EBX, XMM1); XS.And(EBX, 1); XS.Set(ESP, EBX, destinationIsIndirect: true); } else { XS.Pop(EAX); XS.Compare(EAX, ESP, sourceIsIndirect: true); XS.Jump(ConditionalTestEnum.Equal, Label.LastFullLabel + ".True"); XS.Jump(Label.LastFullLabel + ".False"); XS.Label(".True"); XS.Add(ESP, 4); XS.Push(1); XS.Jump(xNextLabel); XS.Label(".False"); XS.Add(ESP, 4); XS.Push(0); XS.Jump(xNextLabel); } } else if (xSize > 4) { if (xStackItemIsFloat) { // Please note that SSE supports double operations only from version 2 XS.SSE2.MoveSD(XMM0, ESP, sourceIsIndirect: true); // Increment ESP to get the value of the next double XS.Add(ESP, 8); XS.SSE2.MoveSD(XMM1, ESP, sourceIsIndirect: true); XS.SSE2.CompareSD(XMM1, XMM0, comparision: Equal); XS.MoveD(EBX, XMM1); XS.And(EBX, 1); // 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, EBX, destinationIsIndirect: true); } else { if (IsReferenceType(xStackItem) && IsReferenceType(xStackItem2)) { XS.Comment(xStackItem.Name); XS.Add(ESP, 4); XS.Pop(EAX); XS.Comment(xStackItem2.Name); XS.Add(ESP, 4); XS.Pop(EBX); XS.Compare(EAX, EBX); XS.Jump(ConditionalTestEnum.NotEqual, Label.LastFullLabel + ".False"); // equal XS.Push(1); XS.Jump(xNextLabel); XS.Label(Label.LastFullLabel + ".False"); //not equal XS.Push(0); XS.Jump(xNextLabel); } else { XS.Pop(EAX); XS.Compare(EAX, ESP, sourceDisplacement: 4); XS.Pop(EAX); XS.Jump(ConditionalTestEnum.NotEqual, Label.LastFullLabel + ".False"); XS.Xor(EAX, ESP, sourceDisplacement: 4); XS.Jump(ConditionalTestEnum.NotZero, Label.LastFullLabel + ".False"); //they are equal XS.Add(ESP, 8); XS.Push(1); XS.Jump(xNextLabel); XS.Label(Label.LastFullLabel + ".False"); //not equal XS.Add(ESP, 8); XS.Push(0); XS.Jump(xNextLabel); } } } else { throw new Exception("Cosmos.IL2CPU.x86->IL->Ceq.cs->Error: Case not handled!"); } }
public override void Execute(_MethodInfo aMethod, ILOpCode aOpCode) { var xOp = aOpCode.OpCode; var xBranchLabel = AppAssembler.TmpBranchLabel(aMethod, aOpCode); var xStackType = aOpCode.StackPopTypes[0]; var xSize = SizeOfType(xStackType); var xIsFloat = TypeIsFloat(xStackType); if (xOp == ILOpCode.Code.Brtrue || xOp == ILOpCode.Code.Brfalse) { if (xIsFloat) { throw new NotSupportedException(); } if (xSize <= 4) { XS.Pop(EAX); XS.Compare(EAX, 0); XS.Jump(xOp == ILOpCode.Code.Brtrue ? ConditionalTestEnum.NotEqual : ConditionalTestEnum.Equal, xBranchLabel); } else if (xSize <= 8) { XS.Pop(EAX); XS.Pop(EBX); if (xOp == ILOpCode.Code.Brtrue) { XS.Compare(EAX, 0); XS.Jump(ConditionalTestEnum.NotEqual, xBranchLabel); XS.Compare(EBX, 0); XS.Jump(ConditionalTestEnum.NotEqual, xBranchLabel); } else { var xEndLabel = GetLabel(aMethod, aOpCode) + ".End"; XS.Compare(EAX, 0); XS.Jump(ConditionalTestEnum.NotEqual, xEndLabel); XS.Compare(EBX, 0); XS.Jump(ConditionalTestEnum.Equal, xBranchLabel); XS.Label(xEndLabel); } } else if (xSize > 8) { throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Branch.cs->Error: StackSize > 8 not supported"); } return; } if (xIsFloat) { var xTestOp = SseCompareOPs[xOp]; var xIsUnordered = xOp == ILOpCode.Code.Bge_Un || xOp == ILOpCode.Code.Bgt_Un || xOp == ILOpCode.Code.Ble_Un || xOp == ILOpCode.Code.Blt_Un || xOp == ILOpCode.Code.Bne_Un; if (xSize <= 4) { XS.SSE.MoveSS(XMM0, ESP, sourceIsIndirect: true); XS.Add(ESP, 4); XS.SSE.MoveSS(XMM1, ESP, sourceIsIndirect: true); XS.Add(ESP, 4); if (xIsUnordered) { XS.SSE.MoveSS(XMM2, XMM1); XS.SSE.CompareSS(XMM2, XMM0, ComparePseudoOpcodes.Unordered); XS.MoveD(EAX, XMM2); XS.Compare(EAX, 0); XS.Jump(ConditionalTestEnum.NotEqual, xBranchLabel); } XS.SSE.CompareSS(XMM1, XMM0, xTestOp); XS.MoveD(EAX, XMM1); XS.Compare(EAX, 0); XS.Jump(ConditionalTestEnum.NotEqual, xBranchLabel); } else if (xSize <= 8) { XS.SSE2.MoveSD(XMM0, ESP, sourceIsIndirect: true); XS.Add(ESP, 8); XS.SSE2.MoveSD(XMM1, ESP, sourceIsIndirect: true); XS.Add(ESP, 8); if (xIsUnordered) { XS.SSE2.MoveSD(XMM2, XMM1); XS.SSE2.CompareSD(XMM2, XMM0, ComparePseudoOpcodes.Unordered); XS.MoveD(EAX, XMM2); XS.Compare(EAX, 0); XS.Jump(ConditionalTestEnum.NotEqual, xBranchLabel); } XS.SSE2.CompareSD(XMM1, XMM0, xTestOp); XS.MoveD(EAX, XMM1); XS.Compare(EAX, 0); XS.Jump(ConditionalTestEnum.NotEqual, xBranchLabel); } } else { var xTestOp = TestOPs[xOp]; if (xSize <= 4) { XS.Pop(EAX); XS.Pop(EBX); XS.Compare(EBX, EAX); XS.Jump(xTestOp, xBranchLabel); } else if (xSize <= 8) { var xEndLabel = GetLabel(aMethod, aOpCode) + ".End"; XS.Pop(EAX); XS.Pop(EDX); XS.Pop(EBX); XS.Pop(ECX); switch (xOp) { case ILOpCode.Code.Beq: case ILOpCode.Code.Bne_Un: XS.Compare(ECX, EDX); XS.Jump(ConditionalTestEnum.NotEqual, xOp == ILOpCode.Code.Beq ? xEndLabel : xBranchLabel); XS.Compare(EBX, EAX); XS.Jump(xTestOp, xBranchLabel); break; case ILOpCode.Code.Bge: case ILOpCode.Code.Bgt: XS.Compare(ECX, EDX); XS.Jump(ConditionalTestEnum.GreaterThan, xBranchLabel); XS.Jump(ConditionalTestEnum.NotEqual, xEndLabel); XS.Compare(EBX, EAX); XS.Jump(xTestOp, xBranchLabel); break; case ILOpCode.Code.Ble: case ILOpCode.Code.Blt: XS.Compare(ECX, EDX); XS.Jump(ConditionalTestEnum.LessThan, xBranchLabel); XS.Jump(ConditionalTestEnum.NotEqual, xEndLabel); XS.Compare(EBX, EAX); XS.Jump(xTestOp, xBranchLabel); break; case ILOpCode.Code.Bge_Un: case ILOpCode.Code.Bgt_Un: XS.Compare(ECX, EDX); XS.Jump(ConditionalTestEnum.Above, xBranchLabel); XS.Jump(ConditionalTestEnum.NotEqual, xEndLabel); XS.Compare(EBX, EAX); XS.Jump(xTestOp, xBranchLabel); break; case ILOpCode.Code.Ble_Un: case ILOpCode.Code.Blt_Un: XS.Compare(ECX, EDX); XS.Jump(ConditionalTestEnum.Below, xBranchLabel); XS.Jump(ConditionalTestEnum.NotEqual, xEndLabel); XS.Compare(EBX, EAX); XS.Jump(xTestOp, xBranchLabel); break; } XS.Label(xEndLabel); } } if (xSize > 8) { throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Branch.cs->Error: StackSize > 8 not supported"); } }