avcall-sparc.c
上传用户:shenzhenrh
上传日期:2013-05-12
资源大小:2904k
文件大小:8k
源码类别:

信息检索与抽取

开发平台:

Unix_Linux

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