~ubuntu-branches/debian/squeeze/ffcall/squeeze

« back to all changes in this revision

Viewing changes to ffcall/avcall/avcall-alpha.c

  • Committer: Bazaar Package Importer
  • Author(s): Christoph Egger
  • Date: 2010-06-26 15:29:30 UTC
  • mfrom: (5.1.1 experimental)
  • Revision ID: james.westby@ubuntu.com-20100626152930-c09y01gk3szcnykn
Tags: 1.10+cvs20100619-2
Ship to unstable

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#ifndef _avcall_alpha_c                         /*-*- C -*-*/
2
 
#define _avcall_alpha_c
3
 
/**
4
 
  Copyright 1993 Bill Triggs, <Bill.Triggs@inrialpes.fr>
5
 
  Copyright 1995-1999 Bruno Haible, <bruno@clisp.org>
6
 
 
7
 
  This is free software distributed under the GNU General Public
8
 
  Licence described in the file COPYING. Contact the author if
9
 
  you don't have this or can't live with it. There is ABSOLUTELY
10
 
  NO WARRANTY, explicit or implied, on this software.
11
 
**/
12
 
/*----------------------------------------------------------------------
13
 
  !!! THIS ROUTINE MUST BE COMPILED gcc -O !!!
14
 
 
15
 
  Foreign function interface for a DEC Alpha with gcc.
16
 
 
17
 
  This calls a C function with an argument list built up using macros
18
 
  defined in av_call.h.
19
 
 
20
 
  Alpha Argument Passing Conventions
21
 
 
22
 
  The first 6 arguments are passed in registers $16-$21 for integers,
23
 
  in registers $f16-$f21 for floats. From then on, everything is passed
24
 
  on the stack.
25
 
 
26
 
  Everything on the stack is word-aligned.
27
 
 
28
 
  Integers and pointers are returned in $0, floats and doubles in $f0.
29
 
  To return a structure, the called function copies the value to space
30
 
  pointed to by its first argument, and all other arguments are shifted
31
 
  down by one.
32
 
 
33
 
  Compile this routine with gcc for the __asm__ extensions and with
34
 
  optimisation on (-O or -O2 or -g -O) so that argframe is set to the
35
 
  correct offset.
36
 
  ----------------------------------------------------------------------*/
37
 
#include "avcall.h.in"
38
 
 
39
 
#define RETURN(TYPE,VAL)        (*(TYPE*)l->raddr = (TYPE)(VAL))
40
 
 
41
 
int
42
 
__builtin_avcall(av_alist* l)
43
 
{
44
 
  register __avword*    sp      __asm__("$30");  /* C names for registers */
45
 
  register long         arg1    __asm__("$16");
46
 
  register long         arg2    __asm__("$17");
47
 
  register long         arg3    __asm__("$18");
48
 
  register long         arg4    __asm__("$19");
49
 
  register long         arg5    __asm__("$20");
50
 
  register long         arg6    __asm__("$21");
51
 
  register double       fret    __asm__("$f0");
52
 
  register double       farg1   __asm__("$f16");
53
 
  register double       farg2   __asm__("$f17");
54
 
  register double       farg3   __asm__("$f18");
55
 
  register double       farg4   __asm__("$f19");
56
 
  register double       farg5   __asm__("$f20");
57
 
  register double       farg6   __asm__("$f21");
58
 
/*register __avword     iret    __asm__("$0"); */
59
 
  register __avword     iret2   __asm__("$1");
60
 
 
61
 
  __avword* argframe = (sp -= __AV_ALIST_WORDS); /* make room for argument list */
62
 
  int arglen = ((unsigned long) l->aptr - (unsigned long) l->args) >> 3;
63
 
  __avword i, i2;
64
 
 
65
 
  for (i = 6; i < arglen; i++)          /* push excess function args */
66
 
    argframe[i-6] = l->args[i];
67
 
 
68
 
                                        /* call function with 1st 6 args */
69
 
  /* we pass the args both in the integer registers and the floating point
70
 
     registers, so we don't have to store the argument types. */
71
 
  __asm__ __volatile__ ("ldq $16,%0" : : "m" (l->args[0])); /* arg1 = l->args[0]; */
72
 
  __asm__ __volatile__ ("ldt $f16,%0" : : "m" (l->args[0])); /* farg1 = *(double*) &l->args[0]; */
73
 
  __asm__ __volatile__ ("ldq $17,%0" : : "m" (l->args[1])); /* arg2 = l->args[1]; */
74
 
  __asm__ __volatile__ ("ldt $f17,%0" : : "m" (l->args[1])); /* farg2 = *(double*) &l->args[1]; */
75
 
  __asm__ __volatile__ ("ldq $18,%0" : : "m" (l->args[2])); /* arg3 = l->args[2]; */
76
 
  __asm__ __volatile__ ("ldt $f18,%0" : : "m" (l->args[2])); /* farg3 = *(double*) &l->args[2]; */
77
 
  __asm__ __volatile__ ("ldq $19,%0" : : "m" (l->args[3])); /* arg4 = l->args[3]; */
78
 
  __asm__ __volatile__ ("ldt $f19,%0" : : "m" (l->args[3])); /* farg4 = *(double*) &l->args[3]; */
79
 
  __asm__ __volatile__ ("ldq $20,%0" : : "m" (l->args[4])); /* arg5 = l->args[4]; */
80
 
  __asm__ __volatile__ ("ldt $f20,%0" : : "m" (l->args[4])); /* farg5 = *(double*) &l->args[4]; */
81
 
  __asm__ __volatile__ ("ldq $21,%0" : : "m" (l->args[5])); /* arg6 = l->args[5]; */
82
 
  __asm__ __volatile__ ("ldt $f21,%0" : : "m" (l->args[5])); /* farg6 = *(double*) &l->args[5]; */
83
 
  i = (*l->func)();
84
 
  i2 = iret2;
85
 
  sp += __AV_ALIST_WORDS;       /* remove argument list from the stack */
86
 
  /* this is apparently not needed, but better safe than sorry... */
87
 
  __asm__ __volatile__ ("" : : :
88
 
                        /* clobber */ "$16", "$17", "$18", "$19", "$20", "$21",
89
 
                                     "$f16","$f17","$f18","$f19","$f20","$f21");
90
 
 
91
 
  /* save return value */
92
 
  if (l->rtype == __AVvoid) {
93
 
  } else
94
 
  if (l->rtype == __AVword) {
95
 
    RETURN(__avword, i);
96
 
  } else
97
 
  if (l->rtype == __AVchar) {
98
 
    RETURN(char, i);
99
 
  } else
100
 
  if (l->rtype == __AVschar) {
101
 
    RETURN(signed char, i);
102
 
  } else
103
 
  if (l->rtype == __AVuchar) {
104
 
    RETURN(unsigned char, i);
105
 
  } else
106
 
  if (l->rtype == __AVshort) {
107
 
    RETURN(short, i);
108
 
  } else
109
 
  if (l->rtype == __AVushort) {
110
 
    RETURN(unsigned short, i);
111
 
  } else
112
 
  if (l->rtype == __AVint) {
113
 
    RETURN(int, i);
114
 
  } else
115
 
  if (l->rtype == __AVuint) {
116
 
    RETURN(unsigned int, i);
117
 
  } else
118
 
  if (l->rtype == __AVlong) {
119
 
    RETURN(long, i);
120
 
  } else
121
 
  if (l->rtype == __AVulong) {
122
 
    RETURN(unsigned long, i);
123
 
  } else
124
 
  if (l->rtype == __AVlonglong) {
125
 
    RETURN(long long, i);
126
 
  } else
127
 
  if (l->rtype == __AVulonglong) {
128
 
    RETURN(unsigned long long, i);
129
 
  } else
130
 
  if (l->rtype == __AVfloat) {
131
 
    RETURN(float, fret);
132
 
  } else
133
 
  if (l->rtype == __AVdouble) {
134
 
    RETURN(double, fret);
135
 
  } else
136
 
  if (l->rtype == __AVvoidp) {
137
 
    RETURN(void*, i);
138
 
  } else
139
 
  if (l->rtype == __AVstruct) {
140
 
    if (l->flags & __AV_PCC_STRUCT_RETURN) {
141
 
      /* pcc struct return convention: need a  *(TYPE*)l->raddr = *(TYPE*)i;  */
142
 
      if (l->rsize == sizeof(char)) {
143
 
        RETURN(char, *(char*)i);
144
 
      } else
145
 
      if (l->rsize == sizeof(short)) {
146
 
        RETURN(short, *(short*)i);
147
 
      } else
148
 
      if (l->rsize == sizeof(int)) {
149
 
        RETURN(int, *(int*)i);
150
 
      } else
151
 
      if (l->rsize == sizeof(long)) {
152
 
        RETURN(long, *(long*)i);
153
 
      } else {
154
 
        int n = (l->rsize + sizeof(__avword)-1)/sizeof(__avword);
155
 
        while (--n >= 0)
156
 
          ((__avword*)l->raddr)[n] = ((__avword*)i)[n];
157
 
      }
158
 
    } else {
159
 
      /* normal struct return convention */
160
 
      if (l->flags & __AV_REGISTER_STRUCT_RETURN) {
161
 
        if (l->rsize == sizeof(char)) {
162
 
          RETURN(char, i);
163
 
        } else
164
 
        if (l->rsize == sizeof(short)) {
165
 
          RETURN(short, i);
166
 
        } else
167
 
        if (l->rsize == sizeof(int)) {
168
 
          RETURN(int, i);
169
 
        } else
170
 
        if (l->rsize == sizeof(long)) {
171
 
          RETURN(long, i);
172
 
        } else
173
 
        if (l->rsize == 2*sizeof(__avword)) {
174
 
          ((__avword*)l->raddr)[0] = i;
175
 
          ((__avword*)l->raddr)[1] = i2;
176
 
        }
177
 
      }
178
 
    }
179
 
  }
180
 
  return 0;
181
 
}
182
 
 
183
 
#endif /*_avcall_alpha_c */