notaz.gp2x.de
/
ia32rtools.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
translate: more float ops
[ia32rtools.git]
/
tools
/
translate.c
diff --git
a/tools/translate.c
b/tools/translate.c
index
a83c6bd
..
a7f629e
100644
(file)
--- a/
tools/translate.c
+++ b/
tools/translate.c
@@
-136,6
+136,11
@@
enum op_op {
OP_FISUB,
OP_FIDIVR,
OP_FISUBR,
OP_FISUB,
OP_FIDIVR,
OP_FISUBR,
+ OP_FCOS,
+ OP_FPATAN,
+ OP_FPTAN,
+ OP_FSIN,
+ OP_FSQRT,
// mmx
OP_EMMS,
// pseudo-ops for lib calls
// mmx
OP_EMMS,
// pseudo-ops for lib calls
@@
-250,7
+255,8
@@
enum ida_func_attr {
};
enum sct_func_attr {
};
enum sct_func_attr {
- SCTFA_CLEAR_SF = (1 << 0), // clear stack frame
+ SCTFA_CLEAR_SF = (1 << 0), // clear stack frame
+ SCTFA_CLEAR_REGS = (1 << 1), // clear registers (mask)
};
enum x87_const {
};
enum x87_const {
@@
-286,6
+292,7
@@
static int g_ida_func_attr;
static int g_sct_func_attr;
static int g_stack_clear_start; // in dwords
static int g_stack_clear_len;
static int g_sct_func_attr;
static int g_stack_clear_start; // in dwords
static int g_stack_clear_len;
+static int g_regmask_init;
static int g_skip_func;
static int g_allow_regfunc;
static int g_quiet_pp;
static int g_skip_func;
static int g_allow_regfunc;
static int g_quiet_pp;
@@
-326,6
+333,7
@@
enum x86_regs {
};
#define mxAX (1 << xAX)
};
#define mxAX (1 << xAX)
+#define mxCX (1 << xCX)
#define mxDX (1 << xDX)
#define mxST0 (1 << xST0)
#define mxST1 (1 << xST1)
#define mxDX (1 << xDX)
#define mxST0 (1 << xST0)
#define mxST1 (1 << xST1)
@@
-1042,6
+1050,11
@@
static const struct {
{ "fisub", OP_FISUB, 1, 1, 0 },
{ "fidivr", OP_FIDIVR, 1, 1, 0 },
{ "fisubr", OP_FISUBR, 1, 1, 0 },
{ "fisub", OP_FISUB, 1, 1, 0 },
{ "fidivr", OP_FIDIVR, 1, 1, 0 },
{ "fisubr", OP_FISUBR, 1, 1, 0 },
+ { "fcos", OP_FCOS, 0, 0, 0 },
+ { "fpatan", OP_FPATAN, 0, 0, OPF_FPOP },
+ { "fptan", OP_FPTAN, 0, 0, OPF_FPUSH },
+ { "fsin", OP_FSIN, 0, 0, 0 },
+ { "fsqrt", OP_FSQRT, 0, 0, 0 },
// mmx
{ "emms", OP_EMMS, 0, 0, OPF_DATA },
{ "movq", OP_MOV, 2, 2, OPF_DATA },
// mmx
{ "emms", OP_EMMS, 0, 0, OPF_DATA },
{ "movq", OP_MOV, 2, 2, OPF_DATA },
@@
-1369,10
+1382,22
@@
static void parse_op(struct parsed_op *op, char words[16][256], int wordc)
case OP_FISUB:
case OP_FIDIVR:
case OP_FISUBR:
case OP_FISUB:
case OP_FIDIVR:
case OP_FISUBR:
+ case OP_FCOS:
+ case OP_FSIN:
+ case OP_FSQRT:
op->regmask_src |= mxST0;
op->regmask_dst |= mxST0;
break;
op->regmask_src |= mxST0;
op->regmask_dst |= mxST0;
break;
+ case OP_FPATAN:
+ op->regmask_src |= mxST0 | mxST1;
+ op->regmask_dst |= mxST0;
+ break;
+
+ case OP_FPTAN:
+ aerr("TODO\n");
+ break;
+
default:
break;
}
default:
break;
}
@@
-4771,21
+4796,6
@@
static void reg_use_pass(int i, int opcnt, unsigned char *cbits,
if (g_bp_frame && !(po->flags & OPF_EBP_S))
regmask_new &= ~(1 << xBP);
if (g_bp_frame && !(po->flags & OPF_EBP_S))
regmask_new &= ~(1 << xBP);
- if (po->op == OP_CALL) {
- // allow fastcall calls from anywhere, calee may be also sitting
- // in some fastcall table even when it's not using reg args
- if (regmask_new & po->regmask_src & (1 << xCX)) {
- *regmask_init |= (1 << xCX);
- regmask_now |= (1 << xCX);
- regmask_new &= ~(1 << xCX);
- }
- if (regmask_new & po->regmask_src & (1 << xDX)) {
- *regmask_init |= (1 << xDX);
- regmask_now |= (1 << xDX);
- regmask_new &= ~(1 << xDX);
- }
- }
-
if (regmask_new != 0)
fnote(po, "uninitialized reg mask: %x\n", regmask_new);
if (regmask_new != 0)
fnote(po, "uninitialized reg mask: %x\n", regmask_new);
@@
-4943,11
+4953,13
@@
static void gen_func(FILE *fout, FILE *fhdr, const char *funcn, int opcnt)
unsigned int uval;
int save_arg_vars[MAX_ARG_GRP] = { 0, };
unsigned char cbits[MAX_OPS / 8];
unsigned int uval;
int save_arg_vars[MAX_ARG_GRP] = { 0, };
unsigned char cbits[MAX_OPS / 8];
+ const char *float_type;
int cond_vars = 0;
int need_tmp_var = 0;
int need_tmp64 = 0;
int had_decl = 0;
int label_pending = 0;
int cond_vars = 0;
int need_tmp_var = 0;
int need_tmp64 = 0;
int had_decl = 0;
int label_pending = 0;
+ int need_double = 0;
int regmask_save = 0; // regs saved/restored in this func
int regmask_arg; // regs from this function args (fastcall, etc)
int regmask_ret; // regs needed on ret
int regmask_save = 0; // regs saved/restored in this func
int regmask_arg; // regs from this function args (fastcall, etc)
int regmask_ret; // regs needed on ret
@@
-4965,6
+4977,8
@@
static void gen_func(FILE *fout, FILE *fhdr, const char *funcn, int opcnt)
g_bp_frame = g_sp_frame = g_stack_fsz = 0;
g_stack_frame_used = 0;
g_bp_frame = g_sp_frame = g_stack_fsz = 0;
g_stack_frame_used = 0;
+ if (g_sct_func_attr & SCTFA_CLEAR_REGS)
+ regmask_init = g_regmask_init;
g_func_pp = proto_parse(fhdr, funcn, 0);
if (g_func_pp == NULL)
g_func_pp = proto_parse(fhdr, funcn, 0);
if (g_func_pp == NULL)
@@
-5091,7
+5105,7
@@
static void gen_func(FILE *fout, FILE *fhdr, const char *funcn, int opcnt)
// - find POPs for PUSHes, rm both
// - scan for all used registers
memset(cbits, 0, sizeof(cbits));
// - find POPs for PUSHes, rm both
// - scan for all used registers
memset(cbits, 0, sizeof(cbits));
- reg_use_pass(0, opcnt, cbits,
0
, ®mask,
+ reg_use_pass(0, opcnt, cbits,
regmask_init
, ®mask,
0, ®mask_save, ®mask_init, regmask_arg);
// pass7:
0, ®mask_save, ®mask_init, regmask_arg);
// pass7:
@@
-5262,11
+5276,15
@@
static void gen_func(FILE *fout, FILE *fhdr, const char *funcn, int opcnt)
if (j == -1)
po->flags |= OPF_32BIT;
}
if (j == -1)
po->flags |= OPF_32BIT;
}
+ else if (po->op == OP_FLD && po->operand[0].lmod == OPLM_QWORD)
+ need_double = 1;
if (po->op == OP_RCL || po->op == OP_RCR || po->op == OP_XCHG)
need_tmp_var = 1;
}
if (po->op == OP_RCL || po->op == OP_RCR || po->op == OP_XCHG)
need_tmp_var = 1;
}
+ float_type = need_double ? "double" : "float";
+
// output starts here
// define userstack size
// output starts here
// define userstack size
@@
-5426,7
+5444,7
@@
static void gen_func(FILE *fout, FILE *fhdr, const char *funcn, int opcnt)
if (regmask_now & 0xff0000) {
for (reg = 16; reg < 24; reg++) {
if (regmask_now & (1 << reg)) {
if (regmask_now & 0xff0000) {
for (reg = 16; reg < 24; reg++) {
if (regmask_now & (1 << reg)) {
- fprintf(fout, "
double f_st%d"
, reg - 16);
+ fprintf(fout, "
%s f_st%d", float_type
, reg - 16);
if (regmask_init & (1 << reg))
fprintf(fout, " = 0");
fprintf(fout, ";\n");
if (regmask_init & (1 << reg))
fprintf(fout, " = 0");
fprintf(fout, ";\n");
@@
-6569,7
+6587,7
@@
static void gen_func(FILE *fout, FILE *fhdr, const char *funcn, int opcnt)
case OP_FILD:
if (po->flags & OPF_FSHIFT)
fprintf(fout, " f_st1 = f_st0;\n");
case OP_FILD:
if (po->flags & OPF_FSHIFT)
fprintf(fout, " f_st1 = f_st0;\n");
- fprintf(fout, " f_st0 = (
double)%s;"
,
+ fprintf(fout, " f_st0 = (
%s)%s;", float_type
,
out_src_opr(buf1, sizeof(buf1), po, &po->operand[0],
lmod_cast(po, po->operand[0].lmod, 1), 0));
strcat(g_comment, " fild");
out_src_opr(buf1, sizeof(buf1), po, &po->operand[0],
lmod_cast(po, po->operand[0].lmod, 1), 0));
strcat(g_comment, " fild");
@@
-6645,7
+6663,7
@@
static void gen_func(FILE *fout, FILE *fhdr, const char *funcn, int opcnt)
case OP_FISUB: j = '-'; break;
default: j = 'x'; break;
}
case OP_FISUB: j = '-'; break;
default: j = 'x'; break;
}
- fprintf(fout, " f_st0 %c= (
double)%s;", j
,
+ fprintf(fout, " f_st0 %c= (
%s)%s;", j, float_type
,
out_src_opr(buf1, sizeof(buf1), po, &po->operand[0],
lmod_cast(po, po->operand[0].lmod, 1), 0));
break;
out_src_opr(buf1, sizeof(buf1), po, &po->operand[0],
lmod_cast(po, po->operand[0].lmod, 1), 0));
break;
@@
-6657,6
+6675,26
@@
static void gen_func(FILE *fout, FILE *fhdr, const char *funcn, int opcnt)
po->op == OP_FIDIVR ? '/' : '-');
break;
po->op == OP_FIDIVR ? '/' : '-');
break;
+ case OP_FCOS:
+ fprintf(fout, " f_st0 = cos%s(f_st0);",
+ need_double ? "" : "f");
+ break;
+
+ case OP_FPATAN:
+ fprintf(fout, " f_st0 = atan%s(f_st1 / f_st0);",
+ need_double ? "" : "f");
+ break;
+
+ case OP_FSIN:
+ fprintf(fout, " f_st0 = sin%s(f_st0);",
+ need_double ? "" : "f");
+ break;
+
+ case OP_FSQRT:
+ fprintf(fout, " f_st0 = sqrt%s(f_st0);",
+ need_double ? "" : "f");
+ break;
+
case OPP_FTOL:
ferr_assert(po, po->flags & OPF_32BIT);
fprintf(fout, " eax = (s32)f_st0;");
case OPP_FTOL:
ferr_assert(po, po->flags & OPF_32BIT);
fprintf(fout, " eax = (s32)f_st0;");
@@
-6784,10
+6822,13
@@
static struct scanned_var {
} *hg_vars;
static int hg_var_cnt;
} *hg_vars;
static int hg_var_cnt;
+static char **hg_refs;
+static int hg_ref_cnt;
+
static void output_hdr_fp(FILE *fout, const struct func_prototype *fp,
int count);
static void output_hdr_fp(FILE *fout, const struct func_prototype *fp,
int count);
-struct func_prototype *hg_fp_add(const char *funcn)
+st
atic st
ruct func_prototype *hg_fp_add(const char *funcn)
{
struct func_prototype *fp;
{
struct func_prototype *fp;
@@
-6849,6
+6890,19
@@
static int hg_fp_cmp_id(const void *p1_, const void *p2_)
}
#endif
}
#endif
+static void hg_ref_add(const char *name)
+{
+ if ((hg_ref_cnt & 0xff) == 0) {
+ hg_refs = realloc(hg_refs, sizeof(hg_refs[0]) * (hg_ref_cnt + 0x100));
+ my_assert_not(hg_refs, NULL);
+ memset(hg_refs + hg_ref_cnt, 0, sizeof(hg_refs[0]) * 0x100);
+ }
+
+ hg_refs[hg_ref_cnt] = strdup(name);
+ my_assert_not(hg_refs[hg_ref_cnt], NULL);
+ hg_ref_cnt++;
+}
+
// recursive register dep pass
// - track saved regs (part 2)
// - try to figure out arg-regs
// recursive register dep pass
// - track saved regs (part 2)
// - try to figure out arg-regs
@@
-7203,6
+7257,24
@@
static void hg_fp_resolve_deps(struct func_prototype *fp)
}
}
}
}
+// make all thiscall/edx arg functions referenced from .data fastcall
+static void do_func_refs_from_data(void)
+{
+ struct func_prototype *fp, fp_s;
+ int i;
+
+ for (i = 0; i < hg_ref_cnt; i++) {
+ strcpy(fp_s.name, hg_refs[i]);
+ fp = bsearch(&fp_s, hg_fp, hg_fp_cnt,
+ sizeof(hg_fp[0]), hg_fp_cmp_name);
+ if (fp == NULL)
+ continue;
+
+ if (fp->argc_stack != 0 && (fp->regmask_dep & (mxCX | mxDX)))
+ fp->regmask_dep |= mxCX | mxDX;
+ }
+}
+
static void output_hdr_fp(FILE *fout, const struct func_prototype *fp,
int count)
{
static void output_hdr_fp(FILE *fout, const struct func_prototype *fp,
int count)
{
@@
-7210,7
+7282,7
@@
static void output_hdr_fp(FILE *fout, const struct func_prototype *fp,
char *p, namebuf[NAMELEN];
const char *name;
int regmask_dep;
char *p, namebuf[NAMELEN];
const char *name;
int regmask_dep;
- int argc_
stack
;
+ int argc_
normal
;
int j, arg;
for (; count > 0; count--, fp++) {
int j, arg;
for (; count > 0; count--, fp++) {
@@
-7248,18
+7320,25
@@
static void output_hdr_fp(FILE *fout, const struct func_prototype *fp,
}
regmask_dep = fp->regmask_dep;
}
regmask_dep = fp->regmask_dep;
- argc_
stack
= fp->argc_stack;
+ argc_
normal
= fp->argc_stack;
fprintf(fout, "%-5s", fp->pp ? fp->pp->ret_type.name :
(fp->has_ret ? "int" : "void"));
fprintf(fout, "%-5s", fp->pp ? fp->pp->ret_type.name :
(fp->has_ret ? "int" : "void"));
- if (regmask_dep && (fp->is_stdcall || argc_stack == 0)
- && (regmask_dep & ~((1 << xCX) | (1 << xDX))) == 0)
+ if (regmask_dep && (fp->is_stdcall || fp->argc_stack > 0)
+ && (regmask_dep & ~mxCX) == 0)
+ {
+ fprintf(fout, "/*__thiscall*/ ");
+ argc_normal++;
+ regmask_dep = 0;
+ }
+ else if (regmask_dep && (fp->is_stdcall || fp->argc_stack == 0)
+ && (regmask_dep & ~(mxCX | mxDX)) == 0)
{
fprintf(fout, " __fastcall ");
{
fprintf(fout, " __fastcall ");
- if (!(regmask_dep & (1 << xDX)) && argc_stack == 0)
- argc_
stack
= 1;
+ if (!(regmask_dep & (1 << xDX)) &&
fp->
argc_stack == 0)
+ argc_
normal
= 1;
else
else
- argc_
stack
+= 2;
+ argc_
normal
+= 2;
regmask_dep = 0;
}
else if (regmask_dep && !fp->is_stdcall) {
regmask_dep = 0;
}
else if (regmask_dep && !fp->is_stdcall) {
@@
-7289,7
+7368,7
@@
static void output_hdr_fp(FILE *fout, const struct func_prototype *fp,
}
}
}
}
- for (j = 0; j < argc_
stack
; j++) {
+ for (j = 0; j < argc_
normal
; j++) {
arg++;
if (arg != 1)
fprintf(fout, ", ");
arg++;
if (arg != 1)
fprintf(fout, ", ");
@@
-7341,6
+7420,9
@@
static void output_hdr(FILE *fout)
for (i = 0; i < hg_fp_cnt; i++)
hg_fp_resolve_deps(&hg_fp[i]);
for (i = 0; i < hg_fp_cnt; i++)
hg_fp_resolve_deps(&hg_fp[i]);
+ // adjust functions referenced from data segment
+ do_func_refs_from_data();
+
// note: messes up .proto ptr, don't use
//qsort(hg_fp, hg_fp_cnt, sizeof(hg_fp[0]), hg_fp_cmp_id);
// note: messes up .proto ptr, don't use
//qsort(hg_fp, hg_fp_cnt, sizeof(hg_fp[0]), hg_fp_cmp_id);
@@
-7384,7
+7466,7
@@
static char *next_word_s(char *w, size_t wsize, char *s)
s = sskip(s);
i = 0;
s = sskip(s);
i = 0;
- if (*s == '\'') {
+ if (*s == '\''
&& s[1] != '\r' && s[1] != '\n'
) {
w[0] = s[0];
for (i = 1; i < wsize - 1; i++) {
if (s[i] == 0) {
w[0] = s[0];
for (i = 1; i < wsize - 1; i++) {
if (s[i] == 0) {
@@
-7438,7
+7520,7
@@
static int is_xref_needed(char *p, char **rlist, int rlist_len)
return 1;
}
return 1;
}
-static int xrefs_show_need(FILE *fasm, char *p,
+static int
ida_
xrefs_show_need(FILE *fasm, char *p,
char **rlist, int rlist_len)
{
int found_need = 0;
char **rlist, int rlist_len)
{
int found_need = 0;
@@
-7485,7
+7567,8
@@
static void scan_variables(FILE *fasm, char **rlist, int rlist_len)
{
struct scanned_var *var;
char line[256] = { 0, };
{
struct scanned_var *var;
char line[256] = { 0, };
- char words[3][256];
+ char words[4][256];
+ int no_identifier;
char *p = NULL;
int wordc;
int l;
char *p = NULL;
int wordc;
int l;
@@
-7524,8
+7607,7
@@
static void scan_variables(FILE *fasm, char **rlist, int rlist_len)
asmln++;
p = line;
asmln++;
p = line;
- if (my_isblank(*p))
- continue;
+ no_identifier = my_isblank(*p);
p = sskip(p);
if (*p == 0 || *p == ';')
p = sskip(p);
if (*p == 0 || *p == ';')
@@
-7545,13
+7627,19
@@
static void scan_variables(FILE *fasm, char **rlist, int rlist_len)
if (wordc < 2)
continue;
if (wordc < 2)
continue;
+ if (no_identifier) {
+ if (wordc >= 3 && IS(words[0], "dd") && IS(words[1], "offset"))
+ hg_ref_add(words[2]);
+ continue;
+ }
+
if (IS_START(words[0], "__IMPORT_DESCRIPTOR_")) {
// when this starts, we don't need anything from this section
break;
}
// check refs comment(s)
if (IS_START(words[0], "__IMPORT_DESCRIPTOR_")) {
// when this starts, we don't need anything from this section
break;
}
// check refs comment(s)
- if (!xrefs_show_need(fasm, p, rlist, rlist_len))
+ if (!
ida_
xrefs_show_need(fasm, p, rlist, rlist_len))
continue;
if ((hg_var_cnt & 0xff) == 0) {
continue;
if ((hg_var_cnt & 0xff) == 0) {
@@
-7581,8
+7669,11
@@
static void scan_variables(FILE *fasm, char **rlist, int rlist_len)
continue;
}
continue;
}
- if (IS(words[1], "dd"))
+ if (IS(words[1], "dd"))
{
var->lmod = OPLM_DWORD;
var->lmod = OPLM_DWORD;
+ if (wordc >= 4 && IS(words[2], "offset"))
+ hg_ref_add(words[3]);
+ }
else if (IS(words[1], "dw"))
var->lmod = OPLM_WORD;
else if (IS(words[1], "db")) {
else if (IS(words[1], "dw"))
var->lmod = OPLM_WORD;
else if (IS(words[1], "db")) {
@@
-7907,6
+7998,7
@@
int main(int argc, char *argv[])
{
static const char *attrs[] = {
"clear_sf",
{
static const char *attrs[] = {
"clear_sf",
+ "clear_regmask",
};
// parse manual attribute-list comment
};
// parse manual attribute-list comment
@@
-7921,12
+8013,17
@@
int main(int argc, char *argv[])
break;
}
}
break;
}
}
- if (i == 0 && *p == '=') {
- // clear_sf=start,len (in dwords)
- ret = sscanf(p, "=%d,%d%n", &g_stack_clear_start,
- &g_stack_clear_len, &j);
+ if (*p == '=') {
+ j = ret = 0;
+ if (i == 0)
+ // clear_sf=start,len (in dwords)
+ ret = sscanf(p, "=%d,%d%n", &g_stack_clear_start,
+ &g_stack_clear_len, &j);
+ else if (i == 1)
+ // clear_regmask=<mask>
+ ret = sscanf(p, "=%x%n", &g_regmask_init, &j) + 1;
if (ret < 2) {
if (ret < 2) {
- anote("unparsed
clear_sf
attr value: %s\n", p);
+ anote("unparsed attr value: %s\n", p);
break;
}
p += j;
break;
}
p += j;
@@
-8108,6
+8205,7
@@
do_pending_endp:
g_sct_func_attr = 0;
g_stack_clear_start = 0;
g_stack_clear_len = 0;
g_sct_func_attr = 0;
g_stack_clear_start = 0;
g_stack_clear_len = 0;
+ g_regmask_init = 0;
skip_warned = 0;
g_skip_func = 0;
g_func[0] = 0;
skip_warned = 0;
g_skip_func = 0;
g_func[0] = 0;