6809 Fix syscall glue for variadic functions
authorTormod Volden <debian.tormod@gmail.com>
Thu, 16 Apr 2015 22:00:19 +0000 (00:00 +0200)
committerAlan Cox <alan@linux.intel.com>
Sat, 18 Apr 2015 20:59:21 +0000 (21:59 +0100)
gcc6809 uses a fastcall calling convention with the first argument
in X, the second and up on the stack. However, variadic functions
get all the arguments on the stack. We therefore mangle the stack
for these functions so that they appear as fastcall to the kernel.

Signed-off-by: Tormod Volden <debian.tormod@gmail.com>
Library/libs/fuzix6809/syscall6809.s
Library/tools/syscall_6809.c

index a8c906d..0f284d3 100644 (file)
@@ -1,4 +1,5 @@
        .globl __syscall
+       .globl __syscall_mangled
        .globl _errno
 
        .area .text
@@ -10,3 +11,14 @@ __syscall:
 error:
        std     _errno          ; X is -1
        rts
+
+; for variadic functions:
+; compensate for the 1st argument that we removed
+__syscall_mangled:
+       swi
+       beq     noerr
+       std     _errno
+noerr:
+       puls d          ; get return address
+       pshs d,x        ; inject a word on stack
+       rts
index f310978..cd4d93a 100644 (file)
@@ -18,11 +18,23 @@ static void write_call(int n)
     perror(namebuf);
     exit(1);
   }
-  fprintf(fp, "\t.area .text\n\n");
-  fprintf(fp, "\t.globl __syscall\n");
-  fprintf(fp, "\t.globl _%s\n\n", syscall_name[n]);
-  fprintf(fp, "_%s:\n\tldd #%d\n", syscall_name[n], n);
-  fprintf(fp, "\tjmp __syscall\n");
+  fprintf(fp, "\t.area .text\n\n"
+             "\t.globl __syscall\n"
+             "\t.globl __syscall_mangled\n"
+             "\t.globl _%1$s\n\n"
+             "_%1$s:\n", syscall_name[n]);
+  if (syscall_args[n] == VARARGS) {
+       /* Mangle into fastcall like the others: */
+       /* get return address and X (first argument) */
+       /* then put return address back */
+       fprintf(fp, "\tpuls d,x\n"
+                   "\tpshs d\n"
+                   "\tldd #%d\n"
+                   "\tjmp __syscall_mangled\n", n);
+  } else {
+       fprintf(fp, "\tldd #%d\n"
+                   "\tjmp __syscall\n", n);
+  }
   fclose(fp);
 }