# Copyright (C) 1995,1996 Robert de Bath <rdebath@cix.compulink.co.uk>
# This file is part of the Linux-8086 C library and is distributed
# under the GNU Library General Public License.
#
# This script generates the 'simple' system calls.
#
# Each call is put into it's own object file, if the semantics of the
# call are not correct UNIX then the 4th field in the dat file has a
# marker and the function is generated with a __ prefix.
#
#
# Different levels of squeeze
#   0 = each is complete
#   1 = Short codes calling common function

COMPACT=1

rm -f syscall.c syscall.mak call_tab.v defn_tab.v syscall.dat

if [ -r ${ELKSSRC}/arch/i86/kernel/syscall.dat \
 -a ! -r ${TOPDIR}/libc/kinclude/Used ]

then echo Using syscalls from ${ELKSSRC}
     cp -p ${ELKSSRC}/arch/i86/kernel/syscall.dat syscall.dat
else echo Using syscalls from syscall.dev86
     cp -p syscall.dev86 syscall.dat
fi

tr '[A-Z]' '[a-z]' < syscall.dat | \
awk -v COMPACT=$COMPACT 'BEGIN{
   print "# Copyright (C) 1995,1996 Robert de Bath <rdebath@cix.compulink.co.uk>" > "syscall.mak";
   print "# This file is part of the Linux-8086 C library and is distributed" > "syscall.mak";
   print "# under the GNU Library General Public License." > "syscall.mak";
   print "# " > "syscall.mak";
   print "# This file is automatically generated\n" > "syscall.mak"

   print "/* Copyright (C) 1995,1996 Robert de Bath <rdebath@cix.compulink.co.uk>";
   print " * This file is part of the Linux-8086 C library and is distributed";
   print " * under the GNU Library General Public License.";
   print " * ";
   print " * This file is automatically generated */\n"
   obj="OBJ=";

   print "/* Standard start */\n\n"
   printf("#ifndef __MSDOS__\n");
   printf("#ifdef __AS386_16__\n");
   printf("#asm\n");
   printf("  .text\n");
   printf("  .even\n");
   printf("#endasm\n\n");

   {
      obj=obj "__syscall.o __syscall4.o ";
      print "/* Shared system call code */\n"
      printf("#ifdef L___syscall\n", funcname);
      printf("#asm\n");
      printf("#if __FIRST_ARG_IN_AX__\n");

      printf("export sys_call3\nsys_call3:\n");
      printf("  mov   bx,sp\n");
      printf("  mov   cx,[bx+2]\n");
      printf("  mov   bx,[bx+4]\n");
      # ax=arg1 bx=arg3 cx=arg2 dx=arg0
      printf("  xchg  ax,bx\n");
      # ax=arg3 bx=arg1 cx=arg2 dx=arg0
      printf("  xchg  ax,dx\n");
      # ax=arg0 bx=arg1 cx=arg2 dx=arg3
      printf("  jmp   sys_call0\n\n");

      printf("export sys_call2\nsys_call2:\n");
      printf("  mov   bx,sp\n");
      printf("  mov   cx,[bx+2]\n");
      printf("  mov   bx,ax\n");
      printf("  mov   ax,dx\n");
      printf("  jmp   sys_call0\n\n");

      printf("export sys_call1\nsys_call1:\n");
      printf("  mov   bx,ax\n");
      printf("  mov   ax,dx\n");
      printf("#else\n");
      printf("export sys_call3\nsys_call3:\n");
      printf("  mov   bx,sp\n");
      printf("  mov   dx,[bx+6]\n");
      printf("  mov   cx,[bx+4]\n");
      printf("  mov   bx,[bx+2]\n");
      printf("  jmp   sys_call0\n\n");

      printf("export sys_call2\nsys_call2:\n");
      printf("  mov   bx,sp\n");
      printf("  mov   cx,[bx+4]\n");
      printf("  mov   bx,[bx+2]\n");
      printf("  jmp   sys_call0\n\n");

      printf("export sys_call1\nsys_call1:\n");
      printf("  mov   bx,sp\n");
      printf("  mov   bx,[bx+2]\n");
      printf("#endif\n\n");

      printf("export sys_call0\nsys_call0:\n");
      printf("  int   $80\n");
      printf("  test  ax,ax\n");
      printf("  jge  syscall_ok\n");
      printf("  neg   ax\n");
      printf("  mov   [_errno],ax\n");
      printf("  mov   ax,#-1\n");
      printf("syscall_ok:\n");
      printf("  ret\n");
      printf("#endasm\n");
      printf("#endif\n\n");

      print "/* Shared system call code, syscalls with 4/5 args */\n"
      printf("#ifdef L___syscall4\n", funcname);
      printf("#asm\n");
      printf("#if __FIRST_ARG_IN_AX__\n");

      printf("export sys_call4\nsys_call4:\n");
      printf("export sys_call5\nsys_call5:\n");
      printf("  mov   bx,sp\n");
      printf("  push  si\n");
      printf("  mov   si,[bx+8]\n");
      printf("  push  di\n");
      printf("  mov   di,[bx+6]\n");
      printf("  mov   cx,[bx+2]\n");
      printf("  mov   bx,[bx+4]\n");
      # ax=arg1 bx=arg3 cx=arg2 dx=arg0
      printf("  xchg  ax,bx\n");
      # ax=arg3 bx=arg1 cx=arg2 dx=arg0
      printf("  xchg  ax,dx\n");
      # ax=arg0 bx=arg1 cx=arg2 dx=arg3
      printf("#else\n");
      printf("export sys_call4\nsys_call4:\n");
      printf("export sys_call5\nsys_call5:\n");
      printf("  mov   bx,sp\n");
      printf("  push  si\n");
      printf("  mov   si,[bx+10]\n");
      printf("  push  di\n");
      printf("  mov   di,[bx+8]\n");
      printf("  mov   dx,[bx+6]\n");
      printf("  mov   cx,[bx+4]\n");
      printf("  mov   bx,[bx+2]\n");
      printf("#endif\n\n");

      printf("  int   $80\n");
      printf("  pop   di\n");
      printf("  pop   si\n");
      printf("  test  ax,ax\n");
      printf("  jge  syscall_ok\n");
      printf("  neg   ax\n");
      printf("  mov   [_errno],ax\n");
      printf("  mov   ax,#-1\n");
      printf("syscall_ok:\n");
      printf("  ret\n");
      printf("#endasm\n");
      printf("#endif\n\n");
   }
}
/^[	 ]*#/ { next; }
/^[	 ]*$/ { next; }
{
   callno = 0+$2;
   if( !(callno in calltab) )
      callwas[callno] = " /* " $1 " */";

   if( $3 == "x" || $3 == "" ) next;
   else if( $4 == "@" || $4 == "-" ) next;
   else if( $4 == "*" )        funcname="__" $1;
   else                        funcname=$1;

   if( callno > max_call ) max_call = callno;

   calltab[callno] = $1;

   if( length(obj) > 60 )
   {
      printf("%s\t\\\n", obj) > "syscall.mak";
      obj="    ";
   }
   obj=obj funcname ".o ";

   printf "/* CALL %s */\n\n", $0;

   printf("#ifdef L_%s\n", funcname);
   printf("#asm\n", funcname);
   printf("export _%s\n", funcname);
   printf("_%s:\n", funcname);

   # Inline assembler max to 5 args (10 bytes)
   if( $3 != 4 && $3 != 5 && ( COMPACT || $3 > 5 ))
   {
      if( $3 == 0 )
      {
         printf("  mov   ax,#%d\n", callno);
      }
      else
      {
         printf("#if __FIRST_ARG_IN_AX__\n");
         printf("  mov   dx,#%d\n", callno);
         printf("#else\n");
         printf("  mov   ax,#%d\n", callno);
         printf("#endif\n");
      }
      printf("  br    sys_call%d\n", $3);
   }
   else
   {
      if( $3 >= 1 )
         printf("#if __FIRST_ARG_IN_AX__\n");
      if( $3 >= 2 )
         printf("  mov   bx,sp\n");
      if( $3 >= 5 )
         printf("  push  si\n");
      if( $3 >= 5 )
         printf("  mov   si,[bx+8]\n");
      if( $3 >= 4 )
         printf("  push  di\n");
      if( $3 >= 4 )
         printf("  mov   di,[bx+6]\n");
      if( $3 >= 3 )
         printf("  mov   dx,[bx+4]\n");
      if( $3 >= 2 )
         printf("  mov   cx,[bx+2]\n");
      if( $3 >= 1 )
         printf("  mov   bx,ax\n");
      if( $3 >= 1 )
         printf("#else\n");
      if( $3 >= 1 )
         printf("  mov   bx,sp\n");
      if( $3 >= 5 )
         printf("  push  si\n");
      if( $3 >= 5 )
         printf("  mov   si,[bx+10]\n");
      if( $3 >= 4 )
         printf("  push  di\n");
      if( $3 >= 4 )
         printf("  mov   di,[bx+8]\n");
      if( $3 >= 3 )
         printf("  mov   dx,[bx+6]\n");
      if( $3 >= 2 )
         printf("  mov   cx,[bx+4]\n");
      if( $3 >= 1 )
         printf("  mov   bx,[bx+2]\n");
      if( $3 >= 1 )
         printf("#endif\n");

         printf("  mov   ax,#%d\n", callno);

         printf("  int   $80\n");

      if( $3 >= 4 )
         printf("  pop   di\n");
      if( $3 >= 5 )
         printf("  pop   si\n");

	 printf("  test  ax,ax\n");
	 printf("  jl   syscall_err\n");
	 printf("  ret\n");
	 printf("syscall_err:\n");
         printf("  neg   ax\n");
         printf("  mov   [_errno],ax\n");
         printf("  mov   ax,#-1\n");
         printf("  ret\n");
   }
   printf("#endasm\n");
   printf("#endif\n\n");
}
END{

   for(i=0; i<=max_call; i++)
      if( i in calltab )
      {
	 printf("#ifndef sys_%s\n", calltab[i]) > "defn_tab.v";
	 printf("#define sys_%s sys_enosys\n", calltab[i]) > "defn_tab.v";
	 printf("#endif\n\n") > "defn_tab.v";
      }

   for(i=0; i<=max_call; i++)
      if( i in calltab )
	 printf("/* %3d */  sys_%s,\n", i, calltab[i]) > "call_tab.v";
      else
	 printf("/* %3d */  sys_enosys,%s\n", i, callwas[i]) > "call_tab.v";
   
   printf("#endif /* __AS386_16__ */\n\n");
   printf("#endif /* __MSDOS__ */\n\n");
   printf("%s\n", obj) > "syscall.mak";
   printf "\n" > "syscall.mak";

}'  > syscall.c

cat >> syscall.mak <<\!

all: $(LIBC)($(OBJ))
	@$(RM) $(OBJ)

$(LIBC)($(OBJ)): syscall.dat
	$(CC) $(CFLAGS) -DL_$* syscall.c -c -o $*.o
	$(AR) $(ARFLAGS) $@ $*.o
!

exit $?
