avcall-ia64.c
上传用户:shenzhenrh
上传日期:2013-05-12
资源大小:2904k
文件大小:10k
- #ifndef _avcall_ia64_c /*-*- C -*-*/
- #define _avcall_ia64_c
- /**
- Copyright 1993 Bill Triggs, <Bill.Triggs@inrialpes.fr>
- Copyright 1995-2001 Bruno Haible, <haible@clisp.cons.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 Intel IA-64 in little-endian mode with gcc.
- This calls a C function with an argument list built up using macros
- defined in av_call.h.
- IA-64 64-bit Argument Passing Conventions:
- The argument sequence is mapped linearly on the registers r32,...,r39,
- and continued on the stack, in [r12+16], [r12+24], ...
- Items in this sequence are word-aligned. Structures larger than a single
- word are even two-word-aligned.
- Integer/pointer arguments are passed in the allocated slots (registers
- or stack slots). The first 8 float/double arguments are passed in
- registers f8,...,f15 instead, but their slots are kept allocated.
- Structure args are passed like multiple integer arguments; except that
- structures consisting only of floats or only of doubles are passed like
- multiple float arguments or multiple double arguments, respectively.
- Integers and pointers are returned in r8, floats and doubles in f8.
- Structures consisting only of at most 8 floats or only of at most 8 doubles
- are returned in f8,...,f15. Other than that, structures of size <= 32 bytes
- are returned in r8,...,r11, as if these were 4 contiguous words in memory.
- Larger structures are returned in memory; the caller passes the address
- of the target memory area in r8, and it is returned unmodified in r8.
- ----------------------------------------------------------------------*/
- #include "avcall.h.in"
- #define RETURN(TYPE,VAL) (*(TYPE*)l->raddr = (TYPE)(VAL))
- register __avword* sret __asm__("r8"); /* structure return pointer */
- register __avword iret __asm__("r8");
- register __avword iret2 __asm__("r9");
- register __avword iret3 __asm__("r10");
- register __avword iret4 __asm__("r11");
- /*register float fret __asm__("f8");*/
- /*register double dret __asm__("f8");*/
- register double farg1 __asm__("f8");
- register double farg2 __asm__("f9");
- register double farg3 __asm__("f10");
- register double farg4 __asm__("f11");
- register double farg5 __asm__("f12");
- register double farg6 __asm__("f13");
- register double farg7 __asm__("f14");
- register double farg8 __asm__("f15");
- int
- __builtin_avcall(av_alist* l)
- {
- register __avword* sp __asm__("r12"); /* C names for registers */
- __avword* argframe = (sp -= __AV_ALIST_WORDS) + 2; /* make room for argument list */
- int arglen = l->aptr - l->args;
- int farglen = l->faptr - l->fargs;
- __avword i;
- for (i = 8; i < arglen; i++) /* push function args onto stack */
- argframe[i-8] = l->args[i];
- /* struct return address */
- if (l->rtype == __AVstruct)
- sret = l->raddr;
- /* put max. 8 double args in registers */
- if (farglen > 0) {
- farg1 = l->fargs[0];
- if (farglen > 1) {
- farg2 = l->fargs[1];
- if (farglen > 2) {
- farg3 = l->fargs[2];
- if (farglen > 3) {
- farg4 = l->fargs[3];
- if (farglen > 4) {
- farg5 = l->fargs[4];
- if (farglen > 5) {
- farg6 = l->fargs[5];
- if (farglen > 6) {
- farg7 = l->fargs[6];
- if (farglen > 7)
- farg8 = l->fargs[7];
- }
- }
- }
- }
- }
- }
- }
- /* call function, pass 8 integer and 8 double args in registers */
- if (l->rtype == __AVfloat) {
- *(float*)l->raddr = (*(float(*)())l->func)(l->args[0], l->args[1],
- l->args[2], l->args[3],
- l->args[4], l->args[5],
- l->args[6], l->args[7]);
- } else
- if (l->rtype == __AVdouble) {
- *(double*)l->raddr = (*(double(*)())l->func)(l->args[0], l->args[1],
- l->args[2], l->args[3],
- l->args[4], l->args[5],
- l->args[6], l->args[7]);
- } else {
- i = (*l->func)(l->args[0], l->args[1], l->args[2], l->args[3],
- l->args[4], l->args[5], l->args[6], l->args[7]);
- /* 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 || l->rtype == __AVlonglong) {
- RETURN(long, i);
- } else
- if (l->rtype == __AVulong || l->rtype == __AVulonglong) {
- RETURN(unsigned long, i);
- } else
- /* see above
- if (l->rtype == __AVfloat) {
- } else
- if (l->rtype == __AVdouble) {
- } else
- */
- if (l->rtype == __AVvoidp) {
- RETURN(void*, i);
- } else
- if (l->rtype == __AVstruct) {
- 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(long)) {
- RETURN(long, *(long*)i);
- } 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_REGISTER_STRUCT_RETURN) {
- /* Return structs of size <= 32 in registers. */
- if (l->rsize > 0 && l->rsize <= 32) {
- if (l->rsize >= 1)
- ((unsigned char *)l->raddr)[0] = (unsigned char)(i);
- if (l->rsize >= 2)
- ((unsigned char *)l->raddr)[1] = (unsigned char)(i>>8);
- if (l->rsize >= 3)
- ((unsigned char *)l->raddr)[2] = (unsigned char)(i>>16);
- if (l->rsize >= 4)
- ((unsigned char *)l->raddr)[3] = (unsigned char)(i>>24);
- if (l->rsize >= 5)
- ((unsigned char *)l->raddr)[4] = (unsigned char)(i>>32);
- if (l->rsize >= 6)
- ((unsigned char *)l->raddr)[5] = (unsigned char)(i>>40);
- if (l->rsize >= 7)
- ((unsigned char *)l->raddr)[6] = (unsigned char)(i>>48);
- if (l->rsize >= 8)
- ((unsigned char *)l->raddr)[7] = (unsigned char)(i>>56);
- if (l->rsize >= 9) {
- ((unsigned char *)l->raddr)[8] = (unsigned char)(iret2);
- if (l->rsize >= 10)
- ((unsigned char *)l->raddr)[9] = (unsigned char)(iret2>>8);
- if (l->rsize >= 11)
- ((unsigned char *)l->raddr)[10] = (unsigned char)(iret2>>16);
- if (l->rsize >= 12)
- ((unsigned char *)l->raddr)[11] = (unsigned char)(iret2>>24);
- if (l->rsize >= 13)
- ((unsigned char *)l->raddr)[12] = (unsigned char)(iret2>>32);
- if (l->rsize >= 14)
- ((unsigned char *)l->raddr)[13] = (unsigned char)(iret2>>40);
- if (l->rsize >= 15)
- ((unsigned char *)l->raddr)[14] = (unsigned char)(iret2>>48);
- if (l->rsize >= 16)
- ((unsigned char *)l->raddr)[15] = (unsigned char)(iret2>>56);
- if (l->rsize >= 17) {
- ((unsigned char *)l->raddr)[16] = (unsigned char)(iret3);
- if (l->rsize >= 18)
- ((unsigned char *)l->raddr)[17] = (unsigned char)(iret3>>8);
- if (l->rsize >= 19)
- ((unsigned char *)l->raddr)[18] = (unsigned char)(iret3>>16);
- if (l->rsize >= 20)
- ((unsigned char *)l->raddr)[19] = (unsigned char)(iret3>>24);
- if (l->rsize >= 21)
- ((unsigned char *)l->raddr)[20] = (unsigned char)(iret3>>32);
- if (l->rsize >= 22)
- ((unsigned char *)l->raddr)[21] = (unsigned char)(iret3>>40);
- if (l->rsize >= 23)
- ((unsigned char *)l->raddr)[22] = (unsigned char)(iret3>>48);
- if (l->rsize >= 24)
- ((unsigned char *)l->raddr)[23] = (unsigned char)(iret3>>56);
- if (l->rsize >= 25) {
- ((unsigned char *)l->raddr)[24] = (unsigned char)(iret4);
- if (l->rsize >= 26)
- ((unsigned char *)l->raddr)[25] = (unsigned char)(iret4>>8);
- if (l->rsize >= 27)
- ((unsigned char *)l->raddr)[26] = (unsigned char)(iret4>>16);
- if (l->rsize >= 28)
- ((unsigned char *)l->raddr)[27] = (unsigned char)(iret4>>24);
- if (l->rsize >= 29)
- ((unsigned char *)l->raddr)[28] = (unsigned char)(iret4>>32);
- if (l->rsize >= 30)
- ((unsigned char *)l->raddr)[29] = (unsigned char)(iret4>>40);
- if (l->rsize >= 31)
- ((unsigned char *)l->raddr)[30] = (unsigned char)(iret4>>48);
- if (l->rsize >= 32)
- ((unsigned char *)l->raddr)[31] = (unsigned char)(iret4>>56);
- }
- }
- }
- }
- }
- }
- }
- }
- return 0;
- }
- #endif /*_avcall_ia64_c */