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

信息检索与抽取

开发平台:

Unix_Linux

  1. #ifndef _avcall_mipsn32_c /*-*- C -*-*/
  2. #define _avcall_mipsn32_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 an SGI 32-bit MIPS III with "cc -n32",
  14.   or gcc configured as mips-sgi-irix6.
  15.   This calls a C function with an argument list built up using macros
  16.   defined in av_call.h.
  17.   SGI MIPS new 32-bit Argument Passing Conventions
  18.   - The entire argument list forms a structure with all the appropriate
  19.     holes & alignments, and space for this is allocated in the stack frame.
  20.   - Shorter integers are promoted to long long length (sizeof(long long)=8).
  21.   - Doubles are 1 longword.
  22.   - Structure arguments are copies embedded in the arglist structure.
  23.   - The first 8 longwords of the structure are passed in registers $4...$11,
  24.     except that float arguments are passed in registers $f12...$f19, and
  25.     that double arguments and structure elements of type double are passed
  26.     in registers $f12...$f19. (But varargs functions may expect them in the
  27.     integer registers and we can't tell whether the function is varargs so
  28.     we pass them both ways.)
  29.     Remaining longwords are passed on the stack. No stack space is allocated
  30.     for the first 8 longwords of the structure.
  31.   - Structure returns of structures > 16 bytes: pointers to caller-allocated
  32.     space are passed in as the first argument of the list.
  33.   - Structure returns of structures <= 16 bytes: in the registers $2 (for the
  34.     first 8 bytes) and $3 (for the next 8 bytes).
  35.     A structure of 1 or 2 floats or doubles is returned in $f0 and $f2:
  36.     the first float or double in $f0, the second float or double in $f2.
  37.   - Integer/pointer returns are in $2, float/double returns in $f0.
  38.   - The called function expects to see its own address in $25.
  39.   This file needs to be compiled with gcc for the asm extensions, but the
  40.   assembly version of it and the header file seem to work with SGI cc.
  41.   ----------------------------------------------------------------------*/
  42. #include "avcall.h.in"
  43. #define RETURN(TYPE,VAL) (*(TYPE*)l->raddr = (TYPE)(VAL))
  44. #define OFFSETOF(struct,member) ((int)&(((struct*)0)->member))
  45. typedef __avword (*func_pointer)();
  46. register func_pointer t9 __asm__("$25");
  47. int
  48. __builtin_avcall(av_alist* l)
  49. {
  50.   register __avword* sp __asm__("$sp");  /* C names for registers */
  51.   register float fret __asm__("$f0");
  52.   register double dret __asm__("$f0");
  53. /*register __avword iret1 __asm__("$2"); */
  54.   register __avword iret2 __asm__("$3");
  55.   __avword space[__AV_ALIST_WORDS]; /* big space for child's stack frame */
  56.   __avword *argframe = (__avword*)sp; /* stack offset for argument list is 0 */
  57.   int arglen = l->aptr - l->args;
  58.   __avword i;
  59.   if (l->farg_mask)
  60.     { /* push leading float args */
  61.       if (l->farg_mask & (1<<0))
  62.         __asm__("lwc1 $f12,%1(%0)" : : "p" (l), "i" OFFSETOF(av_alist,farg[0]));
  63.       if (l->farg_mask & (1<<1))
  64.         __asm__("lwc1 $f13,%1(%0)" : : "p" (l), "i" OFFSETOF(av_alist,farg[1]));
  65.       if (l->farg_mask & (1<<2))
  66.         __asm__("lwc1 $f14,%1(%0)" : : "p" (l), "i" OFFSETOF(av_alist,farg[2]));
  67.       if (l->farg_mask & (1<<3))
  68.         __asm__("lwc1 $f15,%1(%0)" : : "p" (l), "i" OFFSETOF(av_alist,farg[3]));
  69.       if (l->farg_mask & (1<<4))
  70.         __asm__("lwc1 $f16,%1(%0)" : : "p" (l), "i" OFFSETOF(av_alist,farg[4]));
  71.       if (l->farg_mask & (1<<5))
  72.         __asm__("lwc1 $f17,%1(%0)" : : "p" (l), "i" OFFSETOF(av_alist,farg[5]));
  73.       if (l->farg_mask & (1<<6))
  74.         __asm__("lwc1 $f18,%1(%0)" : : "p" (l), "i" OFFSETOF(av_alist,farg[6]));
  75.       if (l->farg_mask & (1<<7))
  76.         __asm__("lwc1 $f19,%1(%0)" : : "p" (l), "i" OFFSETOF(av_alist,farg[7]));
  77.     }
  78.   if (l->darg_mask)
  79.     { /* push leading double args */
  80.       if (l->darg_mask & (1<<0))
  81.         __asm__("ldc1 $f12,%1(%0)" : : "p" (l), "i" OFFSETOF(av_alist,args[0]));
  82.       if (l->darg_mask & (1<<1))
  83.         __asm__("ldc1 $f13,%1(%0)" : : "p" (l), "i" OFFSETOF(av_alist,args[1]));
  84.       if (l->darg_mask & (1<<2))
  85.         __asm__("ldc1 $f14,%1(%0)" : : "p" (l), "i" OFFSETOF(av_alist,args[2]));
  86.       if (l->darg_mask & (1<<3))
  87.         __asm__("ldc1 $f15,%1(%0)" : : "p" (l), "i" OFFSETOF(av_alist,args[3]));
  88.       if (l->darg_mask & (1<<4))
  89.         __asm__("ldc1 $f16,%1(%0)" : : "p" (l), "i" OFFSETOF(av_alist,args[4]));
  90.       if (l->darg_mask & (1<<5))
  91.         __asm__("ldc1 $f17,%1(%0)" : : "p" (l), "i" OFFSETOF(av_alist,args[5]));
  92.       if (l->darg_mask & (1<<6))
  93.         __asm__("ldc1 $f18,%1(%0)" : : "p" (l), "i" OFFSETOF(av_alist,args[6]));
  94.       if (l->darg_mask & (1<<7))
  95.         __asm__("ldc1 $f19,%1(%0)" : : "p" (l), "i" OFFSETOF(av_alist,args[7]));
  96.     }
  97.   for (i = 8; i < arglen; i++) /* push excess function args */
  98.     argframe[i-8] = l->args[i];
  99. /* call function with 1st 8 args */
  100.   __asm__ __volatile__ ("ld $4,%0" : : "m" (l->args[0]) : "$4"); /* arg1 = l->args[0]; */
  101.   __asm__ __volatile__ ("ld $5,%0" : : "m" (l->args[1]) : "$5"); /* arg1 = l->args[1]; */
  102.   __asm__ __volatile__ ("ld $6,%0" : : "m" (l->args[2]) : "$6"); /* arg1 = l->args[2]; */
  103.   __asm__ __volatile__ ("ld $7,%0" : : "m" (l->args[3]) : "$7"); /* arg1 = l->args[3]; */
  104.   __asm__ __volatile__ ("ld $8,%0" : : "m" (l->args[4]) : "$8"); /* arg1 = l->args[4]; */
  105.   __asm__ __volatile__ ("ld $9,%0" : : "m" (l->args[5]) : "$9"); /* arg1 = l->args[5]; */
  106.   __asm__ __volatile__ ("ld $10,%0" : : "m" (l->args[6]) : "$10"); /* arg1 = l->args[6]; */
  107.   __asm__ __volatile__ ("ld $11,%0" : : "m" (l->args[7]) : "$11"); /* arg1 = l->args[7]; */
  108.   i = (*(t9 = l->func))();
  109.   /* save return value */
  110.   if (l->rtype == __AVvoid) {
  111.   } else
  112.   if (l->rtype == __AVword) {
  113.     RETURN(__avword, i);
  114.   } else
  115.   if (l->rtype == __AVchar) {
  116.     RETURN(char, i);
  117.   } else
  118.   if (l->rtype == __AVschar) {
  119.     RETURN(signed char, i);
  120.   } else
  121.   if (l->rtype == __AVuchar) {
  122.     RETURN(unsigned char, i);
  123.   } else
  124.   if (l->rtype == __AVshort) {
  125.     RETURN(short, i);
  126.   } else
  127.   if (l->rtype == __AVushort) {
  128.     RETURN(unsigned short, i);
  129.   } else
  130.   if (l->rtype == __AVint) {
  131.     RETURN(int, i);
  132.   } else
  133.   if (l->rtype == __AVuint) {
  134.     RETURN(unsigned int, i);
  135.   } else
  136.   if (l->rtype == __AVlong) {
  137.     RETURN(long, i);
  138.   } else
  139.   if (l->rtype == __AVulong) {
  140.     RETURN(unsigned long, i);
  141.   } else
  142.   if (l->rtype == __AVlonglong) {
  143.     RETURN(long long, i);
  144.   } else
  145.   if (l->rtype == __AVulonglong) {
  146.     RETURN(unsigned long long, i);
  147.   } else
  148.   if (l->rtype == __AVfloat) {
  149.     RETURN(float, fret);
  150.   } else
  151.   if (l->rtype == __AVdouble) {
  152.     RETURN(double, dret);
  153.   } else
  154.   if (l->rtype == __AVvoidp) {
  155.     RETURN(void*, i);
  156.   } else
  157.   if (l->rtype == __AVstruct) {
  158.     if (l->flags & __AV_PCC_STRUCT_RETURN) {
  159.       /* pcc struct return convention: need a  *(TYPE*)l->raddr = *(TYPE*)i;  */
  160.       if (l->rsize == sizeof(char)) {
  161.         RETURN(char, *(char*)i);
  162.       } else
  163.       if (l->rsize == sizeof(short)) {
  164.         RETURN(short, *(short*)i);
  165.       } else
  166.       if (l->rsize == sizeof(int)) {
  167.         RETURN(int, *(int*)i);
  168.       } else
  169.       if (l->rsize == sizeof(long long)) {
  170.         RETURN(long, *(long long*)i);
  171.       } else {
  172.         int n = (l->rsize + sizeof(__avword)-1)/sizeof(__avword);
  173.         while (--n >= 0)
  174.           ((__avword*)l->raddr)[n] = ((__avword*)i)[n];
  175.       }
  176.     } else {
  177.       /* normal struct return convention */
  178.       if (l->flags & __AV_REGISTER_STRUCT_RETURN) {
  179.         if (l->flags & __AV_GCC_STRUCT_RETURN) {
  180.           /* gcc returns structs of size 1,2,4,8 in registers. */
  181.           if (l->rsize == sizeof(char)) {
  182.             RETURN(char, i);
  183.           } else
  184.           if (l->rsize == sizeof(short)) {
  185.             RETURN(short, i);
  186.           } else
  187.           if (l->rsize == sizeof(int)) {
  188.             RETURN(int, i);
  189.           } else
  190.           if (l->rsize == sizeof(long long)) {
  191.             RETURN(long long, i);
  192.           }
  193.         } else {
  194.           /* cc returns structs of size <= 16 in registers. */
  195.           if (l->rsize > 0 && l->rsize <= 16) {
  196.             if (l->rsize == 1) {
  197.               ((unsigned char *)l->raddr)[0] = (unsigned char)(i>>56);
  198.             } else
  199.             if (l->rsize == 2) {
  200.               ((unsigned char *)l->raddr)[0] = (unsigned char)(i>>56);
  201.               ((unsigned char *)l->raddr)[1] = (unsigned char)(i>>48);
  202.             } else
  203.             if (l->rsize == 3) {
  204.               ((unsigned char *)l->raddr)[0] = (unsigned char)(i>>56);
  205.               ((unsigned char *)l->raddr)[1] = (unsigned char)(i>>48);
  206.               ((unsigned char *)l->raddr)[2] = (unsigned char)(i>>40);
  207.             } else
  208.             if (l->rsize == 4) {
  209.               ((unsigned char *)l->raddr)[0] = (unsigned char)(i>>56);
  210.               ((unsigned char *)l->raddr)[1] = (unsigned char)(i>>48);
  211.               ((unsigned char *)l->raddr)[2] = (unsigned char)(i>>40);
  212.               ((unsigned char *)l->raddr)[3] = (unsigned char)(i>>32);
  213.             } else
  214.             if (l->rsize == 5) {
  215.               ((unsigned char *)l->raddr)[0] = (unsigned char)(i>>56);
  216.               ((unsigned char *)l->raddr)[1] = (unsigned char)(i>>48);
  217.               ((unsigned char *)l->raddr)[2] = (unsigned char)(i>>40);
  218.               ((unsigned char *)l->raddr)[3] = (unsigned char)(i>>32);
  219.               ((unsigned char *)l->raddr)[4] = (unsigned char)(i>>24);
  220.             } else
  221.             if (l->rsize == 6) {
  222.               ((unsigned char *)l->raddr)[0] = (unsigned char)(i>>56);
  223.               ((unsigned char *)l->raddr)[1] = (unsigned char)(i>>48);
  224.               ((unsigned char *)l->raddr)[2] = (unsigned char)(i>>40);
  225.               ((unsigned char *)l->raddr)[3] = (unsigned char)(i>>32);
  226.               ((unsigned char *)l->raddr)[4] = (unsigned char)(i>>24);
  227.               ((unsigned char *)l->raddr)[5] = (unsigned char)(i>>16);
  228.             } else
  229.             if (l->rsize == 7) {
  230.               ((unsigned char *)l->raddr)[0] = (unsigned char)(i>>56);
  231.               ((unsigned char *)l->raddr)[1] = (unsigned char)(i>>48);
  232.               ((unsigned char *)l->raddr)[2] = (unsigned char)(i>>40);
  233.               ((unsigned char *)l->raddr)[3] = (unsigned char)(i>>32);
  234.               ((unsigned char *)l->raddr)[4] = (unsigned char)(i>>24);
  235.               ((unsigned char *)l->raddr)[5] = (unsigned char)(i>>16);
  236.               ((unsigned char *)l->raddr)[6] = (unsigned char)(i>>8);
  237.             } else
  238.             if (l->rsize >= 8 && l->rsize <= 16) {
  239.               ((unsigned char *)l->raddr)[0] = (unsigned char)(i>>56);
  240.               ((unsigned char *)l->raddr)[1] = (unsigned char)(i>>48);
  241.               ((unsigned char *)l->raddr)[2] = (unsigned char)(i>>40);
  242.               ((unsigned char *)l->raddr)[3] = (unsigned char)(i>>32);
  243.               ((unsigned char *)l->raddr)[4] = (unsigned char)(i>>24);
  244.               ((unsigned char *)l->raddr)[5] = (unsigned char)(i>>16);
  245.               ((unsigned char *)l->raddr)[6] = (unsigned char)(i>>8);
  246.               ((unsigned char *)l->raddr)[7] = (unsigned char)(i);
  247.               if (l->rsize == 8) {
  248.               } else
  249.               if (l->rsize == 9) {
  250.                 ((unsigned char *)l->raddr)[8+0] = (unsigned char)(iret2>>56);
  251.               } else
  252.               if (l->rsize == 10) {
  253.                 ((unsigned char *)l->raddr)[8+0] = (unsigned char)(iret2>>56);
  254.                 ((unsigned char *)l->raddr)[8+1] = (unsigned char)(iret2>>48);
  255.               } else
  256.               if (l->rsize == 11) {
  257.                 ((unsigned char *)l->raddr)[8+0] = (unsigned char)(iret2>>56);
  258.                 ((unsigned char *)l->raddr)[8+1] = (unsigned char)(iret2>>48);
  259.                 ((unsigned char *)l->raddr)[8+2] = (unsigned char)(iret2>>40);
  260.               } else
  261.               if (l->rsize == 12) {
  262.                 ((unsigned char *)l->raddr)[8+0] = (unsigned char)(iret2>>56);
  263.                 ((unsigned char *)l->raddr)[8+1] = (unsigned char)(iret2>>48);
  264.                 ((unsigned char *)l->raddr)[8+2] = (unsigned char)(iret2>>40);
  265.                 ((unsigned char *)l->raddr)[8+3] = (unsigned char)(iret2>>32);
  266.               } else
  267.               if (l->rsize == 13) {
  268.                 ((unsigned char *)l->raddr)[8+0] = (unsigned char)(iret2>>56);
  269.                 ((unsigned char *)l->raddr)[8+1] = (unsigned char)(iret2>>48);
  270.                 ((unsigned char *)l->raddr)[8+2] = (unsigned char)(iret2>>40);
  271.                 ((unsigned char *)l->raddr)[8+3] = (unsigned char)(iret2>>32);
  272.                 ((unsigned char *)l->raddr)[8+4] = (unsigned char)(iret2>>24);
  273.               } else
  274.               if (l->rsize == 14) {
  275.                 ((unsigned char *)l->raddr)[8+0] = (unsigned char)(iret2>>56);
  276.                 ((unsigned char *)l->raddr)[8+1] = (unsigned char)(iret2>>48);
  277.                 ((unsigned char *)l->raddr)[8+2] = (unsigned char)(iret2>>40);
  278.                 ((unsigned char *)l->raddr)[8+3] = (unsigned char)(iret2>>32);
  279.                 ((unsigned char *)l->raddr)[8+4] = (unsigned char)(iret2>>24);
  280.                 ((unsigned char *)l->raddr)[8+5] = (unsigned char)(iret2>>16);
  281.               } else
  282.               if (l->rsize == 15) {
  283.                 ((unsigned char *)l->raddr)[8+0] = (unsigned char)(iret2>>56);
  284.                 ((unsigned char *)l->raddr)[8+1] = (unsigned char)(iret2>>48);
  285.                 ((unsigned char *)l->raddr)[8+2] = (unsigned char)(iret2>>40);
  286.                 ((unsigned char *)l->raddr)[8+3] = (unsigned char)(iret2>>32);
  287.                 ((unsigned char *)l->raddr)[8+4] = (unsigned char)(iret2>>24);
  288.                 ((unsigned char *)l->raddr)[8+5] = (unsigned char)(iret2>>16);
  289.                 ((unsigned char *)l->raddr)[8+6] = (unsigned char)(iret2>>8);
  290.               } else
  291.               if (l->rsize == 16) {
  292.                 ((unsigned char *)l->raddr)[8+0] = (unsigned char)(iret2>>56);
  293.                 ((unsigned char *)l->raddr)[8+1] = (unsigned char)(iret2>>48);
  294.                 ((unsigned char *)l->raddr)[8+2] = (unsigned char)(iret2>>40);
  295.                 ((unsigned char *)l->raddr)[8+3] = (unsigned char)(iret2>>32);
  296.                 ((unsigned char *)l->raddr)[8+4] = (unsigned char)(iret2>>24);
  297.                 ((unsigned char *)l->raddr)[8+5] = (unsigned char)(iret2>>16);
  298.                 ((unsigned char *)l->raddr)[8+6] = (unsigned char)(iret2>>8);
  299.                 ((unsigned char *)l->raddr)[8+7] = (unsigned char)(iret2);
  300.               }
  301.             }
  302.           }
  303.         }
  304.       }
  305.     }
  306.   }
  307.   return 0;
  308. }
  309. #endif /*_avcall_mipsn32_c */