X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=tools%2Ftranslate.c;h=8d2fb6fd376ea0a06a289b2c8432bf826903d2e1;hb=fdd5548ad19cb8fb0e7f3ae46d201c6bc9d264c9;hp=66f2a50abaeed8749a8945fe475a94432b8468a8;hpb=de041e5bb00202dfd32327aaed9fc09c4ed28b95;p=ia32rtools.git diff --git a/tools/translate.c b/tools/translate.c index 66f2a50..8d2fb6f 100644 --- a/tools/translate.c +++ b/tools/translate.c @@ -275,6 +275,22 @@ static void printf_number(char *buf, size_t buf_size, snprintf(buf, buf_size, number < 10 ? "%lu" : "0x%02lx", number); } +static int check_segment_prefix(const char *s) +{ + if (s[0] == 0 || s[1] != 's' || s[2] != ':') + return 0; + + switch (s[0]) { + case 'c': return 1; + case 'd': return 2; + case 's': return 3; + case 'e': return 4; + case 'f': return 5; + case 'g': return 6; + default: return 0; + } +} + static int parse_reg(enum opr_lenmod *reg_lmod, const char *s) { int reg; @@ -326,8 +342,8 @@ static int parse_indmode(char *name, int *regmask, int need_c_cvt) s++; *d = 0; - // skip 'ds:' prefix - if (IS_START(s, "ds:")) + // skip '?s:' prefixes + if (check_segment_prefix(s)) s += 3; s = next_idt(w, sizeof(w), s); @@ -373,7 +389,8 @@ static int is_reg_in_str(const char *s) return 0; } -static const char *parse_stack_el(const char *name, char *extra_reg) +static const char *parse_stack_el(const char *name, char *extra_reg, + int early_try) { const char *p, *p2, *s; char *endp = NULL; @@ -381,31 +398,34 @@ static const char *parse_stack_el(const char *name, char *extra_reg) long val; int len; - p = name; - if (IS_START(p + 3, "+ebp+") && is_reg_in_str(p)) { - p += 4; - if (extra_reg != NULL) { - strncpy(extra_reg, name, 3); - extra_reg[4] = 0; + if (g_bp_frame || early_try) + { + p = name; + if (IS_START(p + 3, "+ebp+") && is_reg_in_str(p)) { + p += 4; + if (extra_reg != NULL) { + strncpy(extra_reg, name, 3); + extra_reg[4] = 0; + } } - } - if (IS_START(p, "ebp+")) { - p += 4; + if (IS_START(p, "ebp+")) { + p += 4; - p2 = strchr(p, '+'); - if (p2 != NULL && is_reg_in_str(p)) { - if (extra_reg != NULL) { - strncpy(extra_reg, p, p2 - p); - extra_reg[p2 - p] = 0; + p2 = strchr(p, '+'); + if (p2 != NULL && is_reg_in_str(p)) { + if (extra_reg != NULL) { + strncpy(extra_reg, p, p2 - p); + extra_reg[p2 - p] = 0; + } + p = p2 + 1; } - p = p2 + 1; - } - if (!('0' <= *p && *p <= '9')) - return p; + if (!('0' <= *p && *p <= '9')) + return p; - return NULL; + return NULL; + } } if (!IS_START(name, "esp+")) @@ -474,7 +494,7 @@ static int guess_lmod_from_c_type(enum opr_lenmod *lmod, static const char *dword_types[] = { "int", "_DWORD", "UINT_PTR", "DWORD", "WPARAM", "LPARAM", "UINT", "__int32", - "LONG", "HIMC", "BOOL", + "LONG", "HIMC", "BOOL", "size_t", }; static const char *word_types[] = { "uint16_t", "int16_t", "_WORD", "WORD", @@ -610,7 +630,10 @@ static int parse_operand(struct parsed_opr *opr, if (label != NULL) { opr->type = OPT_LABEL; - if (IS_START(label, "ds:")) { + ret = check_segment_prefix(label); + if (ret != 0) { + if (ret >= 5) + aerr("fs/gs used\n"); opr->had_ds = 1; label += 3; } @@ -656,7 +679,10 @@ static int parse_operand(struct parsed_opr *opr, if (wordc_in != 1) aerr("parse_operand 1 word expected\n"); - if (IS_START(words[w], "ds:")) { + ret = check_segment_prefix(words[w]); + if (ret != 0) { + if (ret >= 5) + aerr("fs/gs used\n"); opr->had_ds = 1; memmove(words[w], words[w] + 3, strlen(words[w]) - 2); } @@ -669,10 +695,11 @@ static int parse_operand(struct parsed_opr *opr, aerr("[] parse failure\n"); parse_indmode(opr->name, regmask_indirect, 1); - if (opr->lmod == OPLM_UNSPEC && parse_stack_el(opr->name, NULL)) { + if (opr->lmod == OPLM_UNSPEC && parse_stack_el(opr->name, NULL, 1)) + { // might be an equ struct parsed_equ *eq = - equ_find(NULL, parse_stack_el(opr->name, NULL), &i); + equ_find(NULL, parse_stack_el(opr->name, NULL, 1), &i); if (eq) opr->lmod = eq->lmod; } @@ -1316,7 +1343,7 @@ static struct parsed_equ *equ_find(struct parsed_op *po, const char *name, static int is_stack_access(struct parsed_op *po, const struct parsed_opr *popr) { - return (parse_stack_el(popr->name, NULL) + return (parse_stack_el(popr->name, NULL, 0) || (g_bp_frame && !(po->flags & OPF_EBP_S) && IS_START(popr->name, "ebp"))); } @@ -1347,7 +1374,7 @@ static void parse_stack_access(struct parsed_op *po, ferr(po, "ebp- parse of '%s' failed\n", name); } else { - bp_arg = parse_stack_el(name, ofs_reg); + bp_arg = parse_stack_el(name, ofs_reg, 0); snprintf(g_comment, sizeof(g_comment), "%s", bp_arg); eq = equ_find(po, bp_arg, &offset); if (eq == NULL) @@ -2743,12 +2770,16 @@ static int collect_call_args_r(struct parsed_op *po, int i, ferr(po, "arg collect %d/%d hit '%s' with %d stack args\n", arg, pp->argc, opr_name(&ops[j], 0), pp_tmp->argc_stack); } - else if (ops[j].op == OP_ADD && ops[j].operand[0].reg == xSP) { + // esp adjust of 0 means we collected it before + else if (ops[j].op == OP_ADD && ops[j].operand[0].reg == xSP + && (ops[j].operand[1].type != OPT_CONST + || ops[j].operand[1].val != 0)) + { if (pp->is_unresolved) break; - ferr(po, "arg collect %d/%d hit esp adjust\n", - arg, pp->argc); + ferr(po, "arg collect %d/%d hit esp adjust of %d\n", + arg, pp->argc, ops[j].operand[1].val); } else if (ops[j].op == OP_POP) { if (pp->is_unresolved) @@ -2786,9 +2817,12 @@ static int collect_call_args_r(struct parsed_op *po, int i, ops[j].p_argnum = arg + 1; save_args |= 1 << arg; } - else if (ops[j].p_argnum < arg + 1) - ferr(&ops[j], "p_argnum conflict (%d<%d) for '%s'\n", - ops[j].p_argnum, arg + 1, pp->name); + else if (ops[j].p_argnum < arg + 1) { + // XXX: might kill valid var.. + //*save_arg_vars &= ~(1 << (ops[j].p_argnum - 1)); + ops[j].p_argnum = arg + 1; + save_args |= 1 << arg; + } } else if (ops[j].p_argnum == 0) ops[j].flags |= OPF_RMD; @@ -3096,22 +3130,33 @@ static void gen_func(FILE *fout, FILE *fhdr, const char *funcn, int opcnt) } while (i < opcnt); } else { - for (i = 0; i < opcnt; i++) { + int ecx_push = 0, esp_sub = 0; + + i = 0; + while (ops[i].op == OP_PUSH && IS(opr_name(&ops[i], 0), "ecx")) { + ops[i].flags |= OPF_RMD; + g_stack_fsz += 4; + ecx_push++; + i++; + } + + for (; i < opcnt; i++) { if (ops[i].op == OP_PUSH || (ops[i].flags & (OPF_JMP|OPF_TAIL))) break; if (ops[i].op == OP_SUB && ops[i].operand[0].reg == xSP && ops[i].operand[1].type == OPT_CONST) { - g_sp_frame = 1; + g_stack_fsz = ops[i].operand[1].val; + ops[i].flags |= OPF_RMD; + esp_sub = 1; break; } } found = 0; - if (g_sp_frame) + if (ecx_push || esp_sub) { - g_stack_fsz = ops[i].operand[1].val; - ops[i].flags |= OPF_RMD; + g_sp_frame = 1; i++; do { @@ -3125,14 +3170,31 @@ static void gen_func(FILE *fout, FILE *fhdr, const char *funcn, int opcnt) j--; } - if (ops[j].op != OP_ADD - || !IS(opr_name(&ops[j], 0), "esp") - || ops[j].operand[1].type != OPT_CONST - || ops[j].operand[1].val != g_stack_fsz) - ferr(&ops[j], "'add esp' expected\n"); - ops[j].flags |= OPF_RMD; + if (ecx_push > 0) { + for (l = 0; l < ecx_push; l++) { + if (ops[j].op != OP_POP + || !IS(opr_name(&ops[j], 0), "ecx")) + { + ferr(&ops[j], "'pop ecx' expected\n"); + } + ops[j].flags |= OPF_RMD; + j--; + } + + found = 1; + } + + if (esp_sub) { + if (ops[j].op != OP_ADD + || !IS(opr_name(&ops[j], 0), "esp") + || ops[j].operand[1].type != OPT_CONST + || ops[j].operand[1].val != g_stack_fsz) + ferr(&ops[j], "'add esp' expected\n"); + ops[j].flags |= OPF_RMD; + + found = 1; + } - found = 1; i++; } while (i < opcnt); }