home *** CD-ROM | disk | FTP | other *** search
/ Amiga ISO Collection / AmigaUtilCD2.iso / Programming / Misc / CLISP-2.LHA / CLISP960530-ki.lha / ffcall / vacall / vacall-hppa.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-04-15  |  8.3 KB  |  190 lines

  1. /* vacall function for hppa CPU */
  2.  
  3. /*
  4.  * Copyright 1995 Bruno Haible, <haible@ma2s2.mathematik.uni-karlsruhe.de>
  5.  *
  6.  * This is free software distributed under the GNU General Public Licence
  7.  * described in the file COPYING. Contact the author if you don't have this
  8.  * or can't live with it. There is ABSOLUTELY NO WARRANTY, explicit or implied,
  9.  * on this software.
  10.  */
  11.  
  12. /*---------------------------------------------------------------------------
  13.   HPPA Argument Passing Conventions:
  14.  
  15.   The calling conventions for anonymous functions and for explicitly named
  16.   functions are different. Only the convention for explicitly named functions
  17.   matters here.
  18.  
  19.   All arguments, except the first 4 words, are passed on the stack
  20.   - growing down! - with word alignment. Doubles take two words and force
  21.   double alignment. Structures args are passed as true structures embedded
  22.   in the argument stack. They force double alignment and - if they don't
  23.   fit entirely in the 4 register words - are passed in memory.
  24.   The first 2 words are passed like this:
  25.     %r26 = first integer arg, %r25 = second integer arg, or
  26.     %fr4L = first float arg, %fr5L = second float arg, or
  27.     %fr5 = double arg.
  28.   Similarly for the next 2 words, passed in %r24 and %r23, or
  29.                                             %fr6L and %fr7L, or
  30.                                             %fr7.
  31.  
  32.   To return a structure, the called function copies the return value to
  33.   the address supplied in register "%r28".
  34. ---------------------------------------------------------------------------*/
  35.  
  36. #include "vacall.h.in"
  37.  
  38. register void*    sret    __asm__("%r28");
  39. register long   arg1    __asm__("%r26");
  40. register long   arg2    __asm__("%r25");
  41. register long   arg3    __asm__("%r24");
  42. register long   arg4    __asm__("%r23");
  43. register float  farg1    __asm__("%fr4"); /* fr4L */
  44. register float  farg2    __asm__("%fr5"); /* fr5L */
  45. register float  farg3    __asm__("%fr6"); /* fr6L */
  46. register float  farg4    __asm__("%fr7"); /* fr7L */
  47. register double darg1    __asm__("%fr5");
  48. register double darg2    __asm__("%fr7");
  49. register int    iret    __asm__("%r28");
  50. register float    fret    __asm__("%fr4"); /* fr4L */
  51. register double    dret    __asm__("%fr4");
  52. register __vaword iret1    __asm__("%r28");
  53. register __vaword iret2    __asm__("%r29");
  54.  
  55. void /* the return type is variable, not void! */
  56. vacall (__vaword word1, __vaword word2, __vaword word3, __vaword word4,
  57.         __vaword firstword)
  58. {
  59.   /* gcc-2.6.3 source says: When a parameter is passed in a register,
  60.    * stack space is still allocated for it.
  61.    */
  62.   /* Note about stack offsets (see vacall-hppa.s):
  63.    * &firstword = %r30 - 244, &word4 = %r30 - 240, ..., &word1 = %r30 - 228,
  64.    */
  65.   __va_alist list;
  66.   /* Move the arguments passed in registers to their stack locations. */
  67.   &word1; /* (&firstword)[4] = word1; */
  68.   &word2; /* (&firstword)[3] = word2; */
  69.   &word3; /* (&firstword)[2] = word3; */
  70.   &word4; /* (&firstword)[1] = word4; */
  71.   list.darg[1] = darg1;
  72.   list.darg[0] = darg2;
  73.   list.farg[3] = farg1;
  74.   list.farg[2] = farg2;
  75.   list.farg[1] = farg3;
  76.   list.farg[0] = farg4;
  77.   /* Prepare the va_alist. */
  78.   list.flags = 0;
  79.   list.aptr = (long)(&firstword + 5);
  80.   list.raddr = (void*)0;
  81.   list.rtype = __VAvoid;
  82.   list.structraddr = sret;
  83.   list.memargptr = (long)(&firstword + 1);
  84.   list.farg_offset = (long)&list.farg[4] - list.aptr;
  85.   list.darg_offset = (long)&list.darg[2] - list.aptr;
  86.   /* Call vacall_function. The macros do all the rest. */
  87.   (*vacall_function) (&list);
  88.   /* Put return value into proper register. */
  89.   switch (list.rtype)
  90.     {
  91.       case __VAvoid:    break;
  92.       case __VAchar:    iret = list.tmp._char; break;
  93.       case __VAschar:    iret = list.tmp._schar; break;
  94.       case __VAuchar:    iret = list.tmp._uchar; break;
  95.       case __VAshort:    iret = list.tmp._short; break;
  96.       case __VAushort:    iret = list.tmp._ushort; break;
  97.       case __VAint:    iret = list.tmp._int; break;
  98.       case __VAuint:    iret = list.tmp._uint; break;
  99.       case __VAlong:    iret = list.tmp._long; break;
  100.       case __VAulong:    iret = list.tmp._ulong; break;
  101.       case __VAfloat:
  102.         fret = list.tmp._float;
  103.         iret1 = list.tmp._words[0]; /* HP cc generates a RTNVAL=GR call */
  104.         break;
  105.       case __VAdouble:
  106.         dret = list.tmp._double;
  107.         iret1 = list.tmp._words[0]; /* HP cc generates a RTNVAL=GR call */
  108.         iret2 = list.tmp._words[1]; /* i.e. result is expected in r28,r29 */
  109.         break;
  110.       case __VAvoidp:    iret = (long)list.tmp._ptr; break;
  111.       case __VAstruct:
  112.         if (list.flags & __VA_PCC_STRUCT_RETURN)
  113.           { /* pcc struct return convention */
  114.             iret = (long) list.raddr;
  115.           }
  116.         else
  117.           { /* normal struct return convention */
  118.             if (list.flags & __VA_SMALL_STRUCT_RETURN)
  119.               if (list.flags & __VA_GCC_STRUCT_RETURN)
  120.                 /* gcc returns structs of size 1,2,4 in registers. */
  121.                 switch (list.rsize)
  122.                   {
  123.                     case sizeof(char):  iret = *(unsigned char *) list.raddr; break;
  124.                     case sizeof(short): iret = *(unsigned short *) list.raddr; break;
  125.                     case sizeof(int):   iret = *(unsigned int *) list.raddr; break;
  126.                     default:            break;
  127.                   }
  128.               else
  129.                 /* cc and c89 return structs of size <= 8 in registers. */
  130.                 switch (list.rsize)
  131.                   {
  132.                     case 1:
  133.                       iret =   ((unsigned char *) list.raddr)[0];
  134.                       break;
  135.                     case 2:
  136.                       iret =  (((unsigned char *) list.raddr)[0] << 8)
  137.                             |  ((unsigned char *) list.raddr)[1];
  138.                       break;
  139.                     case 3:
  140.                       iret =  (((unsigned char *) list.raddr)[0] << 16)
  141.                             | (((unsigned char *) list.raddr)[1] << 8)
  142.                             |  ((unsigned char *) list.raddr)[2];
  143.                       break;
  144.                     case 4:
  145.                       iret =  (((unsigned char *) list.raddr)[0] << 24)
  146.                             | (((unsigned char *) list.raddr)[1] << 16)
  147.                             | (((unsigned char *) list.raddr)[2] << 8)
  148.                             |  ((unsigned char *) list.raddr)[3];
  149.                       break;
  150.                     case 5:
  151.                       iret1 =  (((unsigned char *) list.raddr)[0] << 24)
  152.                              | (((unsigned char *) list.raddr)[1] << 16)
  153.                              | (((unsigned char *) list.raddr)[2] << 8)
  154.                              |  ((unsigned char *) list.raddr)[3];
  155.                       iret2 =   ((unsigned char *) list.raddr)[4];
  156.                       break;
  157.                     case 6:
  158.                       iret1 =  (((unsigned char *) list.raddr)[0] << 24)
  159.                              | (((unsigned char *) list.raddr)[1] << 16)
  160.                              | (((unsigned char *) list.raddr)[2] << 8)
  161.                              |  ((unsigned char *) list.raddr)[3];
  162.                       iret2 =  (((unsigned char *) list.raddr)[4] << 8)
  163.                              |  ((unsigned char *) list.raddr)[5];
  164.                       break;
  165.                     case 7:
  166.                       iret1 =  (((unsigned char *) list.raddr)[0] << 24)
  167.                              | (((unsigned char *) list.raddr)[1] << 16)
  168.                              | (((unsigned char *) list.raddr)[2] << 8)
  169.                              |  ((unsigned char *) list.raddr)[3];
  170.                       iret2 =  (((unsigned char *) list.raddr)[4] << 16)
  171.                              | (((unsigned char *) list.raddr)[5] << 8)
  172.                              |  ((unsigned char *) list.raddr)[6];
  173.                       break;
  174.                     case 8:
  175.                       iret1 =  (((unsigned char *) list.raddr)[0] << 24)
  176.                              | (((unsigned char *) list.raddr)[1] << 16)
  177.                              | (((unsigned char *) list.raddr)[2] << 8)
  178.                              |  ((unsigned char *) list.raddr)[3];
  179.                       iret2 =  (((unsigned char *) list.raddr)[4] << 24)
  180.                              | (((unsigned char *) list.raddr)[5] << 16)
  181.                              | (((unsigned char *) list.raddr)[6] << 8)
  182.                              |  ((unsigned char *) list.raddr)[7];
  183.                       break;
  184.                     default:            break;
  185.                   }
  186.           }
  187.         break;
  188.     }
  189. }
  190.