/// <summary> /// Visitation function for <see cref="CIL.ICILVisitor.BinaryBranch"/>. /// </summary> /// <param name="ctx">The context.</param> void CIL.ICILVisitor.BinaryBranch(Context ctx) { bool swap = ctx.Operand1 is ConstantOperand; IBranch branch = ctx.Branch; IR.ConditionCode conditionCode = ConvertCondition((ctx.Instruction as CIL.BinaryBranchInstruction).OpCode); if (swap) { ctx.SetInstruction(CPUx86.Instruction.CmpInstruction, ctx.Operand2, ctx.Operand1); ctx.AppendInstruction(CPUx86.Instruction.BranchInstruction, GetOppositeConditionCode(conditionCode)); } else { ctx.SetInstruction(CPUx86.Instruction.CmpInstruction, ctx.Operand1, ctx.Operand2); ctx.AppendInstruction(CPUx86.Instruction.BranchInstruction, conditionCode); } ctx.SetBranch(branch.Targets[0]); }
/// <summary> /// Visitation function for <see cref="IR.IIRVisitor.IntegerCompareInstruction"/> instruction. /// </summary> /// <param name="ctx">The context.</param> void IR.IIRVisitor.IntegerCompareInstruction(Context ctx) { EmitOperandConstants(ctx); IR.ConditionCode condition = ctx.ConditionCode; ctx.SetInstruction(CPUx86.Instruction.CmpInstruction, ctx.Result, ctx.Operand1); if (IsUnsigned(ctx.Operand1) || IsUnsigned(ctx.Result)) { ctx.AppendInstruction(CPUx86.Instruction.SetccInstruction, GetUnsignedConditionCode(condition), ctx.Result); } else { ctx.AppendInstruction(CPUx86.Instruction.SetccInstruction, condition, ctx.Result); } if (ctx.Result is RegisterOperand) { RegisterOperand rop = new RegisterOperand(new SigType(CilElementType.U1), ((RegisterOperand)ctx.Result).Register); ctx.AppendInstruction(CPUx86.Instruction.MovzxInstruction, rop, rop); } }
/// <summary> /// Floatings the point compare instruction. /// </summary> /// <param name="ctx">The context.</param> void IR.IIRVisitor.FloatingPointCompareInstruction(Context ctx) { Operand op0 = ctx.Result; Operand left = EmitConstant(ctx.Operand1); Operand right = EmitConstant(ctx.Operand2); //ctx.Remove(); ctx.Operand1 = left; ctx.Operand2 = right; // Swap the operands if necessary... if (left is MemoryOperand && right is RegisterOperand) { SwapComparisonOperands(ctx); left = ctx.Operand1; right = ctx.Operand2; } IR.ConditionCode setcc = IR.ConditionCode.Equal; IR.ConditionCode code = ctx.ConditionCode; ctx.SetInstruction(CPUx86.Instruction.NopInstruction); // x86 is messed up :( switch (code) { case IR.ConditionCode.Equal: break; case IR.ConditionCode.NotEqual: break; case IR.ConditionCode.UnsignedGreaterOrEqual: setcc = IR.ConditionCode.GreaterOrEqual; break; case IR.ConditionCode.UnsignedGreaterThan: setcc = IR.ConditionCode.GreaterThan; break; case IR.ConditionCode.UnsignedLessOrEqual: setcc = IR.ConditionCode.LessOrEqual; break; case IR.ConditionCode.UnsignedLessThan: setcc = IR.ConditionCode.LessThan; break; case IR.ConditionCode.GreaterOrEqual: setcc = IR.ConditionCode.UnsignedGreaterOrEqual; break; case IR.ConditionCode.GreaterThan: setcc = IR.ConditionCode.UnsignedGreaterThan; break; case IR.ConditionCode.LessOrEqual: setcc = IR.ConditionCode.UnsignedLessOrEqual; break; case IR.ConditionCode.LessThan: setcc = IR.ConditionCode.UnsignedLessThan; break; } if (!(left is RegisterOperand)) { RegisterOperand xmm2 = new RegisterOperand(left.Type, SSE2Register.XMM2); if (left.Type.Type == CilElementType.R4) { ctx.AppendInstruction(CPUx86.Instruction.MovssInstruction, xmm2, left); } else { ctx.AppendInstruction(CPUx86.Instruction.MovsdInstruction, xmm2, left); } left = xmm2; } // Compare using the smallest precision if (left.Type.Type == CilElementType.R4 && right.Type.Type == CilElementType.R8) { RegisterOperand rop = new RegisterOperand(new SigType(CilElementType.R4), SSE2Register.XMM4); ctx.AppendInstruction(CPUx86.Instruction.Cvtsd2ssInstruction, rop, right); right = rop; } if (left.Type.Type == CilElementType.R8 && right.Type.Type == CilElementType.R4) { RegisterOperand rop = new RegisterOperand(new SigType(CilElementType.R4), SSE2Register.XMM3); ctx.AppendInstruction(CPUx86.Instruction.Cvtsd2ssInstruction, rop, left); left = rop; } if (left.Type.Type == CilElementType.R4) { switch (code) { case IR.ConditionCode.Equal: ctx.AppendInstruction(CPUx86.Instruction.UcomissInstruction, left, right); break; case IR.ConditionCode.NotEqual: goto case IR.ConditionCode.Equal; case IR.ConditionCode.UnsignedGreaterOrEqual: goto case IR.ConditionCode.Equal; case IR.ConditionCode.UnsignedGreaterThan: goto case IR.ConditionCode.Equal; case IR.ConditionCode.UnsignedLessOrEqual: goto case IR.ConditionCode.Equal; case IR.ConditionCode.UnsignedLessThan: goto case IR.ConditionCode.Equal; case IR.ConditionCode.GreaterOrEqual: ctx.AppendInstruction(CPUx86.Instruction.ComissInstruction, left, right); break; case IR.ConditionCode.GreaterThan: goto case IR.ConditionCode.GreaterOrEqual; case IR.ConditionCode.LessOrEqual: goto case IR.ConditionCode.GreaterOrEqual; case IR.ConditionCode.LessThan: goto case IR.ConditionCode.GreaterOrEqual; } } else { switch (code) { case IR.ConditionCode.Equal: ctx.AppendInstruction(CPUx86.Instruction.UcomisdInstruction, left, right); break; case IR.ConditionCode.NotEqual: goto case IR.ConditionCode.Equal; case IR.ConditionCode.UnsignedGreaterOrEqual: goto case IR.ConditionCode.Equal; case IR.ConditionCode.UnsignedGreaterThan: goto case IR.ConditionCode.Equal; case IR.ConditionCode.UnsignedLessOrEqual: goto case IR.ConditionCode.Equal; case IR.ConditionCode.UnsignedLessThan: goto case IR.ConditionCode.Equal; case IR.ConditionCode.GreaterOrEqual: ctx.AppendInstruction(CPUx86.Instruction.ComisdInstruction, left, right); break; case IR.ConditionCode.GreaterThan: goto case IR.ConditionCode.GreaterOrEqual; case IR.ConditionCode.LessOrEqual: goto case IR.ConditionCode.GreaterOrEqual; case IR.ConditionCode.LessThan: goto case IR.ConditionCode.GreaterOrEqual; } } // Determine the result ctx.AppendInstruction(CPUx86.Instruction.SetccInstruction, setcc, op0); // Extend this to the full register, if we're storing it in a register if (op0 is RegisterOperand) { RegisterOperand rop = new RegisterOperand(new SigType(CilElementType.U1), ((RegisterOperand)op0).Register); ctx.AppendInstruction(CPUx86.Instruction.MovzxInstruction, op0, rop); } }