home *** CD-ROM | disk | FTP | other *** search
/ Amiga ISO Collection / AmigaUtilCD2.iso / Programming / Misc / CLISP-2.LHA / CLISP960530-ki.lha / ffcall / avcall / avcall-sparc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-04-15  |  6.4 KB  |  183 lines

  1. #ifndef _avcall_sparc_c                /*-*- C -*-*/
  2. #define _avcall_sparc_c "$Id: avcall-sparc.c,v 1.1.1.1 1995/09/10 10:58:53 marcus Exp $"
  3. /**
  4.   Copyright 1993 Bill Triggs, <bill@robots.oxford.ac.uk>,
  5.   Oxford University Robotics Group, Oxford OX1 3PJ, U.K.
  6.  
  7.   Copyright 1995 Bruno Haible, <haible@ma2s2.mathematik.uni-karlsruhe.de>
  8.  
  9.   This is free software distributed under the GNU General Public
  10.   Licence described in the file COPYING. Contact the author if
  11.   you don't have this or can't live with it. There is ABSOLUTELY
  12.   NO WARRANTY, explicit or implied, on this software.
  13. **/
  14. /*----------------------------------------------------------------------
  15.   !!! THIS ROUTINE MUST BE COMPILED gcc -O !!!
  16.  
  17.   Foreign function interface for a Sun4 Sparc with gcc/sun-cc.
  18.  
  19.   This calls a C function with an argument list built up using macros
  20.   defined in av_call.h.
  21.  
  22.   Sparc Argument Passing Conventions
  23.  
  24.   The first 6 words of arguments are passed in integer registers o0-o5
  25.   regardless of type or alignment.  (Registers are windowed: o0-o5 become
  26.   i0-i5 if the called function executes a `save' instruction.)  Remaining
  27.   arguments are pushed onto the stack starting at a fixed offset
  28.   ("argframe"). Space is left on the stack frame for temporary storage of
  29.   the register arguments as well.
  30.  
  31.   Doubles may be cut in half and misaligned.  Shorter integers are
  32.   always promoted to word-length.  Functions with K&R-style declarations
  33.   and float args pass them as doubles and truncate them on function entry.
  34.   Structures are passed as pointers to a local copy of the structure made
  35.   by the caller.
  36.  
  37.   Integers and pointers are returned in o0, floats in f0, doubles in
  38.   f0/f1.  If the function returns a structure a pointer to space
  39.   allocated by the caller is pushed onto the stack immediately
  40.   before the function arguments. Gcc without -fpcc-struct-return returns
  41.   <= 4 byte structures as integers.
  42.  
  43.   Sun cc allocates temporary space for a returned structure just below
  44.   the current frame pointer $fp (the $sp of the caller), and the caller
  45.   must copy them from there. It also returns the temp address in $o0, but
  46.   that gets nuked in the return in the code below so we can't use it.
  47.   **The Sun cc struct return stuff below is a kluge**, but seems to work
  48.   on the test cases...
  49.  
  50.   Compile this routine with gcc for the __asm__ extensions and with
  51.   optimisation on (-O or -O2 or -g -O) so that argframe is set to the
  52.   correct offset. (%sp is used differently in non-optimized code).
  53.   For Sun cc, use the pre-compiled assembler version of this routine.
  54.   ----------------------------------------------------------------------*/
  55. #include "avcall.h.in"
  56.  
  57. #define RETURN(TYPE,VAL)    (*(TYPE*)l->raddr = (TYPE)(VAL))
  58.  
  59. int
  60. __builtin_avcall(av_alist* l)
  61. {
  62.   /*?? We probably need to make space for Sun cc
  63.     struct return somewhere here. */
  64.   register __avword* sp    __asm__("%sp");  /* C names for registers */
  65.   register float fret    __asm__("%f0");  /* %f0 */
  66.   register double dret    __asm__("%f0");  /* %f0,%f1 */
  67.  
  68.   __avword space[__AV_ALIST_WORDS];    /* space for callee's stack frame */
  69.   __avword *argframe = sp + 17;        /* stack offset for argument list */
  70.   int arglen = l->aptr - l->args;
  71.   __avword i;
  72.  
  73.   if ((l->rtype == __AVstruct) && !(l->flags & __AV_SUNCC_STRUCT_RETURN))
  74.     argframe[-1] = (__avword)l->raddr;    /* push struct return address */
  75.  
  76.   {
  77.     int i;
  78.     for (i = 6; i < arglen; i++)    /* push excess function args */
  79.       argframe[i] = l->args[i];
  80.   }
  81.  
  82.                     /* call function with 1st 6 args */
  83.   i = ({ __avword iret;    /* %o0 */
  84.          iret = (*l->func)(l->args[0], l->args[1], l->args[2],
  85.                l->args[3], l->args[4], l->args[5]);
  86.          asm ("nop");    /* struct returning functions skip this instruction */
  87.          iret;
  88.        });
  89.  
  90.   switch (l->rtype)            /* save return value */
  91.   {
  92.   case __AVvoid:                    break;
  93.   case __AVword:    RETURN(__avword,    i);    break;
  94.   case __AVchar:    RETURN(char,        i);    break;
  95.   case __AVschar:    RETURN(signed char,    i);    break;
  96.   case __AVuchar:    RETURN(unsigned char,    i);    break;
  97.   case __AVshort:    RETURN(short,        i);    break;
  98.   case __AVushort:    RETURN(unsigned short,    i);    break;
  99.   case __AVint:        RETURN(int,        i);    break;
  100.   case __AVuint:    RETURN(unsigned int,    i);    break;
  101.   case __AVlong:    RETURN(long,        i);    break;
  102.   case __AVulong:    RETURN(unsigned long,    i);    break;
  103.   case __AVfloat:
  104.     /* old Sun cc returns floats as doubles */
  105.     if (l->flags & __AV_SUNCC_FLOAT_RETURN)
  106.       RETURN(float, (float)dret);
  107.     else
  108.       RETURN(float, fret);
  109.     break;
  110.   case __AVdouble:    RETURN(double,        dret);    break;
  111.   case __AVvoidp:    RETURN(void*,        i);    break;
  112.   case __AVstruct:
  113.     /* This is a kluge for old Sun cc and is probably fragile. */
  114.     if (l->flags & __AV_SUNCC_STRUCT_RETURN)
  115.     { /* Sun cc struct return convention */
  116.       switch (l->rsize)
  117.       {
  118.       case sizeof(char):  RETURN(char,  ((char*) sp)[-1]); break;
  119.       case sizeof(short): RETURN(short, ((short*)sp)[-1]); break;
  120.       case sizeof(int):      RETURN(int,   ((int*)  sp)[-1]); break;
  121.       case sizeof(double):
  122.     ((int*)l->raddr)[0] = ((int*)sp)[-2];
  123.     ((int*)l->raddr)[1] = ((int*)sp)[-1];
  124.     break;
  125.       default:
  126.     if (l->rsize % 4)
  127.       { char* dstaddr = (char*)l->raddr;
  128.         char* srcaddr = (char*)((long)sp - l->rsize);
  129.         unsigned int count = l->rsize;
  130.         if (count > 4)
  131.           srcaddr = (char*)((long)srcaddr & -4);
  132.         while (count > 0)
  133.           { *dstaddr++ = *srcaddr++; count--; }
  134.       }
  135.     else
  136.       { __avword* dstaddr = (__avword*)l->raddr;
  137.         __avword* srcaddr = (__avword*)((long)sp - l->rsize);
  138.         while (srcaddr < sp)
  139.           *dstaddr++ = *srcaddr++;
  140.       }
  141.     break;
  142.       }
  143.     }
  144.     else
  145.     if (l->flags & __AV_PCC_STRUCT_RETURN)
  146.     { /* pcc struct return convention: need a  *(TYPE*)l->raddr = *(TYPE*)i;  */
  147.       switch (l->rsize)
  148.       {
  149.       case sizeof(char):  RETURN(char,    *(char*)i);    break;
  150.       case sizeof(short): RETURN(short,    *(short*)i);    break;
  151.       case sizeof(int):      RETURN(int,    *(int*)i);    break;
  152.       case sizeof(double):
  153.     ((int*)l->raddr)[0] = ((int*)i)[0];
  154.     ((int*)l->raddr)[1] = ((int*)i)[1];
  155.     break;
  156.       default:
  157.     {
  158.       int n = (l->rsize + sizeof(__avword)-1)/sizeof(__avword);
  159.       while (--n >= 0)
  160.         ((__avword*)l->raddr)[n] = ((__avword*)i)[n];
  161.     }
  162.     break;
  163.       }
  164.     }
  165.     else
  166.     { /* normal struct return convention */
  167.       if (l->flags & __AV_SMALL_STRUCT_RETURN)
  168.     switch (l->rsize)
  169.     {
  170.     case sizeof(char):  RETURN(char,  i);    break;
  171.     case sizeof(short): RETURN(short, i);    break;
  172.     case sizeof(int):   RETURN(int,   i);    break;
  173.     default:                break;
  174.     }
  175.     }
  176.     break;
  177.   default:                    break;
  178.   }
  179.   return 0;
  180. }
  181.  
  182. #endif /*_avcall_sparc_c */
  183.