+static int scan_prologue_ecx(int i, int opcnt, int flags_set,
+ int limit, int *ecx_push_out)
+{
+ const struct parsed_proto *pp;
+ int ecx_push = 0, other_push = 0;
+ int ret;
+
+ while (limit > 0 && ops[i].op == OP_PUSH
+ && IS(opr_name(&ops[i], 0), "ecx"))
+ {
+ ops[i].flags |= flags_set;
+ ecx_push++;
+ i++;
+ limit--;
+ }
+
+ ret = i;
+ if (ecx_push == 0 || flags_set != 0)
+ goto out;
+
+ // check if some of the pushes aren't really call args
+ for (; i < opcnt; i++) {
+ if (i > 0 && g_labels[i] != NULL)
+ break;
+ if (ops[i].flags & (OPF_JMP|OPF_TAIL))
+ break;
+ if (ops[i].op == OP_PUSH)
+ other_push++;
+ }
+
+ if (ops[i].op != OP_CALL)
+ goto out;
+
+ pp = ops[i].pp;
+ if (pp == NULL && ops[i].operand[0].type == OPT_LABEL)
+ pp = proto_parse(g_fhdr, opr_name(&ops[i], 0), 1);
+ if (pp == NULL)
+ goto out;
+
+ ferr_assert(&ops[i], ecx_push + other_push >= pp->argc_stack);
+ if (other_push < pp->argc_stack)
+ ecx_push -= pp->argc_stack - other_push;
+
+out:
+ if (ecx_push_out != NULL)
+ *ecx_push_out = ecx_push;
+ return ret;
+}
+