public Reg CGenFloat(Env env, CGenState state) { Reg ret; // 1. Load lhs to ST0. Now the float stack should only contain one element. // // memory stack: // +-----+ // | | // | ... | <- %esp // +-----+ // // float stack: // +-----+ // | lhs | <- %st(0) // +-----+ // ret = lhs.CGenValue(env, state); if (ret != Reg.ST0) { throw new InvalidOperationException(); } // 2. Pop from float stack, push into memory stack. Now the float stack should be empty. // // memory stack: // +-----+ // | | // | ... | // | lhs | <- %esp has decreased by 4 // +-----+ // // float stack: // +-----+ empty // Int32 stack_size = state.CGenPushFloatP(); // 3. Load rhs to ST0. Now the float stack should only contain one element. // // memory stack: // +-----+ // | | // | ... | // | lhs | <- %esp // +-----+ // // float stack: // +-----+ // | rhs | <- %st(0) // +-----+ // ret = rhs.CGenValue(env, state); if (ret != Reg.ST0) { throw new InvalidOperationException(); } // 4. Pop double from memory stack, push into float stack. Now both lhs and rhs are in float stack. // // memory stack: // +-----+ // | | // | ... | <- %esp // +-----+ // // float stack: // +-----+ // | rhs | <- %st(1) // +-----+ // | lhs | <- %st(0) // +-----+ // state.CGenPopFloat(stack_size); // 5. Perform operation. FPU would pop both operands and push answer back in. // // memory stack: // +-----+ // | | // | ... | <- %esp // +-----+ // // float stack: // +-----+ // | ans | <- %st(0) // +-----+ // OperateFloat(state); return Reg.ST0; }
/// <summary> /// 1. %st(0) = left, %st(1) = right, stack unchanged /// 2. OperateDouble /// </summary> public void CGenFloat(CGenState state) { // 1. Load Left to ST0. Now the float stack should only contain one element. // // memory stack: // +-----+ // | | // | ... | <- %esp // +-----+ // // float stack: // +-----+ // | Left | <- %st(0) // +-----+ // var ret = this.Left.CGenValue(state); if (ret != Reg.ST0) { throw new InvalidOperationException(); } // 2. Pop from float stack, push into memory stack. Now the float stack should be empty. // // memory stack: // +-----+ // | | // | ... | // | Left | <- %esp has decreased by 4 // +-----+ // // float stack: // +-----+ empty // Int32 stack_size = state.CGenPushFloatP(); // 3. Load Right to ST0. Now the float stack should only contain one element. // // memory stack: // +-----+ // | | // | ... | // | Left | <- %esp // +-----+ // // float stack: // +-----+ // | Right | <- %st(0) // +-----+ // ret = this.Right.CGenValue(state); if (ret != Reg.ST0) { throw new InvalidOperationException(); } // 4. Pop double from memory stack, push into float stack. Now both Left and Right are in float stack. // // memory stack: // +-----+ // | | // | ... | <- %esp // +-----+ // // float stack: // +-----+ // | Right | <- %st(1) // +-----+ // | Left | <- %st(0) // +-----+ // state.CGenPopFloat(stack_size); // 5. Perform operation. FPU would pop both operands and push answer back in. // // memory stack: // +-----+ // | | // | ... | <- %esp // +-----+ // // float stack: // +-----+ // | ans | <- %st(0) // +-----+ // OperateFloat(state); }