From e02753a50275ac94a7fbda6dfbcbc84bc44adb6e Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Wed, 19 Oct 2016 20:59:20 +0100 Subject: [PATCH] 68000: make fork a special case 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 | 3 +++ Library/tools/syscall_68000.c | 25 +++++++++++++++++++++---- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/Library/libs/fuzix68000/syscall__fork.S b/Library/libs/fuzix68000/syscall__fork.S index e39e9c55..84135163 100644 --- a/Library/libs/fuzix68000/syscall__fork.S +++ b/Library/libs/fuzix68000/syscall__fork.S @@ -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 diff --git a/Library/tools/syscall_68000.c b/Library/tools/syscall_68000.c index f817d313..b6ff5b9f 100644 --- a/Library/tools/syscall_68000.c +++ b/Library/tools/syscall_68000.c @@ -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); } -- 2.34.1