WIP: disas output
authorLukas Krickl <lukas@krickl.dev>
Sat, 24 Feb 2024 11:31:21 +0000 (12:31 +0100)
committerLukas Krickl <lukas@krickl.dev>
Sat, 24 Feb 2024 11:31:21 +0000 (12:31 +0100)
src/ulas.h
src/uldas.c

index 616c9826c1fdd5276ba6e4146feb0c71fcca9eed..c0c01b180e97af1cd3c1845b0d176f61a7798c9b 100644 (file)
@@ -593,6 +593,7 @@ int ulas_asminstr(char *dst, unsigned long max, const char **line,
 int ulas_asmnext(FILE *dst, FILE *src, char *buf, int n);
 int ulas_asm(FILE *dst, FILE *src);
 int ulas_asmline(FILE *dst, FILE *src, const char *line, unsigned long n);
+const char *ulas_asmregstr(unsigned int reg);
 
 // parses and executes a 32 bit signed int math expressions
 int ulas_intexpr(const char **line, unsigned long n, int *rc);
index c98a0f9904de37993376e2277f89637befe0f9cd..4e92ff25fc3997c3faedb36dbd82cb5a0b6c8960 100644 (file)
@@ -1,11 +1,93 @@
 #include "uldas.h"
 
+// this function assumes the bounds checks
+// for buf have already been done and will not check anymore!
+void ulas_dasm_instr_fout(FILE *src, FILE *dst, const struct ulas_instr *instr,
+                          const char *buf, unsigned long read) {
+  if (ulas.pass != ULAS_PASS_FINAL) {
+    return;
+  }
+
+  fprintf(dst, "%s ", instr->name);
+  int bi = 0;
+  for (int i = 0; instr->tokens[i]; i++) {
+    int dat = instr->tokens[i];
+    switch (dat) {
+    case ULAS_E8:
+    case ULAS_A8:
+      printf("%x", buf[bi++]);
+      break;
+    case ULAS_E16:
+    case ULAS_A16:
+      break;
+    default: {
+      const char *reg = ulas_asmregstr(dat);
+      if (reg) {
+      printf("%s", reg);
+      } else {
+      printf("%c", dat);
+      }
+      break;
+    }
+    }
+  }
+
+  fprintf(dst, "\n");
+}
+
+// returns > 1 if instruction was found, and 0 if not
+// the integer returned is the amount of bytes this instruction consumed
+int ulas_dasm_instr_check(FILE *src, FILE *dst, const struct ulas_instr *instr,
+                          const char *buf, unsigned long read) {
+  int i = 0;
+  int bi = 0; // current buffer index
+  // test all instruction's contents
+  for (i = 0; instr->data[i]; i++) {
+    int dat = instr->data[i];
+    if (dat == ULAS_DATZERO) {
+      dat = 0;
+    }
+
+    // do we even have enough data?
+    // this is a general check for 1 byte
+    if (bi >= read) {
+      break;
+    }
+
+    switch (dat) {
+    case ULAS_E8:
+    case ULAS_A8:
+      // just ignore it
+      bi++;
+      break;
+    case ULAS_E16:
+    case ULAS_A16:
+      // need 2 bytes here
+      if (bi + 1 >= read) {
+        goto fail;
+      }
+      bi += 2;
+      break;
+    default:
+      if (buf[bi++] != dat) {
+        goto fail;
+      }
+      break;
+    }
+  }
+
+  ulas_dasm_instr_fout(src, dst, instr, buf, read);
+  return i;
+fail:
+  return 0;
+}
+
 // dasm the next instruction
 // if there are no more bytes to be read, return 0
 // on error return -1
 // otherwise return 1
 int ulas_dasm_next(FILE *src, FILE *dst) {
-  unsigned long srctell = ftell(src);
+  long srctell = ftell(src);
   // read n bytes (as many as in instruction)
   char buf[ULAS_OUTBUFMAX];
   memset(buf, 0, ULAS_OUTBUFMAX);
@@ -26,28 +108,10 @@ int ulas_dasm_next(FILE *src, FILE *dst) {
   for (int i = 0; ulas.arch.instrs[i].name; i++) {
     const struct ulas_instr *instr = &ulas.arch.instrs[i];
 
-    // test all instruction's contents
-    for (int j = 0; instr->data[j]; j++) {
-      int dat = instr->data[j];
-      if (dat == ULAS_DATZERO) {
-        dat = 0;
-      }
-    
-      // do we even have enough data?
-      if (j >= read) {
-        break;
-      }
-
-      switch (dat) {
-      case ULAS_E8:
-      case ULAS_A8:
-        break;
-      case ULAS_E16:
-      case ULAS_A16:
-        break;
-      default:
-        break;
-      }
+    int consumed = ulas_dasm_instr_check(src, dst, instr, buf, read);
+    if (consumed) {
+      fseek(src, srctell + consumed, 0);
+      return 1;
     }
   }