+ }
+
+ // pass4:
+ // - find POPs for PUSHes, rm both
+ // - scan for all used registers
+ // - find flag set ops for their users
+ for (i = 0; i < opcnt; i++) {
+ po = &ops[i];
+ if (po->flags & OPF_RMD)
+ continue;
+
+ if (po->op == OP_PUSH
+ && po->argmask == 0 && !(po->flags & OPF_RSAVE)
+ && po->operand[0].type == OPT_REG)
+ {
+ reg = po->operand[0].reg;
+ if (reg < 0)
+ ferr(po, "reg not set for push?\n");
+
+ depth = 0;
+ ret = scan_for_pop(i + 1, opcnt,
+ po->operand[0].name, i + opcnt, 0, &depth, 0);
+ if (ret == 1) {
+ if (depth > 1)
+ ferr(po, "too much depth: %d\n", depth);
+ if (depth > 0)
+ regmask_save |= 1 << reg;
+
+ po->flags |= OPF_RMD;
+ scan_for_pop(i + 1, opcnt, po->operand[0].name,
+ i + opcnt * 2, 0, &depth, 1);
+ continue;
+ }
+ ret = scan_for_pop_ret(i + 1, opcnt, po->operand[0].name, 0);
+ if (ret == 0) {
+ arg = OPF_RMD;
+ if (regmask & (1 << reg)) {
+ if (regmask_save & (1 << reg))
+ ferr(po, "%s already saved?\n", po->operand[0].name);
+ arg = OPF_RSAVE;
+ }
+ po->flags |= arg;
+ scan_for_pop_ret(i + 1, opcnt, po->operand[0].name, arg);
+ continue;
+ }
+ }
+
+ regmask |= po->regmask_src | po->regmask_dst;
+
+ if (po->flags & OPF_CC)
+ {
+ ret = scan_for_flag_set(i - 1);
+ if (ret < 0)
+ ferr(po, "unable to trace flag setter\n");
+
+ tmp_op = &ops[ret]; // flag setter
+ pfo = split_cond(po, po->op, &dummy);
+ pfomask = 0;
+
+ // to get nicer code, we try to delay test and cmp;
+ // if we can't because of operand modification, or if we
+ // have math op, make it calculate flags explicitly
+ if (tmp_op->op == OP_TEST || tmp_op->op == OP_CMP) {
+ if (scan_for_mod(tmp_op, ret + 1, i) >= 0)
+ pfomask = 1 << pfo;
+ }
+ else {
+ if ((pfo != PFO_Z && pfo != PFO_S && pfo != PFO_P)
+ || scan_for_mod_opr0(tmp_op, ret + 1, i) >= 0)
+ pfomask = 1 << pfo;
+ }
+ if (pfomask) {
+ tmp_op->pfomask |= pfomask;
+ cmp_result_vars |= pfomask;
+ po->datap = tmp_op;
+ }
+
+ if (po->op == OP_ADC || po->op == OP_SBB)
+ cmp_result_vars |= 1 << PFO_C;
+ }