68000: make fork a special case
authorAlan Cox <alan@linux.intel.com>
Wed, 19 Oct 2016 19:59:20 +0000 (20:59 +0100)
committerAlan Cox <alan@linux.intel.com>
Wed, 19 Oct 2016 19:59:20 +0000 (20:59 +0100)
By defining _fork() as trashing all registers we can implement multiple udata
pointer based 68K platforms without having to save the CPU registers on syscall
entry. Instead the child does a direct supervisor a7 fixup and rte to user space
with d0/d1 correct. The rest is handled by the wrapper.

Now this isn't perfect and we probably need to adjust the rules a bit if
anyone is doing clever register resident relative code because if you take a
signal handler just at the wrong moment.

I guess as we have to save A5, you'll have to use A5 8) for Amiga style
resident code if we ever get that far.

Library/libs/fuzix68000/syscall__fork.S
Library/tools/syscall_68000.c

index e39e9c5..8413516 100644 (file)
@@ -4,11 +4,14 @@
 
 _fork:
 .mri 1
+       movem.l d2-d7/a2-a6,-(sp)
        move.w #32,d0
        trap #14
        ext.l d1
        bne _error
+       movem.l (sp)+,d2-d7/a2-a6
        rts
 _error:
        move.l d1,errno
+       movem.l (sp)+,d2-d7/a2-a6
        rts
index f817d31..b6ff5b9 100644 (file)
@@ -12,16 +12,28 @@ static char namebuf[128];
 static void write_call(int n)
 {
   FILE *fp;
+  int saves = 0;
   snprintf(namebuf, 128, "fuzix68000/syscall_%s.S", syscall_name[n]);
   fp = fopen(namebuf, "w");
   if (fp == NULL) {
     perror(namebuf);
     exit(1);
   }
+  /*
+   *   We define _fork() as trashing all the registers except the return
+   *   values and a7. This little userspace ick here allows us to avoid saving
+   *   all the registers on syscall entry just in case we are doing a fork and
+   *   have multiple udata blocks.
+   */
+  if (strcmp(syscall_name[n], "_fork") == 0)
+    saves = 1;
+
   fprintf(fp, "\t.text\n\n"
              "\t.globl %1$s\n\n"
              "%1$s:\n", syscall_name[n]);
   fprintf(fp, ".mri 1\n");
+  if (saves)
+    fprintf(fp, "\tmovem.l d2-d7/a2-a6,-(sp)\n");
   fprintf(fp, "\tmove.w #%d,d0\n"
              "\ttrap #14\n", n);
   /* ext is the same speed as tst so we might as well do the ext in case
@@ -29,11 +41,16 @@ static void write_call(int n)
      shorts in kernel for such things and speed the standard says errno
      is integer */
   fprintf(fp, "\text.l d1\n"
-              "\tbne _error\n"
-              "\trts\n"
+              "\tbne _error\n");
+  if (saves)
+    fprintf(fp, "\tmovem.l (sp)+,d2-d7/a2-a6\n");
+
+  fprintf(fp, "\trts\n"
               "_error:\n"
-              "\tmove.l d1,errno\n"
-              "\trts\n");
+              "\tmove.l d1,errno\n");
+  if (saves)
+    fprintf(fp, "\tmovem.l (sp)+,d2-d7/a2-a6\n");
+  fprintf(fp, "\trts\n");
   fclose(fp);
 }