/// <summary> /// Visitation function for <see cref="IX86Visitor.Mov"/> instructions. /// </summary> /// <param name="context">The context.</param> public void Mov(Context context) { if (context.Result.IsCPURegister && context.Operand1.IsCPURegister && context.Result.Register == context.Operand1.Register) { context.Empty(); return; } // Mov can not use ESI or EDI registers with 8 or 16 bit memory or register if (context.Operand1.IsCPURegister && (context.Result.IsMemoryAddress || context.Result.IsCPURegister) && (context.Result.IsByte || context.Result.IsShort || context.Result.IsChar || context.Result.IsBoolean) && (context.Operand1.Register == GeneralPurposeRegister.ESI || context.Operand1.Register == GeneralPurposeRegister.EDI)) { Operand source = context.Operand1; Operand dest = context.Result; var replace = (dest.IsMemoryAddress && dest.EffectiveOffsetBase == GeneralPurposeRegister.EAX) ? GeneralPurposeRegister.EBX : GeneralPurposeRegister.EAX; Operand reg = Operand.CreateCPURegister(TypeSystem.BuiltIn.I4, replace); context.SetInstruction2(X86.Xchg, reg, source, source, reg); context.AppendInstruction(X86.Mov, dest, reg); context.AppendInstruction2(X86.Xchg, source, reg, reg, source); } }
/// <summary> /// Visitation function for <see cref="IX86Visitor.Call"/> instructions. /// </summary> /// <param name="context">The context.</param> public override void Call(Context context) { if (context.Operand1 == null) return; if (!context.Operand1.IsCPURegister) return; var before = context.Previous; while (before.IsEmpty && !before.IsBlockStartInstruction) { before = before.Previous; } if (before == null || before.IsBlockStartInstruction) return; if (!before.Result.IsCPURegister) return; if (context.Operand1.Register != before.Result.Register) return; before.SetInstruction(X86.Call, null, before.Operand1); context.Empty(); }
public void Mov(Context context) { Operand source = context.Operand1; Operand result = context.Result; Debug.Assert(result.IsCPURegister); if (source.IsCPURegister && result.Register == source.Register) { context.Empty(); return; } var size = context.Size; // Mov can not use ESI or EDI registers for 8/16bit values if (!(size == InstructionSize.Size16 || size == InstructionSize.Size8)) return; if (source.IsCPURegister && (source.Register == GeneralPurposeRegister.ESI || source.Register == GeneralPurposeRegister.EDI)) { Operand eax = Operand.CreateCPURegister(TypeSystem.BuiltIn.I4, GeneralPurposeRegister.EAX); context.SetInstruction2(X86.Xchg, eax, source, source, eax); context.AppendInstruction(X86.Mov, result, eax); context.AppendInstruction2(X86.Xchg, source, eax, eax, source); } }
/// <summary> /// Adds the epilogue instructions. /// </summary> /// <param name="context">The context.</param> private void AddEpilogueInstructions(Context context) { Operand ebp = Operand.CreateCPURegister(TypeSystem.BuiltIn.I4, GeneralPurposeRegister.EBP); Operand esp = Operand.CreateCPURegister(TypeSystem.BuiltIn.I4, GeneralPurposeRegister.ESP); context.Empty(); if (MethodCompiler.StackSize != 0) { context.AppendInstruction(X86.Add, esp, esp, Operand.CreateConstant(TypeSystem, -MethodCompiler.StackSize)); } context.AppendInstruction(X86.Pop, ebp); context.AppendInstruction(X86.Ret); }
/// <summary> /// Visitation function for <see cref="IX86Visitor.Mov"/> instructions. /// </summary> /// <param name="context">The context.</param> public override void Mov(Context context) { if (context.Result.IsCPURegister && context.Operand1.IsCPURegister && context.Result.Register == context.Operand1.Register) { context.Empty(); return; } // Mov can not use ESI or EDI registers with 8 or 16 bit memory or register if (context.Operand1.IsCPURegister && (context.Result.IsMemoryAddress || context.Result.IsCPURegister) && (context.Result.IsByte || context.Result.IsShort || context.Result.IsChar || context.Result.IsBoolean) && (context.Operand1.Register == GeneralPurposeRegister.ESI || context.Operand1.Register == GeneralPurposeRegister.EDI)) { Operand source = context.Operand1; Operand dest = context.Result; Operand EAX = Operand.CreateCPURegister(TypeSystem.BuiltIn.I4, GeneralPurposeRegister.EAX); context.SetInstruction2(X86.Xchg, EAX, source, source, EAX); context.AppendInstruction(X86.Mov, dest, EAX); context.AppendInstruction2(X86.Xchg, source, EAX, EAX, source); } }
/// <summary> /// Visitation function for <see cref="IX86Visitor.Nop"/> instructions. /// </summary> /// <param name="context">The context.</param> public override void Nop(Context context) { context.Empty(); }
/// <summary> /// Visitation function for <see cref="IX86Visitor.Movzx"/> instructions. /// </summary> /// <param name="context">The context.</param> public override void Movzx(Context context) { // Movsx can not use ESI or EDI registers if (context.Operand1.IsCPURegister && (context.Operand1.Register == GeneralPurposeRegister.ESI || context.Operand1.Register == GeneralPurposeRegister.EDI)) { Debug.Assert(context.Result.IsCPURegister); Operand dest = context.Result; Operand source = context.Operand1; if (source.Register != dest.Register) { context.SetInstruction(X86.Mov, dest, source); } else { context.Empty(); } if (dest.IsShort || dest.IsChar) { context.AppendInstruction(X86.And, dest, dest, Operand.CreateConstant(TypeSystem, 0xffff)); } else if (dest.IsByte || dest.IsBoolean) { context.AppendInstruction(X86.And, dest, dest, Operand.CreateConstant(TypeSystem, 0xff)); } } }
/// <summary> /// Visitation function for <see cref="IX86Visitor.Movsx"/> instructions. /// </summary> /// <param name="context">The context.</param> public override void Movsx(Context context) { // Movsx can not use ESI or EDI registers if (context.Operand1.IsCPURegister && (context.Operand1.Register == GeneralPurposeRegister.ESI || context.Operand1.Register == GeneralPurposeRegister.EDI)) { Operand dest = context.Result; Operand source = context.Operand1; if (source.Register != dest.Register) { context.SetInstruction(X86.Mov, dest, source); } else { context.Empty(); } if (source.IsShort || source.IsChar) { context.AppendInstruction(X86.And, dest, dest, Operand.CreateConstant(MethodCompiler.TypeSystem, 0x0000ffff)); context.AppendInstruction(X86.Xor, dest, dest, Operand.CreateConstant(MethodCompiler.TypeSystem, 0x00010000)); context.AppendInstruction(X86.Sub, dest, dest, Operand.CreateConstant(MethodCompiler.TypeSystem, 0x00010000)); } else if (source.IsByte || source.IsBoolean) { context.AppendInstruction(X86.And, dest, dest, Operand.CreateConstant(MethodCompiler.TypeSystem, 0x000000ff)); context.AppendInstruction(X86.Xor, dest, dest, Operand.CreateConstant(MethodCompiler.TypeSystem, 0x00000100)); context.AppendInstruction(X86.Sub, dest, dest, Operand.CreateConstant(MethodCompiler.TypeSystem, 0x00000100)); } } }
/// <summary> /// Movsses instruction /// </summary> /// <param name="context">The context.</param> public override void Movss(Context context) { if (context.Result.IsCPURegister && context.Operand1.IsCPURegister && context.Result.Register == context.Operand1.Register) { context.Empty(); return; } }
/// <summary> /// Visitation function for Return. /// </summary> /// <param name="context">The context.</param> void IIRVisitor.Return(Context context) { //Debug.Assert(context.BranchTargets != null); if (context.Operand1 != null) { var returnOperand = context.Operand1; context.Empty(); CallingConvention.SetReturnValue(MethodCompiler, TypeLayout, context, returnOperand); context.AppendInstruction(X86.Jmp, BasicBlocks.EpilogueBlock); } else { context.SetInstruction(X86.Jmp, BasicBlocks.EpilogueBlock); } }
/// <summary> /// Visitation function for SwitchInstruction. /// </summary> /// <param name="context">The context.</param> void IIRVisitor.Switch(Context context) { var targets = context.BranchTargets; Operand operand = context.Operand1; context.Empty(); for (int i = 0; i < targets.Count - 1; ++i) { context.AppendInstruction(X86.Cmp, null, operand, Operand.CreateConstant(TypeSystem, i)); context.AppendInstruction(X86.Branch, ConditionCode.Equal, targets[i]); } }
/// <summary> /// Visitation function for <see cref="IX86Visitor.Nop"/> instructions. /// </summary> /// <param name="context">The context.</param> public void Nop(Context context) { context.Empty(); }
public void Movzx(Context context) { var size = context.Size; // Mov can not use ESI or EDI registers for 8/16bit values if (!(size == InstructionSize.Size16 || size == InstructionSize.Size8)) return; Operand result = context.Result; Debug.Assert(result.IsCPURegister); if (result.Register == GeneralPurposeRegister.ESI || result.Register == GeneralPurposeRegister.EDI) { Debug.Assert(context.Result.IsCPURegister); Operand source = context.Operand1; if (source.Register != result.Register) { context.SetInstruction(X86.Mov, result, source); } else { context.Empty(); } if (size == InstructionSize.Size16) { context.AppendInstruction(X86.And, result, result, Operand.CreateConstant(TypeSystem, 0xffff)); } else if (size == InstructionSize.Size8) { context.AppendInstruction(X86.And, result, result, Operand.CreateConstant(TypeSystem, 0xff)); } } }
public void Movsx(Context context) { var size = context.Size; // Mov can not use ESI or EDI registers for 8/16bit values if (!(size == InstructionSize.Size16 || size == InstructionSize.Size8)) return; Operand result = context.Operand1; Debug.Assert(result.IsCPURegister); if (result.Register == GeneralPurposeRegister.ESI || result.Register == GeneralPurposeRegister.EDI) { Operand dest = context.Result; if (result.Register != dest.Register) { context.SetInstruction(X86.Mov, dest, result); } else { context.Empty(); } if (size == InstructionSize.Size16) { context.AppendInstruction(X86.And, dest, dest, Operand.CreateConstant(MethodCompiler.TypeSystem, 0x0000ffff)); context.AppendInstruction(X86.Xor, dest, dest, Operand.CreateConstant(MethodCompiler.TypeSystem, 0x00010000)); context.AppendInstruction(X86.Sub, dest, dest, Operand.CreateConstant(MethodCompiler.TypeSystem, 0x00010000)); } else if (size == InstructionSize.Size8) { context.AppendInstruction(X86.And, dest, dest, Operand.CreateConstant(MethodCompiler.TypeSystem, 0x000000ff)); context.AppendInstruction(X86.Xor, dest, dest, Operand.CreateConstant(MethodCompiler.TypeSystem, 0x00000100)); context.AppendInstruction(X86.Sub, dest, dest, Operand.CreateConstant(MethodCompiler.TypeSystem, 0x00000100)); } } }
public void Movss(Context context) { Debug.Assert(context.Result.IsCPURegister); Debug.Assert(context.Operand1.IsCPURegister); if (context.Result.Register == context.Operand1.Register) { context.Empty(); return; } }