more 32bit fixes
[ia32rtools.git] / tools / translate.c
index f85d5be..324bc26 100644 (file)
@@ -4,12 +4,22 @@
  *
  * This work is licensed under the terms of 3-clause BSD license.
  * See COPYING file in the top-level directory.
+ *
+ * recognized asm hint comments:
+ * sctattr - function attributes (see code)
+ * sctend  - force end of function/chunk
+ * sctpatch: <p> - replace current asm line with <p>
+ * sctproto: <p> - prototype of ref'd function or struct
+ * sctref  - variable is referenced, make global
+ * sctskip_start - start of skipped code chunk (inclusive)
+ * sctskip_end   - end of skipped code chunk (inclusive)
  */
 
 #define _GNU_SOURCE
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <errno.h>
 
 #include "my_assert.h"
 #include "my_str.h"
@@ -482,7 +492,7 @@ static int parse_indmode(char *name, int *regmask, int need_c_cvt)
     }
 
     if ('0' <= w[0] && w[0] <= '9') {
-      number = parse_number(w);
+      number = parse_number(w, 0);
       printf_number(d, sizeof(cvtbuf) - (d - cvtbuf), number);
       continue;
     }
@@ -578,8 +588,9 @@ static const char *parse_stack_el(const char *name, char *extra_reg,
     if (len < sizeof(buf) - 1) {
       strncpy(buf, s, len);
       buf[len] = 0;
+      errno = 0;
       val = strtol(buf, &endp, 16);
-      if (val == 0 || *endp != 0) {
+      if (val == 0 || *endp != 0 || errno != 0) {
         aerr("%s num parse fail for '%s'\n", __func__, buf);
         return NULL;
       }
@@ -865,7 +876,7 @@ static int parse_operand(struct parsed_opr *opr,
   else if (('0' <= words[w][0] && words[w][0] <= '9')
     || words[w][0] == '-')
   {
-    number = parse_number(words[w]);
+    number = parse_number(words[w], 0);
     opr->type = OPT_CONST;
     opr->val = number;
     printf_number(opr->name, sizeof(opr->name), number);
@@ -1741,8 +1752,9 @@ static struct parsed_equ *equ_find(struct parsed_op *po, const char *name,
     if (namelen <= 0)
       ferr(po, "equ parse failed for '%s'\n", name);
 
+    errno = 0;
     *extra_offs = strtol(p, &endp, 16);
-    if (*endp != 0)
+    if (*endp != 0 || errno != 0)
       ferr(po, "equ parse failed for '%s'\n", name);
   }
 
@@ -1786,10 +1798,11 @@ static void parse_stack_access(struct parsed_op *po,
     p = name + 4;
     if (IS_START(p, "0x"))
       p += 2;
+    errno = 0;
     offset = strtoul(p, &endp, 16);
     if (name[3] == '-')
       offset = -offset;
-    if (*endp != 0)
+    if (*endp != 0 || errno != 0)
       ferr(po, "ebp- parse of '%s' failed\n", name);
   }
   else {
@@ -1834,8 +1847,9 @@ static int parse_stack_esp_offset(struct parsed_op *po,
     // just plain offset?
     if (!IS_START(name, "esp+"))
       return -1;
+    errno = 0;
     offset = strtol(name + 4, &endp, 0);
-    if (endp == NULL || *endp != 0)
+    if (endp == NULL || *endp != 0 || errno != 0)
       return -1;
     *offset_out = offset;
     return 0;
@@ -2574,10 +2588,10 @@ static int scan_for_pop(int i, int opcnt, int magic, int reg,
         if (po->pp != NULL && po->pp->is_noreturn)
           seen_noreturn = 1;
         else
-          return -1;
+          goto out;
       }
       else
-        return -1; // deadend
+        goto out;
     }
 
     if (po->flags & (OPF_RMD|OPF_DONE|OPF_FARG))
@@ -2628,6 +2642,7 @@ static int scan_for_pop(int i, int opcnt, int magic, int reg,
     }
   }
 
+out:
   // for noreturn, assume msvc skipped stack cleanup
   return seen_noreturn ? 1 : -1;
 }
@@ -6695,10 +6710,11 @@ static void gen_func(FILE *fout, FILE *fhdr, const char *funcn, int opcnt)
           lmod_cast_s(po, po->operand[0].lmod), buf2);
         last_arith_dst = &po->operand[0];
         delayed_flag_op = NULL;
-        if (pfomask & (1 << PFO_C)) {
+        if (pfomask & PFOB_C) {
           fprintf(fout, "\n  cond_c = (%s != 0);", buf1);
-          pfomask &= ~(1 << PFO_C);
+          pfomask &= ~PFOB_C;
         }
+        output_std_flags(fout, po, &pfomask, buf1);
         break;
 
       case OP_IMUL:
@@ -6946,7 +6962,7 @@ static void gen_func(FILE *fout, FILE *fhdr, const char *funcn, int opcnt)
               if (pp->arg[arg].type.is_retreg)
                 fprintf(fout, "&%s", pp->arg[arg].reg);
               else if (IS(pp->arg[arg].reg, "ebp")
-                    && !(po->flags & OPF_EBP_S))
+                    && g_bp_frame && !(po->flags & OPF_EBP_S))
               {
                 // rare special case
                 fprintf(fout, "%s(u32)&sf.b[sizeof(sf)]", cast);
@@ -7738,8 +7754,11 @@ static void gen_hdr_dep_pass(int i, int opcnt, unsigned char *cbits,
       po->regmask_dst |= 1 << xAX;
 
       dep = hg_fp_find_dep(fp, po->operand[0].name);
-      if (dep != NULL)
+      if (dep != NULL) {
         dep->regmask_live = regmask_save | regmask_dst;
+        if (g_bp_frame && !(po->flags & OPF_EBP_S))
+          dep->regmask_live |= 1 << xBP;
+      }
     }
     else if (po->op == OP_RET) {
       if (po->operand_cnt > 0) {
@@ -7958,7 +7977,7 @@ static void gen_hdr(const char *funcn, int opcnt)
       // noreturn OS functions
       break;
     }
-    if (ops[i].op != OP_NOP)
+    if (ops[i].op != OP_NOP && ops[i].op != OPP_ABORT)
       ferr(&ops[i], "unreachable code\n");
   }
 
@@ -8286,10 +8305,14 @@ static int ida_xrefs_show_need(FILE *fasm, char *p,
   long pos;
 
   p = strrchr(p, ';');
-  if (p != NULL && *p == ';' && IS_START(p + 2, "DATA XREF: ")) {
-    p += 13;
-    if (is_xref_needed(p, rlist, rlist_len))
+  if (p != NULL && *p == ';') {
+    if (IS_START(p + 2, "sctref"))
       return 1;
+    if (IS_START(p + 2, "DATA XREF: ")) {
+      p += 13;
+      if (is_xref_needed(p, rlist, rlist_len))
+        return 1;
+    }
   }
 
   pos = ftell(fasm);
@@ -8308,6 +8331,12 @@ static int ida_xrefs_show_need(FILE *fasm, char *p,
 
     p = strrchr(p, ';');
     p += 2;
+
+    if (IS_START(p, "sctref")) {
+      found_need = 1;
+      break;
+    }
+
     // it's printed once, but no harm to check again
     if (IS_START(p, "DATA XREF: "))
       p += 11;
@@ -8501,7 +8530,7 @@ static int cmp_chunks(const void *p1, const void *p2)
   return strcmp(c1->name, c2->name);
 }
 
-static void scan_ahead(FILE *fasm)
+static void scan_ahead_for_chunks(FILE *fasm)
 {
   char words[2][256];
   char line[256];
@@ -8842,7 +8871,7 @@ int main(int argc, char *argv[])
           if (addr > f_addr && !scanned_ahead) {
             //anote("scan_ahead caused by '%s', addr %lx\n",
             //  g_func, addr);
-            scan_ahead(fasm);
+            scan_ahead_for_chunks(fasm);
             scanned_ahead = 1;
             func_chunks_sorted = 0;
           }
@@ -8967,7 +8996,7 @@ do_pending_endp:
           if (pd->type == OPT_OFFSET)
             pd->d[pd->count].u.label = strdup(words[i]);
           else
-            pd->d[pd->count].u.val = parse_number(words[i]);
+            pd->d[pd->count].u.val = parse_number(words[i], 0);
           pd->d[pd->count].bt_i = -1;
           pd->count++;
         }
@@ -9146,7 +9175,7 @@ do_pending_endp:
       else
         aerr("bad lmod: '%s'\n", words[2]);
 
-      g_eqs[g_eqcnt].offset = parse_number(words[4]);
+      g_eqs[g_eqcnt].offset = parse_number(words[4], 0);
       g_eqcnt++;
       continue;
     }