more work on cvt_data, works mostly
[ia32rtools.git] / tools / translate.c
index 3bf8d75..f9ac8a8 100644 (file)
@@ -26,6 +26,8 @@ static FILE *g_fhdr;
        exit(1); \
 } while (0)
 
+#include "masm_tools.h"
+
 enum op_flags {
   OPF_RMD    = (1 << 0), /* removed or optimized out */
   OPF_DATA   = (1 << 1), /* data processing - writes to dst opr */
@@ -281,36 +283,6 @@ static int parse_reg(enum opr_lenmod *reg_lmod, const char *s)
   return -1;
 }
 
-static unsigned long parse_number(const char *number)
-{
-  int len = strlen(number);
-  const char *p = number;
-  char *endp = NULL;
-  unsigned long ret;
-  int neg = 0;
-  int bad;
-
-  if (*p == '-') {
-    neg = 1;
-    p++;
-  }
-  if (len > 1 && *p == '0')
-    p++;
-  if (number[len - 1] == 'h') {
-    ret = strtoul(p, &endp, 16);
-    bad = (*endp != 'h');
-  }
-  else {
-    ret = strtoul(p, &endp, 10);
-    bad = (*endp != 0);
-  }
-  if (bad)
-    aerr("number parsing failed\n");
-  if (neg)
-    ret = -ret;
-  return ret;
-}
-
 static int parse_indmode(char *name, int *regmask, int need_c_cvt)
 {
   enum opr_lenmod lmod;
@@ -678,7 +650,7 @@ static int parse_operand(struct parsed_opr *opr,
   // most likely var in data segment
   opr->type = OPT_LABEL;
 
-  pp = proto_parse(g_fhdr, opr->name);
+  pp = proto_parse(g_fhdr, opr->name, 0);
   if (pp != NULL) {
     if (pp->is_fptr || pp->is_func) {
       opr->lmod = OPLM_DWORD;
@@ -1403,6 +1375,8 @@ static void stack_frame_access(struct parsed_op *po,
       ferr(po, "bp_arg arg%d/w offset %d and type '%s' is too small\n",
         i + 1, offset, g_func_pp->arg[i].type.name);
     }
+    if (popr->is_ptr && popr->lmod != OPLM_DWORD)
+      ferr(po, "bp_arg arg%d: non-dword ptr access\n", i + 1);
   }
   else
   {
@@ -1463,7 +1437,7 @@ static void check_label_read_ref(struct parsed_op *po, const char *name)
 {
   const struct parsed_proto *pp;
 
-  pp = proto_parse(g_fhdr, name);
+  pp = proto_parse(g_fhdr, name, 0);
   if (pp == NULL)
     ferr(po, "proto_parse failed for ref '%s'\n", name);
 
@@ -2202,7 +2176,7 @@ static int scan_for_reg_clear(int i, int reg)
 static int scan_for_esp_adjust(int i, int opcnt, int *adj)
 {
   struct parsed_op *po;
-  int i_first = i;
+  int first_pop = -1;
   *adj = 0;
 
   for (; i < opcnt; i++) {
@@ -2219,10 +2193,16 @@ static int scan_for_esp_adjust(int i, int opcnt, int *adj)
         ferr(&ops[i], "unaligned esp adjust: %x\n", *adj);
       return i;
     }
-    else if (po->op == OP_PUSH)
+    else if (po->op == OP_PUSH) {
+      if (first_pop == -1)
+        first_pop = -2; // none
       *adj -= lmod_bytes(po, po->operand[0].lmod);
-    else if (po->op == OP_POP)
+    }
+    else if (po->op == OP_POP) {
+      if (first_pop == -1)
+        first_pop = i;
       *adj += lmod_bytes(po, po->operand[0].lmod);
+    }
     else if (po->flags & (OPF_JMP|OPF_TAIL)) {
       if (po->op != OP_CALL)
         break;
@@ -2232,12 +2212,12 @@ static int scan_for_esp_adjust(int i, int opcnt, int *adj)
     }
   }
 
-  if (*adj == 4 && ops[i_first].op == OP_POP
-    && ops[i_first].operand[0].type == OPT_REG
-    && ops[i_first].operand[0].reg == xCX)
+  if (*adj == 4 && first_pop >= 0 && ops[first_pop].op == OP_POP
+    && ops[first_pop].operand[0].type == OPT_REG
+    && ops[first_pop].operand[0].reg == xCX)
   {
     // probably 'pop ecx' was used..
-    return i_first;
+    return first_pop;
   }
 
   return -1;
@@ -2308,12 +2288,12 @@ static const struct parsed_proto *try_recover_pp(
 
     pp = g_func_pp->arg[arg].fptr;
     if (pp == NULL)
-      ferr(po, "icall: arg%d is not a fptr?\n", arg + 1);
+      ferr(po, "icall sa: arg%d is not a fptr?\n", arg + 1);
     if (pp->argc_reg != 0)
-      ferr(po, "icall: reg arg in arg-call unhandled yet\n");
+      ferr(po, "icall sa: reg arg in arg-call unhandled yet\n");
   }
   else if (opr->type == OPT_OFFSET || opr->type == OPT_LABEL) {
-    pp = proto_parse(g_fhdr, opr->name);
+    pp = proto_parse(g_fhdr, opr->name, 0);
     if (pp == NULL)
       ferr(po, "proto_parse failed for icall from '%s'\n", opr->name);
     if (pp->argc_reg != 0)
@@ -2339,12 +2319,8 @@ static void scan_for_call_type(int i, struct parsed_opr *opr,
       lr = &g_label_refs[i];
       for (; lr != NULL; lr = lr->next)
         scan_for_call_type(lr->i, opr, magic, pp_found);
-      if (i > 0) {
-        if (LAST_OP(i - 1))
-          return;
-        scan_for_call_type(i - 1, opr, magic, pp_found);
-      }
-      return;
+      if (i > 0 && LAST_OP(i - 1))
+        return;
     }
     i--;
 
@@ -2380,7 +2356,8 @@ static void scan_for_call_type(int i, struct parsed_opr *opr,
       return;
     pp = g_func_pp->arg[i].fptr;
     if (pp == NULL)
-      ferr(po, "icall: arg%d is not a fptr?\n", i + 1);
+      ferr(po, "icall: arg%d (%s) is not a fptr?\n",
+        i + 1, g_func_pp->arg[i].reg);
     if (pp->argc_reg != 0)
       ferr(po, "icall: reg arg in arg-call unhandled yet\n");
   }
@@ -2609,7 +2586,7 @@ 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_func_pp = proto_parse(fhdr, funcn);
+  g_func_pp = proto_parse(fhdr, funcn, 0);
   if (g_func_pp == NULL)
     ferr(ops, "proto_parse failed for '%s'\n", funcn);
 
@@ -2776,7 +2753,9 @@ static void gen_func(FILE *fout, FILE *fhdr, const char *funcn, int opcnt)
     if (po->op == OP_CALL) {
       if (po->operand[0].type == OPT_LABEL) {
         tmpname = opr_name(po, 0);
-        pp_c = proto_parse(fhdr, tmpname);
+        if (IS_START(tmpname, "loc_"))
+          ferr(po, "call to loc_*\n");
+        pp_c = proto_parse(fhdr, tmpname, 0);
         if (pp_c == NULL)
           ferr(po, "proto_parse failed for call '%s'\n", tmpname);
         if (pp_c->is_fptr && pp_c->argc_reg != 0)