private static void Remainder(Context context, MethodCompiler methodCompiler) { var result = context.Result; var dividend = context.Operand1; var divisor = context.Operand2; if (result.IsR8) { var xmm1 = methodCompiler.CreateVirtualRegister(methodCompiler.TypeSystem.BuiltIn.R8); var xmm2 = methodCompiler.CreateVirtualRegister(methodCompiler.TypeSystem.BuiltIn.R8); var xmm3 = methodCompiler.CreateVirtualRegister(methodCompiler.TypeSystem.BuiltIn.R8); context.SetInstruction(X86.Divsd, xmm1, dividend, divisor); context.AppendInstruction(X86.Roundsd, xmm2, xmm1, methodCompiler.CreateConstant((byte)0x3)); context.AppendInstruction(X86.Mulsd, xmm3, divisor, xmm2); context.AppendInstruction(X86.Subsd, result, dividend, xmm3); } else { var xmm1 = methodCompiler.CreateVirtualRegister(methodCompiler.TypeSystem.BuiltIn.R4); var xmm2 = methodCompiler.CreateVirtualRegister(methodCompiler.TypeSystem.BuiltIn.R4); var xmm3 = methodCompiler.CreateVirtualRegister(methodCompiler.TypeSystem.BuiltIn.R4); context.SetInstruction(X86.Divss, xmm1, dividend, divisor); context.AppendInstruction(X86.Roundss, xmm2, xmm1, methodCompiler.CreateConstant((byte)0x3)); context.AppendInstruction(X86.Mulss, xmm3, divisor, xmm2); context.AppendInstruction(X86.Subss, result, dividend, xmm3); } }
void IIntrinsicPlatformMethod.ReplaceIntrinsicCall(Context context, MethodCompiler methodCompiler) { Operand v0 = context.Operand1; Operand esp = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I4, GeneralPurposeRegister.ESP); context.SetInstruction(X86.Mov32, esp, v0); context.AppendInstruction(X86.Popad); context.AppendInstruction(X86.AddConst32, esp, esp, methodCompiler.CreateConstant(8)); context.AppendInstruction(X86.Sti); context.AppendInstruction(X86.IRetd); // future - common code (refactor opportunity) context.GotoNext(); // Remove all remaining instructions in block and clear next block list while (!context.IsBlockEndInstruction) { if (!context.IsEmpty) { context.SetInstruction(X86.Nop); } context.GotoNext(); } var nextBlocks = context.Block.NextBlocks; foreach (var next in nextBlocks) { next.PreviousBlocks.Remove(context.Block); } nextBlocks.Clear(); }
private static void InterruptReturn(Context context, MethodCompiler methodCompiler) { Operand v0 = context.Operand1; Operand esp = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I8, GeneralPurposeRegister.ESP); context.SetInstruction(X64.Mov64, esp, v0); context.AppendInstruction(X64.Popad); context.AppendInstruction(X64.Add64, esp, esp, methodCompiler.CreateConstant(8)); context.AppendInstruction(X64.Sti); context.AppendInstruction(X64.IRetd); // future - common code (refactor opportunity) context.GotoNext(); // Remove all remaining instructions in block and clear next block list while (!context.IsBlockEndInstruction) { if (!context.IsEmpty) { context.Empty(); } context.GotoNext(); } var nextBlocks = context.Block.NextBlocks; foreach (var next in nextBlocks) { next.PreviousBlocks.Remove(context.Block); } nextBlocks.Clear(); }
private static void SizeOf(Context context, MethodCompiler methodCompiler) { //var size = type.IsPointer ? methodCompiler.Architecture.NativePointerSize : methodCompiler.TypeLayout.GetTypeSize(type); var type = context.InvokeMethod.GenericArguments[0]; var size = methodCompiler.TypeLayout.GetTypeSize(type); var move = methodCompiler.Architecture.Is32BitPlatform ? (BaseInstruction)IRInstruction.Move32 : IRInstruction.Move64; context.SetInstruction(move, context.Result, methodCompiler.CreateConstant(size)); }
void IIntrinsicPlatformMethod.ReplaceIntrinsicCall(Context context, MethodCompiler methodCompiler) { var dest = context.Operand1; var v0 = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.Void, SSE2Register.XMM0); var offset16 = methodCompiler.CreateConstant(16); context.SetInstruction(X86.PXor, v0, v0, v0); context.AppendInstruction(X86.MovupsStore, dest, methodCompiler.ConstantZero, v0); context.AppendInstruction(X86.MovupsStore, dest, offset16, v0); }
private static void Memclr256(Context context, MethodCompiler methodCompiler) { var dest = context.Operand1; var v0 = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.Void, SSE2Register.XMM0); var offset16 = methodCompiler.CreateConstant(16); context.SetInstruction(X86.PXor, v0, v0, v0); context.AppendInstruction(X86.MovupsStore, dest, methodCompiler.ConstantZero32, v0); context.AppendInstruction(X86.MovupsStore, dest, offset16, v0); }
/// <summary> /// Create platform compound move. /// </summary> /// <param name="methodCompiler">The compiler.</param> /// <param name="context">The context.</param> /// <param name="destinationBase">The destination base.</param> /// <param name="destination">The destination.</param> /// <param name="sourceBase">The source base.</param> /// <param name="source">The source.</param> /// <param name="size">The size.</param> public override void InsertCompoundCopy(MethodCompiler methodCompiler, Context context, Operand destinationBase, Operand destination, Operand sourceBase, Operand source, int size) { const int LargeAlignment = 16; int alignedSize = size - (size % NativeAlignment); int largeAlignedTypeSize = size - (size % LargeAlignment); Debug.Assert(size > 0); var srcReg = methodCompiler.CreateVirtualRegister(destinationBase.Type.TypeSystem.BuiltIn.I4); var dstReg = methodCompiler.CreateVirtualRegister(destinationBase.Type.TypeSystem.BuiltIn.I4); context.AppendInstruction(IRInstruction.UnstableObjectTracking); context.AppendInstruction(X86.Lea32, srcReg, sourceBase, source); context.AppendInstruction(X86.Lea32, dstReg, destinationBase, destination); var tmp = methodCompiler.CreateVirtualRegister(destinationBase.Type.TypeSystem.BuiltIn.I4); var tmpLarge = methodCompiler.CreateVirtualRegister(destinationBase.Type.TypeSystem.BuiltIn.R8); for (int i = 0; i < largeAlignedTypeSize; i += LargeAlignment) { // Large aligned moves allow 128bits to be copied at a time var index = methodCompiler.CreateConstant((int)i); context.AppendInstruction(X86.MovupsLoad, tmpLarge, srcReg, index); context.AppendInstruction(X86.MovupsStore, null, dstReg, index, tmpLarge); } for (int i = largeAlignedTypeSize; i < alignedSize; i += 4) { var index = methodCompiler.CreateConstant(i); context.AppendInstruction(X86.MovLoad32, tmp, srcReg, index); context.AppendInstruction(X86.MovStore32, null, dstReg, index, tmp); } for (int i = alignedSize; i < size; i++) { var index = methodCompiler.CreateConstant(i); context.AppendInstruction(X86.MovLoad8, tmp, srcReg, index); context.AppendInstruction(X86.MovStore8, null, dstReg, index, tmp); } context.AppendInstruction(IRInstruction.StableObjectTracking); }
private static void Memcpy256(Context context, MethodCompiler methodCompiler) { var dest = context.Operand1; var src = context.Operand2; var v0 = methodCompiler.CreateVirtualRegister(methodCompiler.TypeSystem.BuiltIn.Void); var v1 = methodCompiler.CreateVirtualRegister(methodCompiler.TypeSystem.BuiltIn.Void); var offset16 = methodCompiler.CreateConstant(16); context.SetInstruction(X86.MovupsLoad, v0, dest, methodCompiler.ConstantZero); context.AppendInstruction(X86.MovupsLoad, v1, dest, offset16); context.AppendInstruction(X86.MovupsStore, null, dest, methodCompiler.ConstantZero, v0); context.AppendInstruction(X86.MovupsStore, null, dest, offset16, v1); }
void IIntrinsicPlatformMethod.ReplaceIntrinsicCall(Context context, MethodCompiler methodCompiler) { var dest = context.Operand1; var src = context.Operand2; var v0 = methodCompiler.CreateVirtualRegister(methodCompiler.TypeSystem.BuiltIn.Void); var v1 = methodCompiler.CreateVirtualRegister(methodCompiler.TypeSystem.BuiltIn.Void); var offset16 = methodCompiler.CreateConstant(16); context.SetInstruction(X86.MovupsLoad, v0, dest, methodCompiler.ConstantZero); context.AppendInstruction(X86.MovupsLoad, v1, dest, offset16); context.AppendInstruction(X86.MovupsStore, null, dest, methodCompiler.ConstantZero, v0); context.AppendInstruction(X86.MovupsStore, null, dest, offset16, v1); }
public static void OrderOperands(Context context, MethodCompiler methodCompiler) { if (context.Operand1.IsResolvedConstant && context.Operand2.IsResolvedConstant) { context.Operand1 = methodCompiler.CreateConstant(context.Operand1.ConstantUnsigned64 + context.Operand2.ConstantUnsigned64); context.Operand2 = methodCompiler.ConstantZero; } if (context.Operand1.IsConstant && !context.Operand2.IsConstant) { var operand1 = context.Operand1; var operand2 = context.Operand2; context.Operand2 = operand1; context.Operand1 = operand2; } }
public static void OrderLoadOperands(InstructionNode node, MethodCompiler methodCompiler) { if (node.Operand1.IsResolvedConstant && node.Operand2.IsResolvedConstant) { node.Operand1 = methodCompiler.CreateConstant(node.Operand1.ConstantUnsignedLongInteger + node.Operand2.ConstantUnsignedLongInteger); node.Operand2 = methodCompiler.ConstantZero; } if (node.Operand1.IsConstant && !node.Operand2.IsConstant) { var operand1 = node.Operand1; var operand2 = node.Operand2; node.Operand2 = operand1; node.Operand1 = operand2; } }
public static void Unsafe_SizeOf(Context context, MethodCompiler methodCompiler) { var type = methodCompiler.Method.GenericArguments[0]; var size = methodCompiler.TypeLayout.GetTypeSize(type); var opReturn = methodCompiler.AllocateVirtualRegisterOrStackSlot(methodCompiler.Method.Signature.ReturnType); // Move constant into return operand var move = methodCompiler.Is32BitPlatform ? (BaseInstruction)IRInstruction.Move32 : IRInstruction.Move64; context.AppendInstruction(move, opReturn, methodCompiler.CreateConstant(size)); // Set return var setReturn = BaseMethodCompilerStage.GetSetReturnInstruction(opReturn.Type, methodCompiler.Is32BitPlatform); context.AppendInstruction(setReturn, null, opReturn); context.AppendInstruction(IRInstruction.Jmp, methodCompiler.BasicBlocks.EpilogueBlock); }
public static void RuntimeHelpers_IsReferenceOrContainsReferences(Context context, MethodCompiler methodCompiler) { var type = methodCompiler.Method.GenericArguments[0]; var opReturn = methodCompiler.AllocateVirtualRegisterOrStackSlot(methodCompiler.Method.Signature.ReturnType); // FIXME: we're only checking if the current type is a reference type, we aren't checking if it contains references var isReferenceOrContainsReferences = type.IsReferenceType; // Move constant into return operand var move = methodCompiler.Is32BitPlatform ? (BaseInstruction)IRInstruction.Move32 : IRInstruction.Move64; context.AppendInstruction(move, opReturn, methodCompiler.CreateConstant(isReferenceOrContainsReferences ? 1 : 0)); // Set return var setReturn = BaseMethodCompilerStage.GetSetReturnInstruction(opReturn.Type, methodCompiler.Is32BitPlatform); context.AppendInstruction(setReturn, null, opReturn); context.AppendInstruction(IRInstruction.Jmp, methodCompiler.BasicBlocks.EpilogueBlock); }
private static void FrameCallRetR8(Context context, MethodCompiler methodCompiler) { var result = context.Result; var methodAddress = context.Operand1; var eax = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I8, GeneralPurposeRegister.EAX); var edx = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I8, GeneralPurposeRegister.EDX); var xmm0 = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I8, SSE2Register.XMM0); methodCompiler.SplitLongOperand(result, out Operand op0L, out Operand op0H); context.SetInstruction(X64.Call, null, methodAddress); context.AppendInstruction(IRInstruction.Gen, xmm0); //context.AppendInstruction(X64.Movdi64ss, eax, xmm0); // FIXME: X64 context.AppendInstruction(X64.Pextrd64, edx, xmm0, methodCompiler.CreateConstant((byte)1)); context.AppendInstruction(X64.Mov64, op0L, eax); context.AppendInstruction(X64.Mov64, op0H, edx); }
void IIntrinsicPlatformMethod.ReplaceIntrinsicCall(Context context, MethodCompiler methodCompiler) { var result = context.Result; var methodAddress = context.Operand1; var newESP = context.Operand2; var eax = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I4, GeneralPurposeRegister.EAX); var edx = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I4, GeneralPurposeRegister.EDX); var mmx1 = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I4, SSE2Register.XMM0); methodCompiler.SplitLongOperand(result, out Operand op0L, out Operand op0H); context.SetInstruction(X86.CallReg, null, methodAddress); context.AppendInstruction(IRInstruction.Gen, mmx1); context.AppendInstruction(X86.Movd, eax, mmx1); context.AppendInstruction(X86.Pextrd, edx, mmx1, methodCompiler.CreateConstant((byte)1)); context.AppendInstruction(X86.Mov32, op0L, eax); context.AppendInstruction(X86.Mov32, op0H, edx); }
private static void FrameCallRetR8(Context context, MethodCompiler methodCompiler) { var result = context.Result; var methodAddress = context.Operand1; var newESP = context.Operand2; var eax = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I4, GeneralPurposeRegister.EAX); var edx = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I4, GeneralPurposeRegister.EDX); var mmx1 = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I4, SSE2Register.XMM0); methodCompiler.SplitLongOperand(result, out Operand op0L, out Operand op0H); context.SetInstruction(X86.Call, null, methodAddress); context.AppendInstruction(IRInstruction.Gen, mmx1); context.AppendInstruction(X86.Movdi32ss, eax, mmx1); // CHECK context.AppendInstruction(X86.Pextrd32, edx, mmx1, methodCompiler.CreateConstant((byte)1)); context.AppendInstruction(X86.Mov32, op0L, eax); context.AppendInstruction(X86.Mov32, op0H, edx); }
void IIntrinsicPlatformMethod.ReplaceIntrinsicCall(Context context, MethodCompiler methodCompiler) { //Helper.FoldOperand1ToConstant(context); var constantx10 = methodCompiler.CreateConstant(0x10); Operand eax = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I4, GeneralPurposeRegister.EAX); Operand ds = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I2, SegmentRegister.DS); Operand es = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I2, SegmentRegister.ES); Operand fs = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I2, SegmentRegister.FS); Operand gs = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I2, SegmentRegister.GS); Operand ss = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I2, SegmentRegister.SS); context.SetInstruction(X86.Lgdt, null, context.Operand1); context.AppendInstruction(X86.MovConst32, eax, constantx10); context.AppendInstruction(X86.MovStoreSeg32, ds, eax); context.AppendInstruction(X86.MovStoreSeg32, es, eax); context.AppendInstruction(X86.MovStoreSeg32, fs, eax); context.AppendInstruction(X86.MovStoreSeg32, gs, eax); context.AppendInstruction(X86.MovStoreSeg32, ss, eax); context.AppendInstruction(X86.JmpFar); }
private static void Lgdt(Context context, MethodCompiler methodCompiler) { //Helper.FoldOperand1ToConstant(context); var constantx10 = methodCompiler.CreateConstant(0x10); var eax = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I4, GeneralPurposeRegister.EAX); var ds = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I2, SegmentRegister.DS); var es = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I2, SegmentRegister.ES); var fs = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I2, SegmentRegister.FS); var gs = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I2, SegmentRegister.GS); var ss = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I2, SegmentRegister.SS); context.SetInstruction(X86.Lgdt, null, context.Operand1); context.AppendInstruction(X86.Mov32, eax, constantx10); context.AppendInstruction(X86.MovStoreSeg32, ds, eax); context.AppendInstruction(X86.MovStoreSeg32, es, eax); context.AppendInstruction(X86.MovStoreSeg32, fs, eax); context.AppendInstruction(X86.MovStoreSeg32, gs, eax); context.AppendInstruction(X86.MovStoreSeg32, ss, eax); context.AppendInstruction(X86.JmpFar); }
private static void Roundsd2Positive(Context context, MethodCompiler methodCompiler) { context.SetInstruction(X86.Roundsd, context.Result, context.Operand1, methodCompiler.CreateConstant((byte)2)); }
private static void GetDelegateTargetAddress(Context context, MethodCompiler methodCompiler) { var load = methodCompiler.Architecture.Is32BitPlatform ? (BaseInstruction)IRInstruction.LoadInt32 : IRInstruction.LoadInt64; context.SetInstruction(load, context.Result, context.Operand1, methodCompiler.CreateConstant(3 * methodCompiler.Architecture.NativePointerSize)); }
private static void Roundss2Negative(Context context, MethodCompiler methodCompiler) { context.SetInstruction(X64.Roundss, context.Result, context.Operand1, methodCompiler.CreateConstant((byte)1)); }
/// <summary> /// Replaces the intrinsic call site /// </summary> /// <param name="context">The context.</param> /// <param name="methodCompiler">The method compiler.</param> void IIntrinsicInternalMethod.ReplaceIntrinsicCall(Context context, MethodCompiler methodCompiler) { var load = methodCompiler.Architecture.Is32BitPlatform ? (BaseInstruction)IRInstruction.LoadInt32 : IRInstruction.LoadInt64; context.SetInstruction(load, context.Result, context.Operand1, methodCompiler.CreateConstant(2 * methodCompiler.Architecture.NativePointerSize)); }