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

信息检索与抽取

开发平台:

Unix_Linux

  1. #ifndef _avcall_arm_c /*-*- C -*-*/
  2. #define _avcall_arm_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 Acorn Risc Maschine with gcc.
  14.   This calls a C function with an argument list built up using macros
  15.   defined in av_call.h.
  16.   ARM Argument Passing Conventions:
  17.   All arguments, except the first 4 words, are passed on the stack with
  18.   word alignment. Doubles take two words. Structure args are passed as
  19.   true structures embedded in the argument stack. To return a structure,
  20.   the called function copies the return value to the address supplied
  21.   in register "%r0".
  22.   Compile this routine with gcc -O (or -O2 or -g -O) to get the right
  23.   register variables, or use the assembler version.
  24.   ----------------------------------------------------------------------*/
  25. #include "avcall.h.in"
  26. #define RETURN(TYPE,VAL) (*(TYPE*)l->raddr = (TYPE)(VAL))
  27. int
  28. __builtin_avcall(av_alist* l)
  29. {
  30.   register __avword* sp __asm__("r13");  /* C names for registers */
  31. /*register __avword iret __asm__("r0"); */
  32.   register __avword iret2 __asm__("r1");
  33.   register float fret __asm__("r0"); /* r0 */
  34.   register double dret __asm__("r0"); /* r0,r1 */
  35.   __avword space[__AV_ALIST_WORDS]; /* space for callee's stack frame */
  36.   __avword* argframe = sp; /* stack offset for argument list */
  37.   int arglen = l->aptr - l->args;
  38.   __avword i;
  39.   for (i = 4; i < arglen; i++) /* push function args onto stack */
  40.     argframe[i-4] = l->args[i];
  41. /* call function, pass 4 args in registers */
  42.   i = (*l->func)(l->args[0], l->args[1], l->args[2], l->args[3]);
  43.   /* save return value */
  44.   if (l->rtype == __AVvoid) {
  45.   } else
  46.   if (l->rtype == __AVword) {
  47.     RETURN(__avword, i);
  48.   } else
  49.   if (l->rtype == __AVchar) {
  50.     RETURN(char, i);
  51.   } else
  52.   if (l->rtype == __AVschar) {
  53.     RETURN(signed char, i);
  54.   } else
  55.   if (l->rtype == __AVuchar) {
  56.     RETURN(unsigned char, i);
  57.   } else
  58.   if (l->rtype == __AVshort) {
  59.     RETURN(short, i);
  60.   } else
  61.   if (l->rtype == __AVushort) {
  62.     RETURN(unsigned short, i);
  63.   } else
  64.   if (l->rtype == __AVint) {
  65.     RETURN(int, i);
  66.   } else
  67.   if (l->rtype == __AVuint) {
  68.     RETURN(unsigned int, i);
  69.   } else
  70.   if (l->rtype == __AVlong) {
  71.     RETURN(long, i);
  72.   } else
  73.   if (l->rtype == __AVulong) {
  74.     RETURN(unsigned long, i);
  75.   } else
  76.   if (l->rtype == __AVlonglong || l->rtype == __AVulonglong) {
  77.     ((__avword*)l->raddr)[0] = i;
  78.     ((__avword*)l->raddr)[1] = iret2;
  79.   } else
  80.   if (l->rtype == __AVfloat) {
  81.     RETURN(float, fret);
  82.   } else
  83.   if (l->rtype == __AVdouble) {
  84.     RETURN(double, dret);
  85.   } else
  86.   if (l->rtype == __AVvoidp) {
  87.     RETURN(void*, i);
  88.   } else
  89.   if (l->rtype == __AVstruct) {
  90.     /* NB: On arm, all structure sizes are divisible by 4. */
  91.     if (l->flags & __AV_PCC_STRUCT_RETURN) {
  92.       /* pcc struct return convention: need a  *(TYPE*)l->raddr = *(TYPE*)i;  */
  93.       if (l->rsize == sizeof(char)) { /* can't occur */
  94.         RETURN(char, *(char*)i);
  95.       } else
  96.       if (l->rsize == sizeof(short)) { /* can't occur */
  97.         RETURN(short, *(short*)i);
  98.       } else
  99.       if (l->rsize == sizeof(int)) {
  100.         RETURN(int, *(int*)i);
  101.       } else
  102.       if (l->rsize == sizeof(double)) {
  103.         ((int*)l->raddr)[0] = ((int*)i)[0];
  104.         ((int*)l->raddr)[1] = ((int*)i)[1];
  105.       } else {
  106.         int n = (l->rsize+3)/4;
  107.         while (--n >= 0)
  108.           ((__avword*)l->raddr)[n] = ((__avword*)i)[n];
  109.       }
  110.     } else {
  111.       /* normal struct return convention */
  112.       if (l->flags & __AV_REGISTER_STRUCT_RETURN) {
  113.         if (l->rsize == sizeof(char)) { /* can't occur */
  114.           RETURN(char, i);
  115.         } else
  116.         if (l->rsize == sizeof(short)) { /* can't occur */
  117.           RETURN(short, i);
  118.         } else
  119.         if (l->rsize == sizeof(int)) {
  120.           RETURN(int, i);
  121.         } else
  122.         if (l->rsize == 2*sizeof(__avword)) {
  123.           ((__avword*)l->raddr)[0] = i;
  124.           ((__avword*)l->raddr)[1] = iret2;
  125.         }
  126.       }
  127.     }
  128.   }
  129.   return 0;
  130. }
  131. #endif /*_avcall_arm_c */