public void CGenTest(Reg ret, CGenState state) { // test Cond switch (ret) { case Reg.EAX: state.TESTL(Reg.EAX, Reg.EAX); break; case Reg.ST0: /// Compare Expr with 0.0 /// < see cref = "BinaryComparisonOp.OperateFloat(CGenState)" /> state.FLDZ(); state.FUCOMIP(); state.FSTP(Reg.ST0); break; default: throw new InvalidProgramException(); } }
public override Reg CGenValue(CGenState state) { Reg ret = this.Expr.CGenValue(state); switch (ret) { case Reg.EAX: state.TESTL(Reg.EAX, Reg.EAX); state.SETE(Reg.AL); state.MOVZBL(Reg.AL, Reg.EAX); return Reg.EAX; case Reg.ST0: /// Compare Expr with 0.0 /// < see cref = "BinaryComparisonOp.OperateFloat(CGenState)" /> state.FLDZ(); state.FUCOMIP(); state.FSTP(Reg.ST0); state.SETE(Reg.AL); state.MOVZBL(Reg.AL, Reg.EAX); return Reg.EAX; default: throw new InvalidProgramException(); } }
// // test Cond // jz false ---+ // true_expr | // +------- jmp finish | // | false: <--------+ // | false_expr // +--> finish: // public override Reg CGenValue(CGenState state) { Int32 stack_size = state.StackSize; Reg ret = this.Cond.CGenValue(state); state.CGenForceStackSizeTo(stack_size); // test Cond switch (ret) { case Reg.EAX: state.TESTL(Reg.EAX, Reg.EAX); break; case Reg.ST0: /// Compare Expr with 0.0 /// < see cref = "BinaryComparisonOp.OperateFloat(CGenState)" /> state.FLDZ(); state.FUCOMIP(); state.FSTP(Reg.ST0); break; default: throw new InvalidProgramException(); } Int32 false_label = state.RequestLabel(); Int32 finish_label = state.RequestLabel(); state.JZ(false_label); this.TrueExpr.CGenValue(state); state.JMP(finish_label); state.CGenLabel(false_label); ret = this.FalseExpr.CGenValue(state); state.CGenLabel(finish_label); return ret; }
public override Reg CGenValue(CGenState state) { Int32 label_set = state.label_idx; state.label_idx++; Int32 label_finish = state.label_idx; state.label_idx++; Reg ret = this.Left.CGenValue(state); switch (ret) { case Reg.EAX: state.TESTL(Reg.EAX, Reg.EAX); state.JNZ(label_set); break; case Reg.ST0: state.FLDZ(); state.FUCOMIP(); state.FSTP(Reg.ST0); state.JNZ(label_set); break; default: throw new InvalidProgramException(); } ret = this.Right.CGenValue(state); switch (ret) { case Reg.EAX: state.TESTL(Reg.EAX, Reg.EAX); state.JNZ(label_set); break; case Reg.ST0: state.FLDZ(); state.FUCOMIP(); state.FSTP(Reg.ST0); state.JNZ(label_set); break; default: throw new InvalidProgramException(); } state.MOVL(0, Reg.EAX); state.JMP(label_finish); state.CGenLabel(label_set); state.MOVL(1, Reg.EAX); state.CGenLabel(label_finish); return Reg.EAX; }
/// <summary> /// Before: %st(0) = left, %st(1) = right, stack unchanged. /// After: with SetDouble, %eax = left op right, stack unchanged. /// </summary> public override sealed void OperateDouble(CGenState state) { // In the beginning, %st(0) = Left, %st(1) = Right. // // float stack: // +-----+ // | rhs | <- %st(1) // +-----+ // | lhs | <- %st(0) // +-----+ // // 1. Do comparison between %st(0) and %st(1). // Pop one Value from FPU stack. // // float stack: // +-----+ // | rhs | <- %st(0) // +-----+ // state.FUCOMIP(); // 2. Pop another Value from FPU stack. // // float stack: // +-----+ empty // state.FSTP(Reg.ST0); // 3. Set bit based on comparison result. SetDouble(state); state.MOVZBL(Reg.AL, Reg.EAX); }