//+++2002-08-17
//    Copyright (C) 2001,2002  Mike Rieker, Beverly, MA USA
//
//    This program is free software; you can redistribute it and/or modify
//    it under the terms of the GNU General Public License as published by
//    the Free Software Foundation; version 2 of the License.
//
//    This program is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU General Public License for more details.
//
//    You should have received a copy of the GNU General Public License
//    along with this program; if not, write to the Free Software
//    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//---2002-08-17

#define _OZ_HW486_SYSCALL_H
#include "ozone.h"
#include "oz_knl_hw.h"
#include <stdio.h>

int main ()

{
  int i, j;

  printf ("// Generated by oz_hw486_syscall_h_gen.c\n");
  printf ("// Called by oz_hw_486.h to define the OZ_HW_SYSCALL_DCL_* and OZ_HW_SYSCALL_DEF_* macros\n\n");
  printf ("#ifndef _OZ_HW486_SYSCALL_H\n");
  printf ("#define _OZ_HW486_SYSCALL_H\n\n");

  /* Declaration macro creates the oz_sys_... and oz_syscall_... prototype statements */

  for (i = 0; i <= 16; i ++) {
    printf ("#define OZ_HW_SYSCALL_DCL_%d(name", i);		// output OZ_HW_SYSCALL_DCL_n(name
    for (j = 1; j <= i; j ++) {
      printf (",t%d,v%d", j, j);				// add on any ,tn,vn parameters
    }
    printf (") ");						// close prototype
    printf ("uLong oz_sys_##name (");				// output uLong oz_sys_name (
    if (i == 0) printf ("void");				// if zero'th, it has no args
    else {
      printf ("t1 v1");						// else, output t1 v1
      for (j = 2; j <= i; j ++) {
        printf (",t%d v%d", j, j);				// followed by any ,tn vn
      }
    }
    printf ("); ");						// close oz_sys_... function prototype
    printf ("uLong oz_syscall_##name (OZ_Procmode cprocmode, void *__dummy_ebp__, void *__dummy_eip__");
    for (j = 1; j <= i; j ++) {					// similar with oz_syscall_... prototype
      printf (",t%d v%d", j, j);
    }
    printf (");\n");
  }

  printf ("\n");

  /* Definition macro creates the oz_sys_... and oz_syscall_... subroutines */

  /* If caller is in kernel mode, the oz_syscall_... subroutine is simply called */
  /* Else, the oz_hw486_syscall routine is jumped to with:                       */
  /*      %ecx = number of bytes of call arguments                               */
  /*      %edx = call index number                                               */
  /*    (%esp) = return to caller of oz_sys_...                                  */
  /*   4(%esp) = first arg to oz_sys_...                                         */

  printf ("#define OZ_HW486_SYSCALL_SIZEOF(tn) (((sizeof (tn)) + 3) & -4)\n\n");

  for (i = 0; i <= 16; i ++) {
    printf ("#define OZ_HW_SYSCALL_DEF_%d(name", i);		// output OZ_HW_SYSCALL_DEF_n(name
    for (j = 1; j <= i; j ++) {
      printf (",t%d,v%d", j, j);				// add on any ,tn,vn parameters
    }
    printf (") ");						// close prototype

    printf ("uLong oz_sys_##name (");				// output oz_sys_... routine definition
    if (i == 0) printf ("void");
    else {
      printf ("t1 v1");
      for (j = 2; j <= i; j ++) printf (",t%d v%d", j, j);
    }
    printf (") {");

    printf ("asm volatile (\"movw  %%%%cs,%%%%ax\\n");		// first, see if we are in kernel mode already
    printf ("	testb $2,%%%%al\\n");
    printf ("	jne   oz_hw486_syscall\\n");			// not knl mode, jump to syscall routine in oz_kernel_486.s
								// in knl mode, __dummy_ebp__, __dummy_eip__ already on stack followed by args
    printf ("	movl  %%%%ebp,%%%%esp\\n");			// make sure stack is clean
    printf ("	pushl $%d\\n", OZ_PROCMODE_KNL);		// this gets passed as cprocmode = kernel mode
    printf ("	call  oz_syscall_\" #name \"\\n");		// call the oz_syscall_... routine directly
    printf ("	addl  $4,%%%%esp\\n");				// wipe the OZ_PROCMODE_KNL value from stack
    printf ("	popl  %%%%ebp\\n");				// wipe the __dummy_ebp__ from the stack
    printf ("	ret\" : : \"c\" (");				// return to caller of oz_sys_... routine
    if (i == 0) printf ("0");					// if index 0, call arg bytesize is always 0
    else {
      printf ("OZ_HW486_SYSCALL_SIZEOF(t1)");			// else, output total arg bytesize for %ecx
      for (j = 2; j <= i; j ++) printf ("+OZ_HW486_SYSCALL_SIZEOF(t%d)", j);
    }
    printf ("), \"d\" (OZ_SYSCALL_##name)); ");			// output syscall index for %edx
    printf ("return (0); } ");					// output a return (0) to keep compiler happy
    printf ("uLong oz_syscall_##name (OZ_Procmode cprocmode, void *__dummy_ebp__, void *__dummy_eip__");
    for (j = 1; j <= i; j ++) printf (",t%d v%d", j, j);	// output oz_syscall_... routine definition
    printf (")\n");
  }

  printf ("\n#endif\n");

  return (0);
}
