# Copyright (C) 1995-1997 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 for the 386
#
# 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

rm -f syscall.c syscall.mak

tr '[A-Z]' '[a-z]' < syscall.dat | \
awk 'BEGIN{
   print "# Copyright (C) 1995-1997 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-1997 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_32__\n");
   printf("  .text\n");
   printf("  .align 16\n");

   COMPACT=0;
}
/^[	 ]*#/ { next; }
/^[	 ]*$/ { next; }
{
   if( $2 > max_call ) max_call = $2;

   if( $3 == "x" || $3 == "" ) next;
   else if( $4 == "-" )        next;
   else if( $4 == "*" )        funcname="__" $1;
   else                        funcname=$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(".globl %s\n", funcname);
   printf(".type %s,@function\n", funcname);
   printf("%s:\n", funcname);

   # Inline assembler max to 5 args (20 bytes)
   if( $3 != 4 && $3 != 5 && ( COMPACT || $3 > 5 ))
   {
      printf("  mov   %%eax,#%d\n", $2);
      printf("  br    sys_call%d\n", $3);
   }
   else
   {
                    printf("  pushl %%ebp\n");
                    printf("  movl  %%esp,%%ebp\n");
                    printf("  pushl %%ebx\n");
      if( $3 >= 1 ) printf("  mov   8(%%ebp),%%ebx\n");
      if( $3 >= 2 ) printf("  mov   12(%%ebp),%%ecx\n");
      if( $3 >= 3 ) printf("  mov   16(%%ebp),%%edx\n");
      if( $3 >= 4 ) printf("  push  %%esi\n");
      if( $3 >= 4 ) printf("  mov   20(%%ebp),%%esi\n");
      if( $3 >= 5 ) printf("  push  %%edi\n");
      if( $3 >= 5 ) printf("  mov   24(%%ebp),%%edi\n");
                    printf("  mov   $%d,%%eax\n", $2);
                    printf("  int   $0x80\n");

      if( $3 >= 5 ) printf("  pop   %%edi\n");
      if( $3 >= 4 ) printf("  pop   %%esi\n");
                    printf("  pop   %%ebx\n");

	            printf("  test  %%eax,%%eax\n");
	            printf("  jge   syscall_ok\n");
                    printf("  neg   %%eax\n");
                    printf("  mov   %%eax,errno\n");
                    printf("  mov   $-1,%%eax\n");
                    printf("syscall_ok:\n");
                    printf("  movl  %%ebp,%%esp\n");
                    printf("  popl  %%ebp\n");
                    printf("  ret\n");
   }
   printf(".endif\n\n");
}
END{

   printf("#endif /* __AS386_32__ */\n\n");
   printf("#endif /* __MSDOS__ */\n\n");
   printf("%s\n", obj) > "syscall.mak";
   printf "\n" > "syscall.mak";

}'  > syscall.s

cat >> syscall.mak <<\!

CFLAGS=$(ARCH) $(CCFLAGS) $(DEFS)

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

$(LIBC)($(OBJ)): syscall.dat mksyscall
	$(AS) --defsym L_$*=0 syscall.s -o $*.o
	$(AR) $(ARFLAGS) $@ $*.o
!

exit $?
