/// <summary> /// Visitation function for <see cref="IX86Visitor.Cmp"/> instructions. /// </summary> /// <param name="context">The context.</param> public override void Cmp(Context context) { Operand left = context.Operand1; Operand right = context.Operand2; if (left.IsConstant) { Operand ecx = AllocateVirtualRegister(left.Type); Context before = context.InsertBefore(); before.AppendInstruction(X86.Mov, ecx, left); context.Operand1 = ecx; } if (right.IsConstant && (left.IsChar || left.IsShort || left.IsByte)) { Operand edx = AllocateVirtualRegister(TypeSystem.BuiltIn.I4); Context before = context.InsertBefore(); if (left.IsSigned) { before.AppendInstruction(X86.Movsx, edx, left); } else { before.AppendInstruction(X86.Movzx, edx, left); } context.Operand1 = edx; } }
/// <summary> /// Visitation function for <see cref="IX86Visitor.Cmp"/> instructions. /// </summary> /// <param name="context">The context.</param> public void Cmp(Context context) { Operand left = context.Operand1; Operand right = context.Operand2; if (left.IsConstant) { Operand v1 = AllocateVirtualRegister(left.Type); Context before = context.InsertBefore(); before.AppendInstruction(X86.Mov, v1, left); context.Operand1 = v1; } if (right.IsConstant && (left.IsChar || left.IsShort || left.IsByte)) { Operand v2 = AllocateVirtualRegister(TypeSystem.BuiltIn.I4); InstructionSize size = left.IsByte ? InstructionSize.Size8 : InstructionSize.Size16; if (left.IsSigned) { context.InsertBefore().AppendInstruction(X86.Movsx, size, v2, left); } else { context.InsertBefore().AppendInstruction(X86.Movzx, size, v2, left); } context.Operand1 = v2; } }
/// <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) { if (!(ctx.Instruction is BaseIRInstruction)) return; if (ctx.Instruction is IntegerCompare || ctx.Instruction is FloatCompare || ctx.Instruction is Load || ctx.Instruction is Store || ctx.Instruction is Call || ctx.Instruction is ZeroExtendedMove || ctx.Instruction is SignExtendedMove) return; Operand result = ctx.Result; Operand op1 = ctx.Operand1; Operand op2 = ctx.Operand2; // 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); 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(IRInstruction.SignExtendedMove, eax, op1); else if (IsUnsigned(op1) && !(op1 is ConstantOperand)) ctx.InsertBefore().SetInstruction(IRInstruction.ZeroExtendedMove, eax, op1); else ctx.InsertBefore().SetInstruction(X86.Mov, eax, op1); } else { if (op1.Type.Type == CilElementType.R4) { if (op1 is ConstantOperand) { Context before = ctx.InsertBefore(); before.SetInstruction(X86.Mov, eax, op1); before.AppendInstruction(X86.Cvtss2sd, eax, eax); } else { ctx.InsertBefore().SetInstruction(X86.Cvtss2sd, eax, op1); } } else { ctx.InsertBefore().SetInstruction(X86.Mov, eax, op1); } } ctx.AppendInstruction(X86.Mov, result, 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; }
private void LoadFirstOperandIntoRegister(Context context) { // load into a register Operand operand = context.Operand1; Operand register = AllocateVirtualRegister(operand.Type); context.Operand1 = register; context.InsertBefore().SetInstruction(GetMove(register, operand), register, operand); }
/// <summary> /// Visitation function for <see cref="IX86Visitor.In"/> instructions. /// </summary> /// <param name="context">The context.</param> public void In(Context context) { var size = context.Size; if (size == InstructionSize.Size32) return; Debug.Assert(context.Result.Register == GeneralPurposeRegister.EAX); // NOTE: Other option is to use Movzx after IN instruction context.InsertBefore().SetInstruction(X86.Mov, context.Result, ConstantZero); }
/// <summary> /// Visitation function for <see cref="IX86Visitor.Cmp"/> instructions. /// </summary> /// <param name="context">The context.</param> public void Cmp(Context context) { Operand left = context.Operand1; if (left.IsConstant) { Operand v1 = AllocateVirtualRegister(left.Type); context.InsertBefore().AppendInstruction(X86.Mov, v1, left); context.Operand1 = v1; } }
/// <summary> /// Visitation function for <see cref="IX86Visitor.In"/> instructions. /// </summary> /// <param name="context">The context.</param> public override void In(Context context) { var size = context.Size; if (size == InstructionSize.Size32) return; Debug.Assert(context.Result.Register == GeneralPurposeRegister.EAX); // NOTE: Other option is to use Movzx after IN instruction context.InsertBefore().SetInstruction(X86.Mov, context.Result, Operand.CreateConstant(TypeSystem, 0)); }
public void In(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; Debug.Assert(context.Result.Register == GeneralPurposeRegister.EAX); // NOTE: Other option is to use Movzx after IN instruction context.InsertBefore().SetInstruction(X86.Mov, context.Result, ConstantZero); }
/// <summary> /// Inserts the copy statement. /// </summary> /// <param name="predecessor">The predecessor.</param> /// <param name="result">The result.</param> /// <param name="operand">The operand.</param> private void InsertCopyStatement(BasicBlock predecessor, Operand result, Operand operand) { var context = new Context(this.instructionSet, predecessor); while (!context.EndOfInstruction && IsBranchInstruction(context)) context.GotoNext(); if (context.Index != -1) context = context.InsertBefore(); var source = operand is SsaOperand ? (operand as SsaOperand).Operand : operand; var destination = result is SsaOperand ? (result as SsaOperand).Operand : result; Debug.Assert(!(source is SsaOperand)); Debug.Assert(!(destination is SsaOperand)); context.SetInstruction(IR.Instruction.MoveInstruction, destination, source); }
/// <summary> /// Converts the given instruction from three address format to a two address format. /// </summary> /// <param name="context">The conversion context.</param> private void ThreeTwoAddressConversion(Context context) { if (!(context.Instruction is X86Instruction)) return; if (!(context.OperandCount >= 1 && context.ResultCount >= 1 && context.Result != context.Operand1)) return; Operand result = context.Result; Operand operand1 = context.Operand1; context.Operand1 = result; context.InsertBefore().SetInstruction(GetMove(result, operand1), result, operand1); return; }
/// <summary> /// Visitation function for <see cref="IX86Visitor.Call"/> instructions. /// </summary> /// <param name="context">The context.</param> public void Call(Context context) { // FIXME: Result operand should be used instead of Operand1 for the result // FIXME: Move to FixedRegisterAssignmentStage Operand destinationOperand = context.Operand1; if (destinationOperand == null || destinationOperand.IsSymbol) return; if (!destinationOperand.IsRegister) { Context before = context.InsertBefore(); Operand eax = AllocateVirtualRegister(destinationOperand.Type); before.SetInstruction(X86.Mov, eax, destinationOperand); context.Operand1 = eax; } }
/// <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 r10 = new RegisterOperand(context.Operand1.Type, GeneralPurposeRegister.R10); context.InsertBefore().SetInstruction(Instruction.MovInstruction, r10, context.Operand2); context.Operand2 = r10; } } }
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); } }
private void HandleMemoryToMemoryOperation2(Context ctx) { Operand destination = ctx.Operand1; Operand source = ctx.Operand2; Debug.Assert(destination.IsMemoryAddress && source.IsMemoryAddress); SigType destinationSigType = destination.Type; if (RequiresSseOperation(destinationSigType)) { BaseInstruction moveInstruction = GetMoveInstruction(destinationSigType); Operand destinationRegister = AllocateRegister(destinationSigType); ctx.Operand1 = destinationRegister; ctx.AppendInstruction(moveInstruction, destination, destinationRegister); } else { SigType sourceSigType = source.Type; BaseInstruction moveInstruction = GetMoveInstruction(sourceSigType); Operand sourceRegister = AllocateRegister(sourceSigType); ctx.Operand2 = sourceRegister; ctx.InsertBefore().SetInstruction(moveInstruction, sourceRegister, source); } }
/// <summary> /// Visitation function for SubSInstruction. /// </summary> /// <param name="context">The context.</param> void IIRVisitor.SubSigned(Context context) { if (IsInt64(context.Operand1)) { ExpandSub(context); } else { if (context.Operand2.IsConstant && context.Operand1.Type.Type == CilElementType.Char) { Operand r10 = Operand.CreateCPURegister(context.Operand1.Type, GeneralPurposeRegister.R10); context.InsertBefore().SetInstruction(AVR32.Mov, r10, context.Operand2); context.Operand2 = r10; } } }
/// <summary> /// Visitation function for StoreInstruction. /// </summary> /// <param name="context">The context.</param> void IIRVisitor.Store(Context context) { Operand baseOperand = context.Operand1; Operand offsetOperand = context.Operand2; Operand value = context.Operand3; MosaType storeType = context.MosaType; var type = baseOperand.Type; var size = context.Size; if (value.IsR8 && type.IsR4) //&& size == InstructionSize.Size32) { Operand xmm1 = AllocateVirtualRegister(TypeSystem.BuiltIn.R4); context.InsertBefore().AppendInstruction(X86.Cvtsd2ss, size, xmm1, value); value = xmm1; } else if (value.IsMemoryAddress) { Operand v2 = AllocateVirtualRegister(value.Type); context.InsertBefore().AppendInstruction(X86.Mov, size, v2, value); value = v2; } if (offsetOperand.IsConstant) { if (baseOperand.IsField) { Debug.Assert(offsetOperand.IsConstantZero); Debug.Assert(baseOperand.Field.IsStatic); context.SetInstruction(GetMove(baseOperand, value), size, baseOperand, value); } else { var mem = Operand.CreateMemoryAddress(storeType, baseOperand, offsetOperand.ConstantSignedLongInteger); context.SetInstruction(GetMove(mem, value), size, mem, value); } } else { if (type.IsUnmanagedPointer) type = storeType.ToUnmanagedPointer(); else if (type.IsManagedPointer) type = storeType.ToManagedPointer(); Operand v1 = AllocateVirtualRegister(type); Operand mem = Operand.CreateMemoryAddress(storeType, v1, 0); context.SetInstruction(X86.Mov, v1, baseOperand); context.AppendInstruction(X86.Add, v1, v1, offsetOperand); context.AppendInstruction(GetMove(mem, value), size, mem, value); } }
/// <summary> /// Floating point compare instruction. /// </summary> /// <param name="context">The context.</param> void IIRVisitor.FloatCompare(Context context) { EmitFloatingPointConstants(context); Operand result = context.Result; Operand left = context.Operand1; Operand right = context.Operand2; ConditionCode condition = context.ConditionCode; // normalize condition switch (condition) { case ConditionCode.Equal: break; case ConditionCode.NotEqual: break; case ConditionCode.UnsignedGreaterOrEqual: condition = ConditionCode.GreaterOrEqual; break; case ConditionCode.UnsignedGreaterThan: condition = ConditionCode.GreaterThan; break; case ConditionCode.UnsignedLessOrEqual: condition = ConditionCode.LessOrEqual; break; case ConditionCode.UnsignedLessThan: condition = ConditionCode.LessThan; break; } // TODO - Move the following to its own pre-IR decomposition stage for this instruction // Swap, if necessary, the operands to place register operand first than memory operand // otherwise the memory operand will have to be loaded into a register if ((condition == ConditionCode.Equal || condition == ConditionCode.NotEqual) && left.IsMemoryAddress && !right.IsMemoryAddress) { // swap order of operands to move var t = left; left = right; right = t; } Context before = context.InsertBefore(); // Compare using the smallest precision if (left.IsR4 && right.IsR8) { Operand rop = AllocateVirtualRegister(TypeSystem.BuiltIn.R4); before.SetInstruction(X86.Cvtsd2ss, rop, right); right = rop; } if (left.IsR8 && right.IsR4) { Operand rop = AllocateVirtualRegister(TypeSystem.BuiltIn.R4); before.SetInstruction(X86.Cvtsd2ss, rop, left); left = rop; } X86Instruction instruction = null; if (left.IsR4) { instruction = X86.Ucomiss; } else { instruction = X86.Ucomisd; } switch (condition) { case ConditionCode.Equal: { // a==b // mov eax, 1 // ucomisd xmm0, xmm1 // jp L3 // jne L3 // ret //L3: // mov eax, 0 Context[] newBlocks = CreateNewBlocksWithContexts(2); Context nextBlock = Split(context); context.SetInstruction(X86.Mov, result, Operand.CreateConstantSignedInt(TypeSystem, 1)); context.AppendInstruction(instruction, null, left, right); context.AppendInstruction(X86.Branch, ConditionCode.Parity, newBlocks[1].BasicBlock); context.AppendInstruction(X86.Jmp, newBlocks[0].BasicBlock); LinkBlocks(context, newBlocks[0], newBlocks[1]); newBlocks[0].AppendInstruction(X86.Branch, ConditionCode.NotEqual, newBlocks[1].BasicBlock); newBlocks[0].AppendInstruction(X86.Jmp, nextBlock.BasicBlock); LinkBlocks(newBlocks[0], newBlocks[1], nextBlock); newBlocks[1].AppendInstruction(X86.Mov, result, Operand.CreateConstantSignedInt(TypeSystem, 0)); newBlocks[1].AppendInstruction(X86.Jmp, nextBlock.BasicBlock); LinkBlocks(newBlocks[1], nextBlock); break; } case ConditionCode.NotEqual: { // a!=b // mov eax, 1 // ucomisd xmm0, xmm1 // jp L5 // setne al // movzx eax, al //L5: Context[] newBlocks = CreateNewBlocksWithContexts(1); Context nextBlock = Split(context); context.SetInstruction(X86.Mov, result, Operand.CreateConstantSignedInt(TypeSystem, 1)); context.AppendInstruction(instruction, null, left, right); context.AppendInstruction(X86.Branch, ConditionCode.Parity, nextBlock.BasicBlock); context.AppendInstruction(X86.Jmp, newBlocks[0].BasicBlock); LinkBlocks(context, nextBlock, newBlocks[0]); newBlocks[0].AppendInstruction(X86.Setcc, ConditionCode.NotEqual, result); newBlocks[0].AppendInstruction(X86.Movzx, result, result); newBlocks[0].AppendInstruction(X86.Jmp, newBlocks[0].BasicBlock); LinkBlocks(newBlocks[0], newBlocks[0]); break; } case ConditionCode.LessThan: { // a>b and a<b // mov eax, 0 // ucomisd xmm1, xmm0 // seta al context.SetInstruction(X86.Mov, result, Operand.CreateConstantSignedInt(TypeSystem, 0)); context.AppendInstruction(instruction, null, right, left); context.AppendInstruction(X86.Setcc, ConditionCode.UnsignedGreaterThan, result); break; } case ConditionCode.GreaterThan: { // a>b and a<b // mov eax, 0 // ucomisd xmm0, xmm1 // seta al context.SetInstruction(X86.Mov, result, Operand.CreateConstantSignedInt(TypeSystem, 0)); context.AppendInstruction(instruction, null, left, right); context.AppendInstruction(X86.Setcc, ConditionCode.UnsignedGreaterThan, result); break; } case ConditionCode.LessOrEqual: { // a<=b and a>=b // mov eax, 0 // ucomisd xmm1, xmm0 // setae al context.SetInstruction(X86.Mov, result, Operand.CreateConstantSignedInt(TypeSystem, 0)); context.AppendInstruction(instruction, null, left, right); context.AppendInstruction(X86.Setcc, ConditionCode.NoCarry, result); break; } case ConditionCode.GreaterOrEqual: { // a<=b and a>=b // mov eax, 0 // ucomisd xmm0, xmm1 // setae al context.SetInstruction(X86.Mov, result, Operand.CreateConstantSignedInt(TypeSystem, 0)); context.AppendInstruction(instruction, null, right, left); context.AppendInstruction(X86.Setcc, ConditionCode.NoCarry, result); break; } } }
/// <summary> /// Visitation function for DivUInstruction. /// </summary> /// <param name="context">The context.</param> void IIRVisitor.DivUnsigned(Context context) { context.ReplaceInstructionOnly(X86.Div); Operand edx = Operand.CreateCPURegister(BuiltInSigType.IntPtr, GeneralPurposeRegister.EDX); Context before = context.InsertBefore(); before.SetInstruction(X86.Xor, edx, edx); if (context.Operand1.IsConstant) { Operand ecx = Operand.CreateCPURegister(context.Operand1.Type, GeneralPurposeRegister.ECX); before.AppendInstruction(X86.Mov, ecx, context.Operand1); context.Operand1 = ecx; } }
/// <summary> /// Visitation function for StoreInstruction. /// </summary> /// <param name="context">The context.</param> void IIRVisitor.Store(Context context) { Operand baseOperand = context.Operand1; Operand offsetOperand = context.Operand2; Operand value = context.Operand3; MosaType storeType = context.MosaType; //if (value.IsR4 || storeType.IsR4) // <--- this one is right if (value.IsR8 && (storeType ?? value.Type).IsR4) { Operand xmm1 = AllocateVirtualRegister(TypeSystem.BuiltIn.R4); context.InsertBefore().AppendInstruction(X86.Cvtsd2ss, xmm1, value); value = xmm1; } else { Operand v2 = AllocateVirtualRegister(value.Type); context.InsertBefore().AppendInstruction(X86.Mov, v2, value); value = v2; } MosaType type = baseOperand.Type; if (storeType != null) { if (baseOperand.Type.IsUnmanagedPointer) type = storeType.ToUnmanagedPointer(); else if (baseOperand.Type.IsManagedPointer) type = storeType.ToManagedPointer(); } if (offsetOperand.IsConstant) { Operand mem = Operand.CreateMemoryAddress(type, baseOperand, offsetOperand.ConstantSignedInteger); context.SetInstruction(GetMove(mem, value), mem, value); } else { Operand v1 = AllocateVirtualRegister(type); Operand mem = Operand.CreateMemoryAddress(type, v1, 0); context.SetInstruction(X86.Mov, v1, baseOperand); context.AppendInstruction(X86.Add, v1, v1, offsetOperand); context.AppendInstruction(GetMove(mem, value), mem, value); } }
/// <summary> /// Visitation function for <see cref="IX86Visitor.Shr"/> instructions. /// </summary> /// <param name="context">The context.</param> void IX86Visitor.Shr(Context context) { if (context.Operand1.IsConstant) return; Operand ecx = Operand.CreateCPURegister(BuiltInSigType.IntPtr, GeneralPurposeRegister.ECX); Context before = context.InsertBefore(); before.SetInstruction(X86.Mov, ecx, context.Operand1); context.Operand1 = context.Result; }
/// <summary> /// Visitation function for <see cref="IX86Visitor.IDiv"/> instructions. /// </summary> /// <param name="context">The context.</param> void IX86Visitor.IDiv(Context context) { Context before = context.InsertBefore(); before.SetInstruction(X86.Cdq); if (context.Operand1.IsConstant) { Operand ecx = Operand.CreateCPURegister(context.Operand1.Type, GeneralPurposeRegister.ECX); before.AppendInstruction(X86.Mov, ecx, context.Operand1); context.Operand1 = ecx; } }
/// <summary> /// Visitation function for <see cref="IX86Visitor.Shl"/> instructions. /// </summary> /// <param name="context">The context.</param> void IX86Visitor.Shl(Context context) { if (context.Operand1 is ConstantOperand) return; RegisterOperand ecx = new RegisterOperand(BuiltInSigType.IntPtr, GeneralPurposeRegister.ECX); Context before = context.InsertBefore(); before.SetInstruction(X86.Mov, ecx, context.Operand1); context.Operand1 = context.Result; }
/// <summary> /// Creates the outgoing moves. /// </summary> /// <param name="block">The block.</param> /// <param name="operandStack">The operand stack.</param> /// <param name="joinStack">The join stack.</param> private void CreateOutgoingMoves(BasicBlock block, Stack<Operand> operandStack, Stack<Operand> joinStack) { var context = new Context(instructionSet, block); while (!context.EndOfInstruction && !(context.Instruction is IBranchInstruction)) { context.GotoNext(); } while (operandStack.Count > 0) { var operand = operandStack.Pop(); var destination = joinStack.Pop(); context.InsertBefore().SetInstruction(IR.Instruction.MoveInstruction, destination, operand); } }
/// <summary> /// Visitation function for <see cref="IX86Visitor.Cmp"/> instructions. /// </summary> /// <param name="ctx">The context.</param> void IX86Visitor.Cmp(Context ctx) { Operand left = ctx.Operand1; Operand right = ctx.Operand2; if (left.IsConstant) { Operand ecx = Operand.CreateCPURegister(left.Type, GeneralPurposeRegister.ECX); Context before = ctx.InsertBefore(); before.SetInstruction(X86.Push, null, ecx); before.AppendInstruction(X86.Mov, ecx, left); ctx.Operand1 = ecx; ctx.AppendInstruction(X86.Pop, ecx); } if (right.IsConstant && !Is32Bit(left)) { Operand edx = Operand.CreateCPURegister(BuiltInSigType.Int32, GeneralPurposeRegister.EBX); Context before = ctx.InsertBefore(); before.SetInstruction(X86.Push, null, edx); if (IsSigned(left)) before.AppendInstruction(X86.Movsx, edx, left); else before.AppendInstruction(X86.Movzx, edx, left); ctx.Operand1 = edx; ctx.AppendInstruction(X86.Pop, edx); } }
/// <summary> /// Visitation function for <see cref="IX86Visitor.IMul" /> instructions. /// </summary> /// <param name="context">The context.</param> public void IMul(Context context) { if (!context.Operand2.IsConstant) return; Operand v1 = AllocateVirtualRegister(context.Operand2.Type); Operand operand2 = context.Operand2; context.Operand2 = v1; context.InsertBefore().SetInstruction(X86.Mov, v1, operand2); }
/// <summary> /// Visitation function for <see cref="IX86Visitor.Mul"/> instructions. /// </summary> /// <param name="ctx">The context.</param> void IX86Visitor.Mul(Context ctx) { if (ctx.Operand1.IsConstant) { Operand ecx = Operand.CreateCPURegister(ctx.Operand1.Type, GeneralPurposeRegister.ECX); Context before = ctx.InsertBefore(); before.SetInstruction(X86.Push, null, ecx); before.AppendInstruction(X86.Mov, ecx, ctx.Operand1); ctx.Operand1 = ecx; ctx.AppendInstruction(X86.Pop, ecx); } }
/// <summary> /// Visitation function for SubSInstruction. /// </summary> /// <param name="context">The context.</param> void IIRVisitor.SubSigned(Context context) { if (IsInt64(context.Operand1)) { ExpandSub(context); } else { //FIXME: Move to IRTransformationStage if (context.Operand2 is ConstantOperand && context.Operand1.Type.Type == CilElementType.Char) { RegisterOperand ecx = new RegisterOperand(context.Operand1.Type, GeneralPurposeRegister.ECX); context.InsertBefore().SetInstruction(X86.Mov, ecx, context.Operand2); context.Operand2 = ecx; } } }
/// <summary> /// Visitation function for <see cref="IX86Visitor.Call"/> instructions. /// </summary> /// <param name="context">The context.</param> void IX86Visitor.Call(Context context) { Operand destinationOperand = context.Operand1; if (destinationOperand == null || destinationOperand.IsSymbol) return; if (!(destinationOperand.IsRegister)) { Context before = context.InsertBefore(); Operand eax = Operand.CreateCPURegister(BuiltInSigType.IntPtr, GeneralPurposeRegister.EAX); before.SetInstruction(X86.Mov, eax, destinationOperand); context.Operand1 = eax; } }
/// <summary> /// Extends to r8. /// </summary> /// <param name="context">The context.</param> private static void ExtendToR8(Context context) { Operand xmm5 = Operand.CreateCPURegister(BuiltInSigType.Double, SSE2Register.XMM5); Operand xmm6 = Operand.CreateCPURegister(BuiltInSigType.Double, SSE2Register.XMM6); Context before = context.InsertBefore(); if (context.Result.Type.Type == CilElementType.R4) { before.SetInstruction(X86.Cvtss2sd, xmm5, context.Result); context.Result = xmm5; } if (context.Operand1.Type.Type == CilElementType.R4) { before.SetInstruction(X86.Cvtss2sd, xmm6, context.Operand1); context.Operand1 = xmm6; } }