/// <summary> /// Creates the temporary moves. /// </summary> /// <param name="ctx">The context.</param> /// <param name="block">The block.</param> /// <param name="stack">The stack.</param> private void CreateTemporaryMoves(Context ctx, BasicBlock block, Stack <Operand> stack) { Context context = ctx.InsertBefore(); context.SetInstruction(IR.Instruction.NopInstruction); BasicBlock nextBlock; if (NextBlockHasInitialStack(block, out nextBlock)) { LinkTemporaryMoves(context, block, nextBlock, stack); } else { CreateNewTemporaryMoves(context, block, stack); } }
private void HandleMemoryToMemoryOperation(Context ctx, Operand register, bool useStack) { Operand destination = ctx.Result; Operand source = ctx.Operand1; Debug.Assert(destination is MemoryOperand && source is MemoryOperand); if (register == null) register = new RegisterOperand(destination.Type, GeneralPurposeRegister.EDX); ctx.Operand1 = register; Context before = ctx.InsertBefore(); if (useStack) { before.SetInstruction(CPUx86.Instruction.PushInstruction, null, register); before.AppendInstruction(CPUx86.Instruction.MovInstruction, register, source); } else before.SetInstruction(CPUx86.Instruction.MovInstruction, register, source); if (useStack) ctx.AppendInstruction(CPUx86.Instruction.PopInstruction, register); }
/// <summary> /// Visitation function for <see cref="CPUx86.IX86Visitor.UDiv"/> instructions. /// </summary> /// <param name="context">The context.</param> void CPUx86.IX86Visitor.UDiv(Context context) { RegisterOperand edx = new RegisterOperand(new SigType(CilElementType.I), GeneralPurposeRegister.EDX); Context before = context.InsertBefore(); before.SetInstruction(CPUx86.Instruction.XorInstruction, edx, edx); if (context.Operand1 is ConstantOperand) { RegisterOperand ecx = new RegisterOperand(context.Operand1.Type, GeneralPurposeRegister.ECX); before.AppendInstruction(CPUx86.Instruction.MovInstruction, ecx, context.Operand1); context.Operand1 = ecx; } }
/// <summary> /// Visitation function for <see cref="CPUx86.IX86Visitor.Shr"/> instructions. /// </summary> /// <param name="context">The context.</param> void CPUx86.IX86Visitor.Shr(Context context) { if (context.Operand1 is ConstantOperand) return; RegisterOperand ecx = new RegisterOperand(new SigType(CilElementType.I), GeneralPurposeRegister.ECX); Context before = context.InsertBefore(); before.SetInstruction(CPUx86.Instruction.MovInstruction, ecx, context.Operand1); context.Operand1 = context.Result; }
/// <summary> /// Visitation function for <see cref="CPUx86.IX86Visitor.Mul"/> instructions. /// </summary> /// <param name="ctx">The context.</param> void CPUx86.IX86Visitor.Mul(Context ctx) { if (ctx.Operand1 is ConstantOperand) { RegisterOperand ecx = new RegisterOperand(ctx.Operand1.Type, GeneralPurposeRegister.ECX); Context before = ctx.InsertBefore(); before.SetInstruction(CPUx86.Instruction.PushInstruction, null, ecx); before.AppendInstruction(CPUx86.Instruction.MovInstruction, ecx, ctx.Operand1); ctx.Operand1 = ecx; ctx.AppendInstruction(CPUx86.Instruction.PopInstruction, ecx); } if (ctx.Operand1 == null || ctx.Result == null) return; }
/// <summary> /// Visitation function for <see cref="CPUx86.IX86Visitor.Div"/> instructions. /// </summary> /// <param name="context">The context.</param> void CPUx86.IX86Visitor.Div(Context context) { Context before = context.InsertBefore(); before.SetInstruction(CPUx86.Instruction.CdqInstruction); if (context.Operand1 is ConstantOperand) { RegisterOperand ecx = new RegisterOperand(context.Operand1.Type, GeneralPurposeRegister.ECX); before.AppendInstruction(CPUx86.Instruction.MovInstruction, ecx, context.Operand1); context.Operand1 = ecx; } }
/// <summary> /// Visitation function for RemFInstruction. /// </summary> /// <param name="context">The context.</param> void IR.IIRVisitor.RemFInstruction(Context context) { HandleNonCommutativeOperation(context, CPUx86.Instruction.SseDivInstruction); ExtendToR8(context); Operand destination = context.Result; Operand source = context.Operand1; Context[] newBlocks = CreateEmptyBlockContexts(context.Label, 3); Context nextBlock = SplitContext(context, false); RegisterOperand xmm5 = new RegisterOperand(new SigType(CilElementType.R8), SSE2Register.XMM5); RegisterOperand xmm6 = new RegisterOperand(new SigType(CilElementType.R8), SSE2Register.XMM6); RegisterOperand eax = new RegisterOperand(new SigType(CilElementType.I4), GeneralPurposeRegister.EAX); RegisterOperand edx = new RegisterOperand(new SigType(CilElementType.I4), GeneralPurposeRegister.EDX); RegisterOperand uedx = new RegisterOperand(new SigType(CilElementType.U4), GeneralPurposeRegister.EDX); Context before = context.InsertBefore(); context.SetInstruction(CPUx86.Instruction.JmpInstruction, newBlocks[0].BasicBlock); LinkBlocks(context, newBlocks[0]); newBlocks[0].SetInstruction(CPUx86.Instruction.MovsdInstruction, xmm5, source); newBlocks[0].AppendInstruction(CPUx86.Instruction.MovsdInstruction, xmm6, destination); newBlocks[0].AppendInstruction(CPUx86.Instruction.SseDivInstruction, destination, source); newBlocks[0].AppendInstruction(CPUx86.Instruction.Cvttsd2siInstruction, edx, destination); newBlocks[0].AppendInstruction(CPUx86.Instruction.CmpInstruction, edx, new ConstantOperand(new SigType(CilElementType.I4), 0)); newBlocks[0].AppendInstruction(CPUx86.Instruction.BranchInstruction, IR.ConditionCode.Equal, newBlocks[2].BasicBlock); newBlocks[0].AppendInstruction(CPUx86.Instruction.JmpInstruction, newBlocks[1].BasicBlock); LinkBlocks(newBlocks[0], newBlocks[1], newBlocks[2]); newBlocks[1].AppendInstruction(CPUx86.Instruction.Cvtsi2sdInstruction, destination, edx); newBlocks[1].AppendInstruction(CPUx86.Instruction.SseMulInstruction, destination, xmm5); newBlocks[1].AppendInstruction(CPUx86.Instruction.SseSubInstruction, xmm6, destination); newBlocks[1].AppendInstruction(CPUx86.Instruction.MovsdInstruction, destination, xmm6); newBlocks[1].AppendInstruction(CPUx86.Instruction.JmpInstruction, nextBlock.BasicBlock); LinkBlocks(newBlocks[1], nextBlock); newBlocks[2].SetInstruction(CPUx86.Instruction.MovsdInstruction, destination, xmm6); newBlocks[2].AppendInstruction(CPUx86.Instruction.JmpInstruction, nextBlock.BasicBlock); LinkBlocks(newBlocks[2], nextBlock); }
/// <summary> /// Visitation function for SubSInstruction. /// </summary> /// <param name="context">The context.</param> void IR.IIRVisitor.SubSInstruction(Context context) { if (IsInt64(context.Operand1)) { ExpandSub(context); } else { if (context.Operand2 is ConstantOperand && context.Operand1.Type.Type == CilElementType.Char) { RegisterOperand ecx = new RegisterOperand(context.Operand1.Type, GeneralPurposeRegister.ECX); context.InsertBefore().SetInstruction(CPUx86.Instruction.MovInstruction, ecx, context.Operand2); context.Operand2 = ecx; } } }
/// <summary> /// Eliminates the common subexpressions. /// </summary> /// <param name="ctx">The context.</param> private static void EliminateCommonSubexpressions(Context ctx) { List<AEBinExp> AEB = new List<AEBinExp>(); List<AEBinExp> tmp; AEBinExp aeb; for (; !ctx.EndOfInstruction; ctx.GotoNext()) { IInstruction instruction = ctx.Instruction; // block.Instructions[i]; RegisterOperand temp = null; bool found = false; if ((instruction is CIL.ArithmeticInstruction) && (instruction is CIL.BinaryInstruction)) { tmp = new List<AEBinExp>(AEB); while (tmp.Count > 0) { aeb = tmp[0]; tmp.RemoveAt(0); // Match current instruction's expression against those // in AEB, including commutativity if (IsCommutative(instruction)) { //int position = aeb.Position; found = true; // If no variable in tuple, create a new temporary and // insert an instruction evaluating the expression // and assigning it to the temporary if (aeb.Var == null) { // new_tmp() AEB.Remove(aeb); AEB.Add(new AEBinExp(aeb.Position, aeb.Operand1, aeb.Operator, aeb.Operand2, temp)); // Insert new assignment to instruction stream in block Context inserted = ctx.InsertBefore(); switch (aeb.Operator) { case Operation.Add: inserted.SetInstruction(CIL.Instruction.Get(CIL.OpCode.Add), temp, aeb.Operand1, aeb.Operand2); break; case Operation.Mul: inserted.SetInstruction(CIL.Instruction.Get(CIL.OpCode.Mul), temp, aeb.Operand1, aeb.Operand2); break; case Operation.Or: inserted.SetInstruction(CIL.Instruction.Get(CIL.OpCode.Or), temp, aeb.Operand1, aeb.Operand2); break; case Operation.Xor: inserted.SetInstruction(CIL.Instruction.Get(CIL.OpCode.Xor), temp, aeb.Operand1, aeb.Operand2); break; default: break; } //block.Instructions.Insert(position, inst); //++position; //++i; // Replace current instruction by one that copies // the temporary instruction // FIXME PG: // block.Instructions[position] = new IR.MoveInstruction(block.Instructions[position].Results[0], temp); // ctx.SetInstruction(IR.MoveInstruction); // FIXME PG // ctx.Result = block.Instructions[position].Results[0]; // FIXME PG ctx.Operand1 = temp; } else { temp = (RegisterOperand)aeb.Var; } // FIXME PG // block.Instructions[i] = new IR.MoveInstruction(instruction.Results[0], temp); } } if (!found) { Operation opr = Operation.None; if (instruction is CIL.AddInstruction) opr = Operation.Add; else if (instruction is CIL.MulInstruction) opr = Operation.Mul; else if (instruction is IR.LogicalAndInstruction) opr = Operation.And; // Insert new tuple AEB.Add(new AEBinExp(ctx.Index, ctx.Operand1, opr, ctx.Operand2, null)); } // Remove all tuples that use the variable assigned to by // the current instruction tmp = new List<AEBinExp>(AEB); while (tmp.Count > 0) { aeb = tmp[0]; tmp.RemoveAt(0); if (ctx.Operand1 == aeb.Operand1 || ctx.Operand2 == aeb.Operand2) AEB.Remove(aeb); } } } }
/// <summary> /// Converts the given instruction from three address format to a two address format. /// </summary> /// <param name="ctx">The conversion context.</param> private static void ThreeTwoAddressConversion(Context ctx) { Operand result = ctx.Result; Operand op1 = ctx.Operand1; Operand op2 = ctx.Operand2; if (ctx.Instruction is IR.FloatingPointCompareInstruction) return; if (ctx.Instruction is CIL.MulInstruction /*|| ctx.Instruction is CIL.DivInstruction*/) if (!(op1 is ConstantOperand) && (op2 is ConstantOperand)) { Operand temp = op1; op1 = op2; op2 = temp; } // Create registers for different data types RegisterOperand eax = new RegisterOperand(op1.Type, op1.StackType == StackTypeCode.F ? (Register)SSE2Register.XMM0 : GeneralPurposeRegister.EAX); RegisterOperand storeOperand = new RegisterOperand(result.Type, result.StackType == StackTypeCode.F ? (Register)SSE2Register.XMM0 : GeneralPurposeRegister.EAX); // RegisterOperand eaxL = new RegisterOperand(op1.Type, GeneralPurposeRegister.EAX); ctx.Result = storeOperand; ctx.Operand1 = op2; ctx.Operand2 = null; ctx.OperandCount = 1; if (op1.StackType != StackTypeCode.F) { if (IsSigned(op1) && !(op1 is ConstantOperand)) ctx.InsertBefore().SetInstruction(IR.Instruction.SignExtendedMoveInstruction, eax, op1); else if (IsUnsigned(op1) && !(op1 is ConstantOperand)) ctx.InsertBefore().SetInstruction(IR.Instruction.ZeroExtendedMoveInstruction, eax, op1); else ctx.InsertBefore().SetInstruction(CPUx86.Instruction.MovInstruction, eax, op1); } else { if (op1.Type.Type == CilElementType.R4) { if (op1 is ConstantOperand) { Context before = ctx.InsertBefore(); before.SetInstruction(CPUx86.Instruction.MovInstruction, eax, op1); before.AppendInstruction(CPUx86.Instruction.Cvtss2sdInstruction, eax, eax); } else ctx.InsertBefore().SetInstruction(CPUx86.Instruction.Cvtss2sdInstruction, eax, op1); } else ctx.InsertBefore().SetInstruction(CPUx86.Instruction.MovInstruction, eax, op1); } ctx.AppendInstruction(CPUx86.Instruction.MovInstruction, result, eax); }
/// <summary> /// Eliminates the common subexpressions. /// </summary> /// <param name="ctx">The context.</param> private static void EliminateCommonSubexpressions(Context ctx) { List <AEBinExp> AEB = new List <AEBinExp> (); List <AEBinExp> tmp; AEBinExp aeb; for (; !ctx.EndOfInstruction; ctx.GotoNext()) { IInstruction instruction = ctx.Instruction; // block.Instructions[i]; RegisterOperand temp = null; bool found = false; if ((instruction is CIL.ArithmeticInstruction) && (instruction is CIL.BinaryInstruction)) { tmp = new List <AEBinExp> (AEB); while (tmp.Count > 0) { aeb = tmp[0]; tmp.RemoveAt(0); // Match current instruction's expression against those // in AEB, including commutativity if (IsCommutative(instruction)) { //int position = aeb.Position; found = true; // If no variable in tuple, create a new temporary and // insert an instruction evaluating the expression // and assigning it to the temporary if (aeb.Var == null) { // new_tmp() AEB.Remove(aeb); AEB.Add(new AEBinExp(aeb.Position, aeb.Operand1, aeb.Operator, aeb.Operand2, temp)); // Insert new assignment to instruction stream in block Context inserted = ctx.InsertBefore(); switch (aeb.Operator) { case Operation.Add: inserted.SetInstruction(CIL.Instruction.Get(CIL.OpCode.Add), temp, aeb.Operand1, aeb.Operand2); break; case Operation.Mul: inserted.SetInstruction(CIL.Instruction.Get(CIL.OpCode.Mul), temp, aeb.Operand1, aeb.Operand2); break; case Operation.Or: inserted.SetInstruction(CIL.Instruction.Get(CIL.OpCode.Or), temp, aeb.Operand1, aeb.Operand2); break; case Operation.Xor: inserted.SetInstruction(CIL.Instruction.Get(CIL.OpCode.Xor), temp, aeb.Operand1, aeb.Operand2); break; default: break; } //block.Instructions.Insert(position, inst); //++position; //++i; // Replace current instruction by one that copies // the temporary instruction // FIXME PG: // block.Instructions[position] = new IR.MoveInstruction(block.Instructions[position].Results[0], temp); // ctx.SetInstruction(IR.MoveInstruction); // FIXME PG // ctx.Result = block.Instructions[position].Results[0]; // FIXME PG ctx.Operand1 = temp; } else { temp = (RegisterOperand)aeb.Var; } // FIXME PG // block.Instructions[i] = new IR.MoveInstruction(instruction.Results[0], temp); } } if (!found) { Operation opr = Operation.None; if (instruction is CIL.AddInstruction) { opr = Operation.Add; } else if (instruction is CIL.MulInstruction) { opr = Operation.Mul; } else if (instruction is IR.LogicalAndInstruction) { opr = Operation.And; } // Insert new tuple AEB.Add(new AEBinExp(ctx.Index, ctx.Operand1, opr, ctx.Operand2, null)); } // Remove all tuples that use the variable assigned to by // the current instruction tmp = new List <AEBinExp> (AEB); while (tmp.Count > 0) { aeb = tmp[0]; tmp.RemoveAt(0); if (ctx.Operand1 == aeb.Operand1 || ctx.Operand2 == aeb.Operand2) { AEB.Remove(aeb); } } } } }
/// <summary> /// Visitation function for <see cref="ICILVisitor.Newobj"/>. /// </summary> /// <param name="ctx">The context.</param> public void Newobj(Context ctx) { Operand thisReference = ctx.Result; Debug.Assert(thisReference != null, @"Newobj didn't specify class signature?"); ClassSigType classSigType = (ClassSigType)thisReference.Type; RuntimeType classType = RuntimeBase.Instance.TypeLoader.GetType(this.MethodCompiler.Method, this.MethodCompiler.Assembly, classSigType.Token); List<Operand> ctorOperands = new List<Operand>(ctx.Operands); Context before = ctx.InsertBefore(); before.SetInstruction(Instruction.NopInstruction); ReplaceWithInternalCall(before, VmCall.AllocateObject); SymbolOperand methodTableSymbol = this.GetMethodTableSymbol(classType); before.SetOperand(1, methodTableSymbol); before.SetOperand(2, new ConstantOperand(BuiltInSigType.Int32, classType.Size)); before.OperandCount = 2; before.Result = thisReference; // Result is the this pointer, now invoke the real constructor RuntimeMethod ctorMethod = this.FindConstructor(classType, ctorOperands); SymbolOperand symbolOperand = SymbolOperand.FromMethod(ctorMethod); ctorOperands.Insert(0, thisReference); this.ProcessInvokeInstruction(ctx, symbolOperand, null, ctorOperands); }
/// <summary> /// Visitation function for <see cref="CIL.ICILVisitor.Rem"/>. /// </summary> /// <param name="ctx">The context.</param> void CIL.ICILVisitor.Rem(Context ctx) { Operand result = ctx.Result; Operand operand = ctx.Operand1; if (ctx.Operand1.StackType != StackTypeCode.F) { RegisterOperand eax = new RegisterOperand(new SigType(CilElementType.I4), GeneralPurposeRegister.EAX); RegisterOperand ecx = new RegisterOperand(new SigType(CilElementType.I4), GeneralPurposeRegister.ECX); RegisterOperand eaxSource = new RegisterOperand(result.Type, GeneralPurposeRegister.EAX); RegisterOperand ecxSource = new RegisterOperand(operand.Type, GeneralPurposeRegister.ECX); ctx.SetInstruction(CPUx86.Instruction.MovInstruction, eaxSource, result); if (IsUnsigned(result)) ctx.AppendInstruction(IR.Instruction.ZeroExtendedMoveInstruction, eax, eaxSource); else ctx.AppendInstruction(IR.Instruction.SignExtendedMoveInstruction, eax, eaxSource); ctx.AppendInstruction(CPUx86.Instruction.MovInstruction, ecxSource, operand); if (IsUnsigned(operand)) ctx.AppendInstruction(IR.Instruction.ZeroExtendedMoveInstruction, ecx, ecxSource); else ctx.AppendInstruction(IR.Instruction.SignExtendedMoveInstruction, ecx, ecxSource); if (IsUnsigned(result) && IsUnsigned(operand)) ctx.AppendInstruction(CPUx86.Instruction.UDivInstruction, eax, ecx); else ctx.AppendInstruction(CPUx86.Instruction.DivInstruction, eax, ecx); ctx.AppendInstruction(CPUx86.Instruction.MovInstruction, result, new RegisterOperand(new SigType(CilElementType.I4), GeneralPurposeRegister.EDX)); } else { HandleNonCommutativeOperation(ctx, CPUx86.Instruction.SseDivInstruction); ExtendToR8(ctx); Operand destination = ctx.Result; Operand source = ctx.Operand1; RegisterOperand xmm5 = new RegisterOperand(new SigType(CilElementType.R8), SSE2Register.XMM5); Context before = ctx.InsertBefore(); before.SetInstruction(CPUx86.Instruction.MovInstruction, xmm5, destination); // Round towards zero ctx.AppendInstruction(CPUx86.Instruction.SseRoundInstruction, destination, destination, new ConstantOperand(BuiltInSigType.Byte, 0x03)); ctx.AppendInstruction(CPUx86.Instruction.SseMulInstruction, destination, source); ctx.AppendInstruction(CPUx86.Instruction.SseSubInstruction, xmm5, destination); ctx.AppendInstruction(CPUx86.Instruction.MovInstruction, destination, xmm5); } }
/// <summary> /// Visitation function for Newobj instruction. /// </summary> /// <param name="context">The context.</param> public void Newobj(Context context) { Operand thisReference = context.Result; Debug.Assert(thisReference != null, @"Newobj didn't specify class signature?"); ClassSigType classSigType = (ClassSigType)thisReference.Type; RuntimeType classType = typeModule.GetType(classSigType.Token); List<Operand> ctorOperands = new List<Operand>(context.Operands); RuntimeMethod ctorMethod = context.InvokeTarget; if (!ReplaceWithInternalCall(context, ctorMethod)) { Context before = context.InsertBefore(); before.SetInstruction(Instruction.NopInstruction); ReplaceWithVmCall(before, VmCall.AllocateObject); SymbolOperand methodTableSymbol = GetMethodTableSymbol(classType); before.SetOperand(1, methodTableSymbol); before.SetOperand(2, new ConstantOperand(BuiltInSigType.Int32, typeLayout.GetTypeSize(classType))); before.OperandCount = 2; before.Result = thisReference; // Result is the this pointer, now invoke the real constructor SymbolOperand symbolOperand = SymbolOperand.FromMethod(ctorMethod); ctorOperands.Insert(0, thisReference); ProcessInvokeInstruction(context, symbolOperand, null, ctorOperands); } }
/// <summary> /// Extends to r8. /// </summary> /// <param name="ctx">The context.</param> private static void ExtendToR8(Context ctx) { RegisterOperand xmm5 = new RegisterOperand(new SigType(CilElementType.R8), SSE2Register.XMM5); RegisterOperand xmm6 = new RegisterOperand(new SigType(CilElementType.R8), SSE2Register.XMM6); Context before = ctx.InsertBefore(); if (ctx.Result.Type.Type == CilElementType.R4) { before.SetInstruction(CPUx86.Instruction.Cvtss2sdInstruction, xmm5, ctx.Result); ctx.Result = xmm5; } if (ctx.Operand1.Type.Type == CilElementType.R4) { before.SetInstruction(CPUx86.Instruction.Cvtss2sdInstruction, xmm6, ctx.Operand1); ctx.Operand1 = xmm6; } }
/// <summary> /// Visitation function for <see cref="CIL.ICILVisitor.Sub"/>. /// </summary> /// <param name="ctx">The context.</param> void CIL.ICILVisitor.Sub(Context ctx) { if (ctx.Operand1.StackType == StackTypeCode.Int64) ExpandSub(ctx); else { if (ctx.Operand2 is ConstantOperand && ctx.Operand1.Type.Type == CilElementType.Char) { RegisterOperand ecx = new RegisterOperand(ctx.Operand1.Type, GeneralPurposeRegister.ECX); ctx.InsertBefore().SetInstruction(CPUx86.Instruction.MovInstruction, ecx, ctx.Operand2); ctx.Operand2 = ecx; } } }
private void HandleMemoryToMemoryOperation(Context ctx) { Operand destination = ctx.Result; Operand source = ctx.Operand1; Debug.Assert(destination is MemoryOperand && source is MemoryOperand); SigType destinationSigType = destination.Type; if (this.RequiresSseOperation(destinationSigType)) { IInstruction moveInstruction = this.GetMoveInstruction(destinationSigType); RegisterOperand destinationRegister = this.AllocateRegister(destinationSigType); ctx.Result = destinationRegister; ctx.AppendInstruction(moveInstruction, destination, destinationRegister); } else { SigType sourceSigType = ctx.Operand1.Type; IInstruction moveInstruction = this.GetMoveInstruction(sourceSigType); RegisterOperand sourceRegister = this.AllocateRegister(sourceSigType); ctx.Operand1 = sourceRegister; ctx.InsertBefore().SetInstruction(moveInstruction, sourceRegister, source); } }
/// <summary> /// Visitation function for <see cref="CPUx86.IX86Visitor.Call"/> instructions. /// </summary> /// <param name="context">The context.</param> void CPUx86.IX86Visitor.Call(Context context) { Operand destinationOperand = context.Operand1; if (destinationOperand == null) { return; } if (destinationOperand is SymbolOperand) { return; } if (!(destinationOperand is RegisterOperand)) { Context before = context.InsertBefore(); RegisterOperand eax = new RegisterOperand(BuiltInSigType.IntPtr, GeneralPurposeRegister.EAX); before.SetInstruction(CPUx86.Instruction.MovInstruction, eax, destinationOperand); context.Operand1 = eax; } }
private Operand InsertLoadBeforeInstruction(Context context, string symbolName, SigType type) { Context before = context.InsertBefore(); Operand result = this.MethodCompiler.CreateTemporary(type); Operand op = new SymbolOperand(type, symbolName); before.SetInstruction(Instruction.Get(OpCode.Ldc_i4), result, op); return result; }
/// <summary> /// Visitation function for <see cref="CPUx86.IX86Visitor.Cmp"/> instructions. /// </summary> /// <param name="ctx">The context.</param> void CPUx86.IX86Visitor.Cmp(Context ctx) { Operand left = ctx.Result; Operand right = ctx.Operand1; if (left is ConstantOperand) { RegisterOperand ecx = new RegisterOperand(left.Type, GeneralPurposeRegister.ECX); Context before = ctx.InsertBefore(); before.SetInstruction(CPUx86.Instruction.PushInstruction, null, ecx); before.AppendInstruction(CPUx86.Instruction.MovInstruction, ecx, left); ctx.Result = ecx; ctx.AppendInstruction(CPUx86.Instruction.PopInstruction, ecx); } if (right is ConstantOperand && !Is32Bit(left)) { RegisterOperand edx = new RegisterOperand(new SigType(CilElementType.I4), GeneralPurposeRegister.EBX); Context before = ctx.InsertBefore(); before.SetInstruction(CPUx86.Instruction.PushInstruction, null, edx); if (IsSigned(left)) before.AppendInstruction(CPUx86.Instruction.MovsxInstruction, edx, left); else before.AppendInstruction(CPUx86.Instruction.MovzxInstruction, edx, left); ctx.Result = edx; ctx.AppendInstruction(CPUx86.Instruction.PopInstruction, edx); } }
/// <summary> /// Creates the temporary moves. /// </summary> /// <param name="ctx">The CTX.</param> /// <param name="block">The block.</param> /// <param name="stack">The stack.</param> private void CreateTemporaryMoves(Context ctx, BasicBlock block, Stack<Operand> stack) { Context context = ctx.InsertBefore(); context.SetInstruction(IR.Instruction.NopInstruction); BasicBlock nextBlock; if (NextBlockHasInitialStack(block, out nextBlock)) LinkTemporaryMoves(context, block, nextBlock, stack); else CreateNewTemporaryMoves(context, block, stack); }
public void RemFInstruction(Context context) { HandleNonCommutativeOperation(context, CPUx86.Instruction.SseDivInstruction); ExtendToR8(context); Operand destination = context.Result; Operand source = context.Operand1; RegisterOperand xmm5 = new RegisterOperand(new SigType(CilElementType.R8), SSE2Register.XMM5); Context before = context.InsertBefore(); before.SetInstruction(CPUx86.Instruction.MovInstruction, xmm5, destination); // Round towards zero context.AppendInstruction(CPUx86.Instruction.SseRoundInstruction, destination, destination, new ConstantOperand(BuiltInSigType.Byte, 0x03)); context.AppendInstruction(CPUx86.Instruction.SseMulInstruction, destination, source); context.AppendInstruction(CPUx86.Instruction.SseSubInstruction, xmm5, destination); context.AppendInstruction(CPUx86.Instruction.MovInstruction, destination, xmm5); }