//+++2003-11-18
//    Copyright (C) 2001,2002,2003  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
//---2003-11-18

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

static int const regarg_7_16[] = { 22,23,0,1,2,3,4,5,6,7 };

int main ()

{
  int i, j;

  printf ("// Generated by oz_hwaxp_syscall_h_gen.c\n");
  printf ("// Called by oz_hw_axp.h to define the OZ_HW_SYSCALL_DCL_* and OZ_HW_SYSCALL_DEF_* macros\n\n");
  printf ("#ifndef _OZ_HWAXP_SYSCALL_H\n");
  printf ("#define _OZ_HWAXP_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 (");			// output oz_syscall_... routine definition
    for (j = 1; j <= 5; j ++) {					// always output args 1..5
      if (j <= i) printf ("t%d v%d,", j, j);			// either real ones
      else printf ("int __dummy%d__,", j);			// ... or dummy ones
    }
    printf ("OZ_Procmode cprocmode");				// arg 6 (R21) is always the caller's procmode
    for (j = 6; j <= i; j ++) printf (",t%d v%d", j, j);	// output args 6..n as args 7..n+1
    printf (");\n");
  }

  printf ("\n");

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

  /* All calls go through CHMK     */
  /* All args are in registers:    */
  /*   Args 1..6 go in R16..R21    */
  /*   Args 7..9 go in R22..R24    */
  /*   Args 10..16 go in R0..R6    */
  /* Outer mode return addr in R26 */
  /* Call index number goes in R27 */

  /* The oz_hwaxp_chmk routine does not care about the number of arguments */

  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 (\"mov	%0,$27\\n");		// syscall index number goes in R27
    for (j = 6; j < i; j ++) {					// load args 7..n into registers
      printf ("	ldq	$%d,%d($sp)\\n", regarg_7_16[j-6], (j - 6) * 8);
    }
    printf ("	call_pal 0x83 # CHMK\\n");			// jump to oz_hwaxp_chmk
    printf ("\" : : ");
    printf ("\"i\" (OZ_SYSCALL_##name)); ");			// output syscall index for R27
    printf ("return (0); } ");					// output a return (0) to keep compiler happy
    printf ("uLong oz_syscall_##name (");			// output oz_syscall_... routine definition
    for (j = 1; j <= 5; j ++) {					// always output args 1..5
      if (j <= i) printf ("t%d v%d,", j, j);			// either real ones
      else printf ("int __dummy%d__,", j);			// ... or dummy ones
    }
    printf ("OZ_Procmode cprocmode");				// arg 6 (R21) is always the caller's procmode
    for (j = 6; j <= i; j ++) printf (",t%d v%d", j, j);	// output args 6..n as args 7..n+1
    printf (")\n");
  }

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

  return (0);
}
