X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;ds=sidebyside;f=tools%2Ftranslate.c;h=e9ea443e62361e40a23b53e2dd50236ec67d542a;hb=25a330eb4fbab19f36ef6bd8e2f6f817e90b870f;hp=5acdd11f817094ea1096e147a240805553dfdd38;hpb=c0de901581e6edfc9b0a18fe6bb89ee56da12804;p=ia32rtools.git diff --git a/tools/translate.c b/tools/translate.c index 5acdd11..e9ea443 100644 --- a/tools/translate.c +++ b/tools/translate.c @@ -57,6 +57,7 @@ enum op_flags { OPF_LOCK = (1 << 17), /* op has lock prefix */ OPF_VAPUSH = (1 << 18), /* vararg ptr push (as call arg) */ OPF_DONE = (1 << 19), /* already fully handled by analysis */ + OPF_PPUSH = (1 << 20), /* part of complex push-pop graph */ }; enum op_op { @@ -113,7 +114,7 @@ enum op_op { // x87 // mmx OP_EMMS, - // mmx + // undefined OP_UD2, }; @@ -176,9 +177,10 @@ struct parsed_op { }; // datap: -// OP_CALL - parser proto hint (str) +// OP_CALL - parser proto hint (str) // (OPF_CC) - points to one of (OPF_FLAGS) that affects cc op -// OP_POP - points to OP_PUSH in push/pop pair +// OP_PUSH - points to OP_POP in complex push/pop graph +// OP_POP - points to OP_PUSH in simple push/pop pair struct parsed_equ { char name[64]; @@ -234,6 +236,7 @@ static int g_sp_frame; static int g_stack_frame_used; static int g_stack_fsz; static int g_ida_func_attr; +static int g_skip_func; static int g_allow_regfunc; static int g_quiet_pp; static int g_header_mode; @@ -984,7 +987,8 @@ static void parse_op(struct parsed_op *op, char words[16][256], int wordc) } if (i == ARRAY_SIZE(op_table)) { - anote("unhandled op: '%s'\n", words[0]); + if (!g_skip_func) + aerr("unhandled op: '%s'\n", words[0]); i--; // OP_UD2 } w++; @@ -2259,22 +2263,44 @@ static int scan_for_pop_ret(int i, int opcnt, const char *reg, return found ? 0 : -1; } -static void scan_for_pop_const(int i, int opcnt) +static void scan_for_pop_const(int i, int opcnt, int *regmask_pp) { + struct parsed_op *po; + int is_multipath = 0; int j; for (j = i + 1; j < opcnt; j++) { - if ((ops[j].flags & (OPF_JMP|OPF_TAIL|OPF_RSAVE)) - || ops[j].op == OP_PUSH || g_labels[i] != NULL) + po = &ops[j]; + + if (po->op == OP_JMP && po->btj == NULL) { + ferr_assert(po, po->bt_i >= 0); + j = po->bt_i - 1; + continue; + } + + if ((po->flags & (OPF_JMP|OPF_TAIL|OPF_RSAVE)) + || po->op == OP_PUSH) { break; } - if (ops[j].op == OP_POP && !(ops[j].flags & (OPF_RMD|OPF_DONE))) + if (g_labels[j] != NULL) + is_multipath = 1; + + if (po->op == OP_POP && !(po->flags & OPF_RMD)) { - ops[i].flags |= OPF_RMD | OPF_DONE; - ops[j].flags |= OPF_DONE; - ops[j].datap = &ops[i]; + is_multipath |= !!(po->flags & OPF_PPUSH); + if (is_multipath) { + ops[i].flags |= OPF_PPUSH | OPF_DONE; + ops[i].datap = po; + po->flags |= OPF_PPUSH | OPF_DONE; + *regmask_pp |= 1 << po->operand[0].reg; + } + else { + ops[i].flags |= OPF_RMD | OPF_DONE; + po->flags |= OPF_DONE; + po->datap = &ops[i]; + } break; } } @@ -3813,11 +3839,12 @@ static void gen_func(FILE *fout, FILE *fhdr, const char *funcn, int opcnt) int need_tmp64 = 0; int had_decl = 0; int label_pending = 0; - int regmask_save = 0; - int regmask_arg = 0; - int regmask_now = 0; - int regmask_init = 0; - int regmask = 0; + int regmask_save = 0; // regs saved/restored in this func + int regmask_arg = 0; // regs carrying function args (fastcall, etc) + int regmask_now; // temp + int regmask_init = 0; // regs that need zero initialization + int regmask_pp = 0; // regs used in complex push-pop graph + int regmask = 0; // used regs int pfomask = 0; int found = 0; int depth = 0; @@ -3997,7 +4024,7 @@ tailcall: } else if (po->op == OP_PUSH && !(po->flags & OPF_FARG) && !(po->flags & OPF_RSAVE) && po->operand[0].type == OPT_CONST) - scan_for_pop_const(i, opcnt); + scan_for_pop_const(i, opcnt, ®mask_pp); } // pass5: @@ -4383,6 +4410,7 @@ tailcall: } } + // declare normal registers regmask_now = regmask & ~regmask_arg; regmask_now &= ~(1 << xSP); if (regmask_now & 0x00ff) { @@ -4429,6 +4457,16 @@ tailcall: } } + // declare push-pop temporaries + if (regmask_pp) { + for (reg = 0; reg < 8; reg++) { + if (regmask_pp & (1 << reg)) { + fprintf(fout, " u32 pp_%s;\n", regs_r32[reg]); + had_decl = 1; + } + } + } + if (cond_vars) { for (i = 0; i < 8; i++) { if (cond_vars & (1 << i)) { @@ -5368,6 +5406,13 @@ tailcall: fprintf(fout, " s_%s = %s;", buf1, buf1); break; } + else if (po->flags & OPF_PPUSH) { + tmp_op = po->datap; + ferr_assert(po, tmp_op != NULL); + out_dst_opr(buf2, sizeof(buf2), po, &tmp_op->operand[0]); + fprintf(fout, " pp_%s = %s;", buf2, buf1); + break; + } else if (g_func_pp->is_userstack) { fprintf(fout, " *(--esp) = %s;", buf1); break; @@ -5378,15 +5423,20 @@ tailcall: break; case OP_POP: + out_dst_opr(buf1, sizeof(buf1), po, &po->operand[0]); if (po->flags & OPF_RSAVE) { - out_dst_opr(buf1, sizeof(buf1), po, &po->operand[0]); fprintf(fout, " %s = s_%s;", buf1, buf1); break; } + else if (po->flags & OPF_PPUSH) { + // push/pop graph + ferr_assert(po, po->datap == NULL); + fprintf(fout, " %s = pp_%s;", buf1, buf1); + break; + } else if (po->datap != NULL) { // push/pop pair tmp_op = po->datap; - out_dst_opr(buf1, sizeof(buf1), po, &po->operand[0]); fprintf(fout, " %s = %s;", buf1, out_src_opr(buf2, sizeof(buf2), tmp_op, &tmp_op->operand[0], @@ -5394,8 +5444,7 @@ tailcall: break; } else if (g_func_pp->is_userstack) { - fprintf(fout, " %s = *esp++;", - out_dst_opr(buf1, sizeof(buf1), po, &po->operand[0])); + fprintf(fout, " %s = *esp++;", buf1); break; } else @@ -5853,7 +5902,7 @@ tailcall: continue; if (po->op == OP_PUSH && po->operand[0].type == OPT_CONST) - scan_for_pop_const(i, opcnt); + scan_for_pop_const(i, opcnt, ®mask_dummy); } // pass4: @@ -6032,17 +6081,8 @@ static void output_hdr_fp(FILE *fout, const struct func_prototype *fp, continue; if (fp->pp != NULL) { - // prefer fp for common style, - // only use output_pp if args are complex - for (j = 0; j < fp->pp->argc; j++) { - if (fp->pp->arg[j].fptr != NULL) - break; - } - if (j != fp->pp->argc) { - output_pp(fout, fp->pp, OPP_ALIGN); - fprintf(fout, ";\n"); - continue; - } + // part of seed, output later + continue; } regmask_dep = fp->regmask_dep; @@ -6130,11 +6170,9 @@ static void output_hdr(FILE *fout) for (i = 0; i < hg_var_cnt; i++) { var = &hg_vars[i]; - if (var->pp != NULL && var->pp->is_fptr) { - fprintf(fout, "extern "); - output_pp(fout, var->pp, 0); - fprintf(fout, ";"); - } + if (var->pp != NULL) + // part of seed + continue; else if (var->is_c_str) fprintf(fout, "extern %-8s %s[];", "char", var->name); else @@ -6151,14 +6189,12 @@ static void output_hdr(FILE *fout) // output function prototypes output_hdr_fp(fout, hg_fp, hg_fp_cnt); - // include passthrough - fprintf(fout, "\n// for translate\n"); + // seed passthrough + fprintf(fout, "\n// - seed -\n"); rewind(g_fhdr); - while (fgets(line, sizeof(line), g_fhdr)) { - if (IS_START(line, "//#")) - fwrite(line, 1, strlen(line), fout); - } + while (fgets(line, sizeof(line), g_fhdr)) + fwrite(line, 1, strlen(line), fout); } // read a line, truncating it if it doesn't fit @@ -6741,7 +6777,7 @@ parse_words: do_pending_endp: // do delayed endp processing to collect switch jumptables if (pending_endp) { - if (in_func && !skip_func && !end && wordc >= 2 + if (in_func && !g_skip_func && !end && wordc >= 2 && ((words[0][0] == 'd' && words[0][2] == 0) || (words[1][0] == 'd' && words[1][2] == 0))) { @@ -6796,7 +6832,7 @@ do_pending_endp: continue; } - if (in_func && !skip_func) { + if (in_func && !g_skip_func) { if (g_header_mode) gen_hdr(g_func, pi); else @@ -6807,7 +6843,7 @@ do_pending_endp: in_func = 0; g_ida_func_attr = 0; skip_warned = 0; - skip_func = 0; + g_skip_func = 0; g_func[0] = 0; func_chunks_used = 0; func_chunk_i = -1; @@ -6841,7 +6877,7 @@ do_pending_endp: words[0], g_func); p = words[0]; if (bsearch(&p, rlist, rlist_len, sizeof(rlist[0]), cmpstringp)) - skip_func = 1; + g_skip_func = 1; strcpy(g_func, words[0]); set_label(0, words[0]); in_func = 1; @@ -6860,10 +6896,10 @@ do_pending_endp: && ops[0].op == OP_JMP && ops[0].operand[0].had_ds) { // import jump - skip_func = 1; + g_skip_func = 1; } - if (!skip_func && func_chunks_used) { + if (!g_skip_func && func_chunks_used) { // start processing chunks struct chunk_item *ci, key = { g_func, 0 }; @@ -6922,8 +6958,8 @@ do_pending_endp: continue; } - if (!in_func || skip_func) { - if (!skip_warned && !skip_func && g_labels[pi] != NULL) { + if (!in_func || g_skip_func) { + if (!skip_warned && !g_skip_func && g_labels[pi] != NULL) { if (verbose) anote("skipping from '%s'\n", g_labels[pi]); skip_warned = 1;