z88dk: Add first pieces to bootstrap Z88DK for Fuzix
authorAlan Cox <alan@linux.intel.com>
Fri, 26 Dec 2014 21:40:55 +0000 (21:40 +0000)
committerAlan Cox <alan@linux.intel.com>
Fri, 26 Dec 2014 21:40:55 +0000 (21:40 +0000)
Library/Makefile
Library/tools/syscall-z88dk.c [new file with mode: 0644]

index 8ad77ae..75ca334 100644 (file)
@@ -5,5 +5,6 @@ CFLAGS += -I../Kernel/include
 all: tools/syscall tools/binman
 
 tools/syscall: tools/syscall.c ../Kernel/include/syscall_name.h
+tools/syscall-z88dk: tools/syscall-z88dk.c ../Kernel/include/syscall_name.h
 
 tools/binman: tools/binman.c
diff --git a/Library/tools/syscall-z88dk.c b/Library/tools/syscall-z88dk.c
new file mode 100644 (file)
index 0000000..9a26675
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ *     Generate the syscall functions for Z88DK
+ *
+ *     Z88DK has some "interesting" properties. It's SmallC derived
+ *     so pushes the arguments backwards which we must cope with. It also
+ *     has a nifty 'fastcall' HL single argument passing ABI that you can
+ *     use (SDCC take notes please).
+ *
+ *     We turn 2/3/4 argument syscalls into stack shuffles (in and out) and
+ *     single argument into fastcall.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "syscall_name.h"
+
+static char namebuf[128];
+
+static void write_call(int n)
+{
+  FILE *fp;
+  snprintf(namebuf, 128, "z88dk/%s.asm", syscall_name[n]);
+  fp = fopen(namebuf, "w");
+  if (fp == NULL) {
+    perror(namebuf);
+    exit(1);
+  }
+  fprintf(fp, "\tLIB syscall\n");
+  fprintf(fp, "\tXLIB %s\n\n", syscall_name[n]);
+  fprintf(fp, ".%s\n", syscall_name[n]);
+
+  switch(syscall_args[n]) {
+    case 0:  
+      fprintf(fp, "\tld hl, %d\n", n);
+      fprintf(fp, "\tjp syscall\n");
+    case 1:
+      fprintf(fp, "\tpush hl\n");
+      fprintf(fp, "\tld hl, %d\n", n);
+      fprintf(fp, "\tcall syscall\n");
+      fprintf(fp, "\tpop af\n");
+      fprintf(fp, "\tret\n");
+      break;
+    case 2:
+      fprintf(fp, "\tpop de\n\tpop bc\n\tpush de\n\tpush bc\n");
+      fprintf(fp, "\tld hl, %d\n", n);
+      fprintf(fp, "\tcall syscall\n");
+      fprintf(fp, "\tpop de\n\tpop bc\n\tpush de\n\tpush bc\n");
+      fprintf(fp, "\tret\n");
+      break;
+    case 3:
+      fprintf(fp, "\tpop de\n\tpop bc\n\tpop hl\n\tpush de\n\tpush bc\n\tpush hl\n");
+      fprintf(fp, "\tld hl, %d\n", n);
+      fprintf(fp, "\tcall syscall\n");
+      fprintf(fp, "\tpop de\n\tpop bc\n\tpop ix\n\tpush de\n\tpush bc\n\tpush ix\n");
+      fprintf(fp, "\tret\n");
+      break;
+    case 4:
+      fprintf(fp, "\tpop de\n\tpop bc\n\tpop hl\n\tpop ix\n\tpush de\n\tpush bc\n\tpush hl\n\tpush ix\n");
+      fprintf(fp, "\tld hl, %d\n", n);
+      fprintf(fp, "\tcall syscall\n");
+      fprintf(fp, "\tpop de\n\tpop bc\n\tpop ix\n\tpop iy\n\tpush de\n\tpush bc\n\tpush ix\n\tpush iy\n");
+      fprintf(fp, "\tret\n");
+      break;
+  }
+  fclose(fp);
+}
+
+static void write_header(FILE *fp, int n)
+{
+  fprintf(fp, "extern int __LIB__ ");
+  if (syscall_args[n] == 1)
+    fprintf(fp, "__FASTCALL__ ");
+  fprintf(fp, "%s(", syscall_name[n]);
+  if (syscall_args[n] == 0)
+    fprintf(fp, "void);\n");
+  if (syscall_args[n] == 1)
+    fprintf(fp, "unsigned int);\n");
+  if (syscall_args[n] == 2)
+    fprintf(fp, "char *, unsigned int);\n");
+  if (syscall_args[n] == 3)
+    fprintf(fp, "unsigned int, void *, unsigned int);\n");
+  if (syscall_args[n] == 4)
+    fprintf(fp, "unsigned int, unsigned int, unsigned int, unsigned int);\n");
+}
+
+
+static void write_call_table(void)
+{
+  int i;
+  for (i = 0; i < NR_SYSCALL; i++)
+    write_call(i);
+}
+
+static void write_proto_header(void)
+{
+  int i;
+  FILE *fp = fopen("z88dk/header.proto", "w");
+  if (fp == NULL) {
+    perror("z88dk/header.proto");
+    exit(1);
+  }
+  for (i = 0; i < NR_SYSCALL; i++)
+    write_header(fp, i);
+  fclose(fp);
+}
+
+int main(int argc, char *argv[])
+{
+  write_proto_header();
+  write_call_table();
+  exit(0);
+}