⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 avcall-sparc.c

📁 c++写的一个脚本解释器
💻 C
字号:
#ifndef _avcall_sparc_c				/*-*- C -*-*/#define _avcall_sparc_c/**  Copyright 1993 Bill Triggs, <Bill.Triggs@inrialpes.fr>  Copyright 1995-1999 Bruno Haible, <bruno@clisp.org>  This is free software distributed under the GNU General Public  Licence described in the file COPYING. Contact the author if  you don't have this or can't live with it. There is ABSOLUTELY  NO WARRANTY, explicit or implied, on this software.**//*----------------------------------------------------------------------  !!! THIS ROUTINE MUST BE COMPILED gcc -O !!!  Foreign function interface for a Sun4 Sparc with gcc/sun-cc.  This calls a C function with an argument list built up using macros  defined in av_call.h.  Sparc Argument Passing Conventions  The first 6 words of arguments are passed in integer registers o0-o5  regardless of type or alignment.  (Registers are windowed: o0-o5 become  i0-i5 if the called function executes a `save' instruction.)  Remaining  arguments are pushed onto the stack starting at a fixed offset  ("argframe"). Space is left on the stack frame for temporary storage of  the register arguments as well.  Doubles may be cut in half and misaligned.  Shorter integers are  always promoted to word-length.  Functions with K&R-style declarations  and float args pass them as doubles and truncate them on function entry.  Structures are passed as pointers to a local copy of the structure made  by the caller.  Integers and pointers are returned in o0, floats in f0, doubles in  f0/f1.  If the function returns a structure a pointer to space  allocated by the caller is pushed onto the stack immediately  before the function arguments. Gcc without -fpcc-struct-return returns  <= 4 byte structures as integers.  Sun cc allocates temporary space for a returned structure just below  the current frame pointer $fp (the $sp of the caller), and the caller  must copy them from there. It also returns the temp address in $o0, but  that gets nuked in the return in the code below so we can't use it.  **The Sun cc struct return stuff below is a kludge**, but seems to work  on the test cases...  Compile this routine with gcc for the __asm__ extensions and with  optimisation on (-O or -O2 or -g -O) so that argframe is set to the  correct offset. (%sp is used differently in non-optimized code).  For Sun cc, use the pre-compiled assembler version of this routine.  ----------------------------------------------------------------------*/#include "avcall.h.in"#define RETURN(TYPE,VAL)	(*(TYPE*)l->raddr = (TYPE)(VAL))register void* callee	__asm__("%g2");  /* any global or local register */register __avword o0	__asm__("%o0");register __avword o1	__asm__("%o1");register __avword o2	__asm__("%o2");register __avword o3	__asm__("%o3");register __avword o4	__asm__("%o4");register __avword o5	__asm__("%o5");int__builtin_avcall(av_alist* l){  /*?? We probably need to make space for Sun cc    struct return somewhere here. */  register __avword* sp	__asm__("%sp");  /* C names for registers */  register float fret	__asm__("%f0");  /* %f0 */  register double dret	__asm__("%f0");  /* %f0,%f1 */  __avword trampoline[6];		/* room for a trampoline */  __avword space[__AV_ALIST_WORDS];	/* space for callee's stack frame */  __avword *argframe = sp + 17;		/* stack offset for argument list */  int arglen = l->aptr - l->args;  __avword i;  if ((l->rtype == __AVstruct) && !(l->flags & __AV_SUNCC_STRUCT_RETURN))    argframe[-1] = (__avword)l->raddr;	/* push struct return address */  {    int i;    for (i = 6; i < arglen; i++)	/* push excess function args */      argframe[i] = l->args[i];  }  if ((l->rtype == __AVstruct) && (l->flags & __AV_SUNPROCC_STRUCT_RETURN))    /* SUNWspro cc compiled functions don't copy the structure to the area     * pointed to by argframe[-1] unless the caller has a proper "unimp n"     * instruction. We generate the calling instructions on the stack. */    {      trampoline[0] = 0x9FC08000;	/* call %g2	*/      trampoline[1] = 0x01000000;	/* nop		*/      trampoline[2] = l->rsize & 0xFFF;	/* unimp n	*/      trampoline[3] = 0xB0102000;       /* mov 0,%i0    */      trampoline[4] = 0x81C7E008;       /* ret          */      trampoline[5] = 0x81E80000;       /* restore      */      __asm__ __volatile__ ("iflush %0" : : "r" (&trampoline[0]));      __asm__ __volatile__ ("iflush %0" : : "r" (&trampoline[2]));      __asm__ __volatile__ ("iflush %0" : : "r" (&trampoline[4]));      __asm__ __volatile__ ("iflush %0" : : "r" (&trampoline[5]));      o0 = l->args[0]; o1 = l->args[1]; o2 = l->args[2];      o3 = l->args[3]; o4 = l->args[4]; o5 = l->args[5];      callee = l->func;      goto *(void*)trampoline;    }					/* call function with 1st 6 args */  i = ({ __avword iret;	/* %o0 */         iret = (*l->func)(l->args[0], l->args[1], l->args[2],			   l->args[3], l->args[4], l->args[5]);         asm ("nop");	/* struct returning functions skip this instruction */         iret;       });  /* save return value */  if (l->rtype == __AVvoid) {  } else  if (l->rtype == __AVword) {    RETURN(__avword, i);  } else  if (l->rtype == __AVchar) {    RETURN(char, i);  } else  if (l->rtype == __AVschar) {    RETURN(signed char, i);  } else  if (l->rtype == __AVuchar) {    RETURN(unsigned char, i);  } else  if (l->rtype == __AVshort) {    RETURN(short, i);  } else  if (l->rtype == __AVushort) {    RETURN(unsigned short, i);  } else  if (l->rtype == __AVint) {    RETURN(int, i);  } else  if (l->rtype == __AVuint) {    RETURN(unsigned int, i);  } else  if (l->rtype == __AVlong) {    RETURN(long, i);  } else  if (l->rtype == __AVulong) {    RETURN(unsigned long, i);  } else  if (l->rtype == __AVlonglong || l->rtype == __AVulonglong) {    ((__avword*)l->raddr)[0] = i;    ((__avword*)l->raddr)[1] = o1;  } else  if (l->rtype == __AVfloat) {    /* old Sun cc returns floats as doubles */    if (l->flags & __AV_SUNCC_FLOAT_RETURN) {      RETURN(float, (float)dret);    } else {      RETURN(float, fret);    }  } else  if (l->rtype == __AVdouble) {    RETURN(double, dret);  } else  if (l->rtype == __AVvoidp) {    RETURN(void*, i);  } else  if (l->rtype == __AVstruct) {    /* This is a kludge for old Sun cc and is probably fragile. */    if (l->flags & __AV_SUNCC_STRUCT_RETURN) {      /* Sun cc struct return convention */      if (l->rsize == sizeof(char)) {        RETURN(char, ((char*)sp)[-1]);      } else      if (l->rsize == sizeof(short)) {        RETURN(short, ((short*)sp)[-1]);      } else      if (l->rsize == sizeof(int)) {        RETURN(int, ((int*)sp)[-1]);      } else      if (l->rsize == sizeof(double)) {        ((int*)l->raddr)[0] = ((int*)sp)[-2];        ((int*)l->raddr)[1] = ((int*)sp)[-1];      } else      if (l->rsize % 4) {        char* dstaddr = (char*)l->raddr;        char* srcaddr = (char*)((long)sp - l->rsize);        unsigned int count = l->rsize;        if (count > 4)          srcaddr = (char*)((long)srcaddr & -4);        while (count > 0) {          *dstaddr++ = *srcaddr++;          count--;        }      } else {        __avword* dstaddr = (__avword*)l->raddr;        __avword* srcaddr = (__avword*)((long)sp - l->rsize);        while (srcaddr < sp)          *dstaddr++ = *srcaddr++;      }    } else {      if (l->flags & __AV_PCC_STRUCT_RETURN) {        /* pcc struct return convention: need a  *(TYPE*)l->raddr = *(TYPE*)i;  */        if (l->rsize == sizeof(char)) {          RETURN(char, *(char*)i);        } else        if (l->rsize == sizeof(short)) {          RETURN(short, *(short*)i);        } else        if (l->rsize == sizeof(int)) {          RETURN(int, *(int*)i);        } else        if (l->rsize == sizeof(double)) {          ((int*)l->raddr)[0] = ((int*)i)[0];          ((int*)l->raddr)[1] = ((int*)i)[1];        } else {          int n = (l->rsize + sizeof(__avword)-1)/sizeof(__avword);          while (--n >= 0)            ((__avword*)l->raddr)[n] = ((__avword*)i)[n];        }      } else {        /* normal struct return convention */        if (l->flags & __AV_SMALL_STRUCT_RETURN) {          if (l->rsize == sizeof(char)) {            RETURN(char, i);          } else          if (l->rsize == sizeof(short)) {            RETURN(short, i);          } else          if (l->rsize == sizeof(int)) {            RETURN(int, i);          }        }      }    }  }  return 0;}#endif /*_avcall_sparc_c */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -