+ // need space for retreg args
+ if (pp->has_retreg) {
+ for (i = 0; i < pp->argc; i++) {
+ if (!pp->arg[i].type.is_retreg)
+ continue;
+ if (IS(pp->arg[i].reg, "ecx") && ecx_ofs >= 0) {
+ reg_ofs[i] = ecx_ofs;
+ continue;
+ }
+ if (IS(pp->arg[i].reg, "edx") && edx_ofs >= 0) {
+ reg_ofs[i] = edx_ofs;
+ continue;
+ }
+ fprintf(f, "\tpushl %%%s\n", pp->arg[i].reg);
+ saved_regs++;
+ sarg_ofs++;
+ reg_ofs[i] = sarg_ofs;
+ }
+ }
+
+ // construct arg stack
+ for (i = argc_repush - 1; i >= 0; i--) {
+ if (pp->arg[i].reg == NULL) {
+ fprintf(f, "\tmovl %d(%%esp), %%ecx\n",
+ (sarg_ofs + stack_args - 1) * 4);
+ fprintf(f, "\tpushl %%ecx\n");
+ stack_args--;
+ }
+ else {
+ const char *reg = pp->arg[i].reg;
+ if (pp->arg[i].type.is_retreg) {
+ reg = "ecx";
+ fprintf(f, "\tlea %d(%%esp), %%ecx\n",
+ (sarg_ofs - reg_ofs[i]) * 4);
+ }
+ else if (IS(reg, "ecx"))
+ // must reload original ecx
+ fprintf(f, "\tmovl %d(%%esp), %%ecx\n",
+ (sarg_ofs - 2) * 4);
+
+ fprintf(f, "\tpushl %%%s\n", reg);
+ }
+ sarg_ofs++;
+ }
+
+ fprintf(f, "\n\tcall %s\n\n", pp_to_name(pp));
+
+ if (!c_is_stdcall && sarg_ofs > saved_regs + 1)
+ fprintf(f, "\tadd $%d,%%esp\n",
+ (sarg_ofs - (saved_regs + 1)) * 4);
+
+ // pop retregs
+ if (pp->has_retreg) {
+ for (i = pp->argc - 1; i >= 0; i--) {
+ if (!pp->arg[i].type.is_retreg)
+ continue;
+ if (IS(pp->arg[i].reg, "ecx") && ecx_ofs >= 0) {
+ continue;
+ }
+ if (IS(pp->arg[i].reg, "edx") && edx_ofs >= 0) {
+ continue;
+ }
+ fprintf(f, "\tpopl %%%s\n", pp->arg[i].reg);
+ }
+ }
+
+ if (!ret64)
+ fprintf(f, "\tpopl %%edx\n");
+ fprintf(f, "\tpopl %%ecx\n");
+
+ if (pp->is_stdcall && pp->argc_stack)
+ fprintf(f, "\tret $%d\n\n", pp->argc_stack * 4);
+ else
+ fprintf(f, "\tret\n\n");