Improve syscall implementation, in /mips-tetris improve helloworld.s and read.s
authorNick Downing <nick@ndcode.org>
Mon, 2 Jan 2023 23:45:46 +0000 (10:45 +1100)
committerNick Downing <nick@ndcode.org>
Tue, 3 Jan 2023 03:58:22 +0000 (14:58 +1100)
emu_mips.c
mips-tetris

index bee58cf..ff55124 100644 (file)
@@ -228,6 +228,62 @@ void write_word(void *context, int addr, int data) {
   mem.w[(addr ^ MEM_SIZE_M4) >> 2] = data;
 }
 
+void _syscall(uint32_t *v0, uint32_t *a0, uint32_t *a1) {
+  switch (*v0) {
+  case 1: /* print int */
+    printf("%d", *a0);
+    break;
+  case 4: /* print string */
+    for (int p = *a0, c; (c = mem.b[p ^ MEM_SIZE_M1]) != 0; ++p)
+      putchar(c);
+    break;
+  case 5: /* read int */
+    {
+      fflush(stdout);
+
+      char buf[0x100];
+      if (fgets(buf, 0x100, stdin) == NULL) {
+        perror("fgets()");
+        exit(EXIT_FAILURE);
+      }
+      *v0 = atoi(buf);
+    }
+    break;
+  case 8: /* read string */
+    {
+      fflush(stdout);
+
+      char *buf = malloc(*a1);
+      if (buf == NULL) {
+        perror("malloc()");
+        exit(EXIT_FAILURE);
+      }
+      if (fgets(buf, *a1, stdin) == NULL) {
+        perror("fgets()");
+        exit(EXIT_FAILURE);
+      }
+      char *p = buf;
+      int q = *a0;
+      while ((mem.b[q++ ^ MEM_SIZE_M1] = *p++) != 0)
+        ;
+      free(buf);
+    }
+    break;
+  case 10: /* end program */
+    exit(EXIT_SUCCESS);
+  case 11: /* print char */
+    putchar(*a0);
+    break;
+  case 12: /* read char */
+    fflush(stdout);
+    *a0 = getchar();
+    break;
+  default:
+    fprintf(stderr, "unimplemented syscall %d\n", *v0);
+    exit(EXIT_FAILURE);
+  }
+}
+
 #if ALT_BACKEND
 int simulator_bigendian = 1;
 
@@ -344,35 +400,11 @@ int main(int argc, char **argv) {
 
     cpu_update(cpu);
     if (cpu->exception_pending == Syscall) {
-      switch (cpu->registers[R2]) {
-      case 1: /* print char */
-        fputc(cpu->registers[R4], stdout);
-        break;
-      case 4: /* print string */
-        {
-          int c;
-          for (int p = cpu->registers[R4]; (c = read_byte(NULL, p)) != 0; ++p)
-            fputc(c, stdout);
-        }
-        break;
-      case 5: /* integer input */
-        {
-          fflush(stdout);
-
-          char buf[0x100];
-          if (fgets(buf, 0x100, stdin) == NULL) {
-            perror("fgets()");
-            exit(EXIT_FAILURE);
-          }
-          cpu->registers[R10] = atoi(buf);
-        }
-        break;
-      case 10: /* end program */
-        exit(EXIT_SUCCESS);
-      default:
-        fprintf(stderr, "unimplemented syscall %d\n", cpu->registers[R2]);
-        exit(EXIT_FAILURE);
-      }
+      _syscall(
+        cpu->registers + R2, // v0
+        cpu->registers + R4, // a0
+        cpu->registers + R5 // a1
+      );
       cpu->exception_pending = NoException;
       cpu->registers[PC] = cpu->next_pc;
       cpu->next_pc += 4;
index 821a1a9..2a73cf6 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 821a1a9d35ad299aca70d3778a7ea3162034a5c4
+Subproject commit 2a73cf60a2bb1c3d0b437adbded9a8f0a2c141ba