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

« back to all changes in this revision

Viewing changes to ffcall/avcall/avcall-mips64.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_mips64_c                                /*-*- C -*-*/
2
 
#define _avcall_mips64_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 an SGI 64-bit MIPS with sgi-cc.
16
 
 
17
 
  This calls a C function with an argument list built up using macros
18
 
  defined in av_call.h.
19
 
 
20
 
  SGI MIPS 64-bit Argument Passing Conventions
21
 
 
22
 
  - The entire argument list forms a structure with all the appropriate
23
 
    holes & alignments, and space for this is allocated in the stack frame.
24
 
  - Shorter integers are promoted to longword length (sizeof(long)=8).
25
 
  - Doubles are 1 longword.
26
 
  - Structure arguments are copies embedded in the arglist structure.
27
 
  - The first 8 longwords of the structure are passed in registers $4...$11,
28
 
    except that float arguments are passed in registers $f12...$f19, and
29
 
    that double arguments and structure elements of type double are passed
30
 
    in registers $f12...$f19. (But varargs functions may expect them in the
31
 
    integer registers and we can't tell whether the function is varargs so
32
 
    we pass them both ways.)
33
 
    Remaining longwords are passed on the stack. No stack space is allocated
34
 
    for the first 8 longwords of the structure.
35
 
  - Structure returns of structures > 16 bytes: pointers to caller-allocated
36
 
    space are passed in as the first argument of the list.
37
 
  - Structure returns of structures <= 16 bytes: in the registers $2 (for the
38
 
    first 8 bytes) and $3 (for the next 8 bytes).
39
 
    A structure of 1 or 2 floats or doubles is returned in $f0 and $f2:
40
 
    the first float or double in $f0, the second float or double in $f2.
41
 
  - Integer/pointer returns are in $2, float/double returns in $f0.
42
 
  - The called function expects to see its own address in $25.
43
 
 
44
 
  This file needs to be compiled with gcc for the asm extensions, but the
45
 
  assembly version of it and the header file seem to work with SGI cc.
46
 
  ----------------------------------------------------------------------*/
47
 
#include "avcall.h.in"
48
 
 
49
 
#define RETURN(TYPE,VAL)        (*(TYPE*)l->raddr = (TYPE)(VAL))
50
 
#define OFFSETOF(struct,member) ((int)&(((struct*)0)->member))
51
 
 
52
 
typedef __avword (*func_pointer)();
53
 
register func_pointer   t9      __asm__("$25");
54
 
 
55
 
int
56
 
__builtin_avcall(av_alist* l)
57
 
{
58
 
  register __avword*    sp      __asm__("$sp");  /* C names for registers */
59
 
  register float        fret    __asm__("$f0");
60
 
  register double       dret    __asm__("$f0");
61
 
/*register __avword     iret1   __asm__("$2"); */
62
 
  register __avword     iret2   __asm__("$3");
63
 
  __avword space[__AV_ALIST_WORDS];     /* big space for child's stack frame */
64
 
  __avword *argframe = (__avword*)sp;   /* stack offset for argument list is 0 */
65
 
  int arglen = l->aptr - l->args;
66
 
  __avword i;
67
 
 
68
 
  if (l->farg_mask)
69
 
    { /* push leading float args */
70
 
      if (l->farg_mask & (1<<0))
71
 
        __asm__("lwc1 $f12,%1(%0)" : : "p" (l), "i" OFFSETOF(av_alist,farg[0]));
72
 
      if (l->farg_mask & (1<<1))
73
 
        __asm__("lwc1 $f13,%1(%0)" : : "p" (l), "i" OFFSETOF(av_alist,farg[1]));
74
 
      if (l->farg_mask & (1<<2))
75
 
        __asm__("lwc1 $f14,%1(%0)" : : "p" (l), "i" OFFSETOF(av_alist,farg[2]));
76
 
      if (l->farg_mask & (1<<3))
77
 
        __asm__("lwc1 $f15,%1(%0)" : : "p" (l), "i" OFFSETOF(av_alist,farg[3]));
78
 
      if (l->farg_mask & (1<<4))
79
 
        __asm__("lwc1 $f16,%1(%0)" : : "p" (l), "i" OFFSETOF(av_alist,farg[4]));
80
 
      if (l->farg_mask & (1<<5))
81
 
        __asm__("lwc1 $f17,%1(%0)" : : "p" (l), "i" OFFSETOF(av_alist,farg[5]));
82
 
      if (l->farg_mask & (1<<6))
83
 
        __asm__("lwc1 $f18,%1(%0)" : : "p" (l), "i" OFFSETOF(av_alist,farg[6]));
84
 
      if (l->farg_mask & (1<<7))
85
 
        __asm__("lwc1 $f19,%1(%0)" : : "p" (l), "i" OFFSETOF(av_alist,farg[7]));
86
 
    }
87
 
  if (l->darg_mask)
88
 
    { /* push leading double args */
89
 
      if (l->darg_mask & (1<<0))
90
 
        __asm__("ldc1 $f12,%1(%0)" : : "p" (l), "i" OFFSETOF(av_alist,args[0]));
91
 
      if (l->darg_mask & (1<<1))
92
 
        __asm__("ldc1 $f13,%1(%0)" : : "p" (l), "i" OFFSETOF(av_alist,args[1]));
93
 
      if (l->darg_mask & (1<<2))
94
 
        __asm__("ldc1 $f14,%1(%0)" : : "p" (l), "i" OFFSETOF(av_alist,args[2]));
95
 
      if (l->darg_mask & (1<<3))
96
 
        __asm__("ldc1 $f15,%1(%0)" : : "p" (l), "i" OFFSETOF(av_alist,args[3]));
97
 
      if (l->darg_mask & (1<<4))
98
 
        __asm__("ldc1 $f16,%1(%0)" : : "p" (l), "i" OFFSETOF(av_alist,args[4]));
99
 
      if (l->darg_mask & (1<<5))
100
 
        __asm__("ldc1 $f17,%1(%0)" : : "p" (l), "i" OFFSETOF(av_alist,args[5]));
101
 
      if (l->darg_mask & (1<<6))
102
 
        __asm__("ldc1 $f18,%1(%0)" : : "p" (l), "i" OFFSETOF(av_alist,args[6]));
103
 
      if (l->darg_mask & (1<<7))
104
 
        __asm__("ldc1 $f19,%1(%0)" : : "p" (l), "i" OFFSETOF(av_alist,args[7]));
105
 
    }
106
 
 
107
 
  for (i = 8; i < arglen; i++)          /* push excess function args */
108
 
    argframe[i-8] = l->args[i];
109
 
 
110
 
                                        /* call function with 1st 8 args */
111
 
  __asm__ __volatile__ ("ld $4,%0" : : "m" (l->args[0]) : "$4"); /* arg1 = l->args[0]; */
112
 
  __asm__ __volatile__ ("ld $5,%0" : : "m" (l->args[1]) : "$5"); /* arg1 = l->args[1]; */
113
 
  __asm__ __volatile__ ("ld $6,%0" : : "m" (l->args[2]) : "$6"); /* arg1 = l->args[2]; */
114
 
  __asm__ __volatile__ ("ld $7,%0" : : "m" (l->args[3]) : "$7"); /* arg1 = l->args[3]; */
115
 
  __asm__ __volatile__ ("ld $8,%0" : : "m" (l->args[4]) : "$8"); /* arg1 = l->args[4]; */
116
 
  __asm__ __volatile__ ("ld $9,%0" : : "m" (l->args[5]) : "$9"); /* arg1 = l->args[5]; */
117
 
  __asm__ __volatile__ ("ld $10,%0" : : "m" (l->args[6]) : "$10"); /* arg1 = l->args[6]; */
118
 
  __asm__ __volatile__ ("ld $11,%0" : : "m" (l->args[7]) : "$11"); /* arg1 = l->args[7]; */
119
 
  i = (*(t9 = l->func))();
120
 
 
121
 
  /* save return value */
122
 
  if (l->rtype == __AVvoid) {
123
 
  } else
124
 
  if (l->rtype == __AVword) {
125
 
    RETURN(__avword, i);
126
 
  } else
127
 
  if (l->rtype == __AVchar) {
128
 
    RETURN(char, i);
129
 
  } else
130
 
  if (l->rtype == __AVschar) {
131
 
    RETURN(signed char, i);
132
 
  } else
133
 
  if (l->rtype == __AVuchar) {
134
 
    RETURN(unsigned char, i);
135
 
  } else
136
 
  if (l->rtype == __AVshort) {
137
 
    RETURN(short, i);
138
 
  } else
139
 
  if (l->rtype == __AVushort) {
140
 
    RETURN(unsigned short, i);
141
 
  } else
142
 
  if (l->rtype == __AVint) {
143
 
    RETURN(int, i);
144
 
  } else
145
 
  if (l->rtype == __AVuint) {
146
 
    RETURN(unsigned int, i);
147
 
  } else
148
 
  if (l->rtype == __AVlong) {
149
 
    RETURN(long, i);
150
 
  } else
151
 
  if (l->rtype == __AVulong) {
152
 
    RETURN(unsigned long, i);
153
 
  } else
154
 
  if (l->rtype == __AVlonglong) {
155
 
    RETURN(long long, i);
156
 
  } else
157
 
  if (l->rtype == __AVulonglong) {
158
 
    RETURN(unsigned long long, i);
159
 
  } else
160
 
  if (l->rtype == __AVfloat) {
161
 
    RETURN(float, fret);
162
 
  } else
163
 
  if (l->rtype == __AVdouble) {
164
 
    RETURN(double, dret);
165
 
  } else
166
 
  if (l->rtype == __AVvoidp) {
167
 
    RETURN(void*, i);
168
 
  } else
169
 
  if (l->rtype == __AVstruct) {
170
 
    if (l->flags & __AV_PCC_STRUCT_RETURN) {
171
 
      /* pcc struct return convention: need a  *(TYPE*)l->raddr = *(TYPE*)i;  */
172
 
      if (l->rsize == sizeof(char)) {
173
 
        RETURN(char, *(char*)i);
174
 
      } else
175
 
      if (l->rsize == sizeof(short)) {
176
 
        RETURN(short, *(short*)i);
177
 
      } else
178
 
      if (l->rsize == sizeof(int)) {
179
 
        RETURN(int, *(int*)i);
180
 
      } else
181
 
      if (l->rsize == sizeof(long)) {
182
 
        RETURN(long, *(long*)i);
183
 
      } else {
184
 
        int n = (l->rsize + sizeof(__avword)-1)/sizeof(__avword);
185
 
        while (--n >= 0)
186
 
          ((__avword*)l->raddr)[n] = ((__avword*)i)[n];
187
 
      }
188
 
    } else {
189
 
      /* normal struct return convention */
190
 
      if (l->flags & __AV_REGISTER_STRUCT_RETURN) {
191
 
        if (l->flags & __AV_GCC_STRUCT_RETURN) {
192
 
          /* gcc returns structs of size 1,2,4,8 in registers. */
193
 
          if (l->rsize == sizeof(char)) {
194
 
            RETURN(char, i);
195
 
          } else
196
 
          if (l->rsize == sizeof(short)) {
197
 
            RETURN(short, i);
198
 
          } else
199
 
          if (l->rsize == sizeof(int)) {
200
 
            RETURN(int, i);
201
 
          } else
202
 
          if (l->rsize == sizeof(long)) {
203
 
            RETURN(long, i);
204
 
          }
205
 
        } else {
206
 
          /* cc returns structs of size <= 16 in registers. */
207
 
          if (l->rsize > 0 && l->rsize <= 16) {
208
 
            if (l->rsize == 1) {
209
 
              ((unsigned char *)l->raddr)[0] = (unsigned char)(i>>56);
210
 
            } else
211
 
            if (l->rsize == 2) {
212
 
              ((unsigned char *)l->raddr)[0] = (unsigned char)(i>>56);
213
 
              ((unsigned char *)l->raddr)[1] = (unsigned char)(i>>48);
214
 
            } else
215
 
            if (l->rsize == 3) {
216
 
              ((unsigned char *)l->raddr)[0] = (unsigned char)(i>>56);
217
 
              ((unsigned char *)l->raddr)[1] = (unsigned char)(i>>48);
218
 
              ((unsigned char *)l->raddr)[2] = (unsigned char)(i>>40);
219
 
            } else
220
 
            if (l->rsize == 4) {
221
 
              ((unsigned char *)l->raddr)[0] = (unsigned char)(i>>56);
222
 
              ((unsigned char *)l->raddr)[1] = (unsigned char)(i>>48);
223
 
              ((unsigned char *)l->raddr)[2] = (unsigned char)(i>>40);
224
 
              ((unsigned char *)l->raddr)[3] = (unsigned char)(i>>32);
225
 
            } else
226
 
            if (l->rsize == 5) {
227
 
              ((unsigned char *)l->raddr)[0] = (unsigned char)(i>>56);
228
 
              ((unsigned char *)l->raddr)[1] = (unsigned char)(i>>48);
229
 
              ((unsigned char *)l->raddr)[2] = (unsigned char)(i>>40);
230
 
              ((unsigned char *)l->raddr)[3] = (unsigned char)(i>>32);
231
 
              ((unsigned char *)l->raddr)[4] = (unsigned char)(i>>24);
232
 
            } else
233
 
            if (l->rsize == 6) {
234
 
              ((unsigned char *)l->raddr)[0] = (unsigned char)(i>>56);
235
 
              ((unsigned char *)l->raddr)[1] = (unsigned char)(i>>48);
236
 
              ((unsigned char *)l->raddr)[2] = (unsigned char)(i>>40);
237
 
              ((unsigned char *)l->raddr)[3] = (unsigned char)(i>>32);
238
 
              ((unsigned char *)l->raddr)[4] = (unsigned char)(i>>24);
239
 
              ((unsigned char *)l->raddr)[5] = (unsigned char)(i>>16);
240
 
            } else
241
 
            if (l->rsize == 7) {
242
 
              ((unsigned char *)l->raddr)[0] = (unsigned char)(i>>56);
243
 
              ((unsigned char *)l->raddr)[1] = (unsigned char)(i>>48);
244
 
              ((unsigned char *)l->raddr)[2] = (unsigned char)(i>>40);
245
 
              ((unsigned char *)l->raddr)[3] = (unsigned char)(i>>32);
246
 
              ((unsigned char *)l->raddr)[4] = (unsigned char)(i>>24);
247
 
              ((unsigned char *)l->raddr)[5] = (unsigned char)(i>>16);
248
 
              ((unsigned char *)l->raddr)[6] = (unsigned char)(i>>8);
249
 
            } else
250
 
            if (l->rsize >= 8 && l->rsize <= 16) {
251
 
              ((unsigned char *)l->raddr)[0] = (unsigned char)(i>>56);
252
 
              ((unsigned char *)l->raddr)[1] = (unsigned char)(i>>48);
253
 
              ((unsigned char *)l->raddr)[2] = (unsigned char)(i>>40);
254
 
              ((unsigned char *)l->raddr)[3] = (unsigned char)(i>>32);
255
 
              ((unsigned char *)l->raddr)[4] = (unsigned char)(i>>24);
256
 
              ((unsigned char *)l->raddr)[5] = (unsigned char)(i>>16);
257
 
              ((unsigned char *)l->raddr)[6] = (unsigned char)(i>>8);
258
 
              ((unsigned char *)l->raddr)[7] = (unsigned char)(i);
259
 
              if (l->rsize == 8) {
260
 
              } else
261
 
              if (l->rsize == 9) {
262
 
                ((unsigned char *)l->raddr)[8+0] = (unsigned char)(iret2>>56);
263
 
              } else
264
 
              if (l->rsize == 10) {
265
 
                ((unsigned char *)l->raddr)[8+0] = (unsigned char)(iret2>>56);
266
 
                ((unsigned char *)l->raddr)[8+1] = (unsigned char)(iret2>>48);
267
 
              } else
268
 
              if (l->rsize == 11) {
269
 
                ((unsigned char *)l->raddr)[8+0] = (unsigned char)(iret2>>56);
270
 
                ((unsigned char *)l->raddr)[8+1] = (unsigned char)(iret2>>48);
271
 
                ((unsigned char *)l->raddr)[8+2] = (unsigned char)(iret2>>40);
272
 
              } else
273
 
              if (l->rsize == 12) {
274
 
                ((unsigned char *)l->raddr)[8+0] = (unsigned char)(iret2>>56);
275
 
                ((unsigned char *)l->raddr)[8+1] = (unsigned char)(iret2>>48);
276
 
                ((unsigned char *)l->raddr)[8+2] = (unsigned char)(iret2>>40);
277
 
                ((unsigned char *)l->raddr)[8+3] = (unsigned char)(iret2>>32);
278
 
              } else
279
 
              if (l->rsize == 13) {
280
 
                ((unsigned char *)l->raddr)[8+0] = (unsigned char)(iret2>>56);
281
 
                ((unsigned char *)l->raddr)[8+1] = (unsigned char)(iret2>>48);
282
 
                ((unsigned char *)l->raddr)[8+2] = (unsigned char)(iret2>>40);
283
 
                ((unsigned char *)l->raddr)[8+3] = (unsigned char)(iret2>>32);
284
 
                ((unsigned char *)l->raddr)[8+4] = (unsigned char)(iret2>>24);
285
 
              } else
286
 
              if (l->rsize == 14) {
287
 
                ((unsigned char *)l->raddr)[8+0] = (unsigned char)(iret2>>56);
288
 
                ((unsigned char *)l->raddr)[8+1] = (unsigned char)(iret2>>48);
289
 
                ((unsigned char *)l->raddr)[8+2] = (unsigned char)(iret2>>40);
290
 
                ((unsigned char *)l->raddr)[8+3] = (unsigned char)(iret2>>32);
291
 
                ((unsigned char *)l->raddr)[8+4] = (unsigned char)(iret2>>24);
292
 
                ((unsigned char *)l->raddr)[8+5] = (unsigned char)(iret2>>16);
293
 
              } else
294
 
              if (l->rsize == 15) {
295
 
                ((unsigned char *)l->raddr)[8+0] = (unsigned char)(iret2>>56);
296
 
                ((unsigned char *)l->raddr)[8+1] = (unsigned char)(iret2>>48);
297
 
                ((unsigned char *)l->raddr)[8+2] = (unsigned char)(iret2>>40);
298
 
                ((unsigned char *)l->raddr)[8+3] = (unsigned char)(iret2>>32);
299
 
                ((unsigned char *)l->raddr)[8+4] = (unsigned char)(iret2>>24);
300
 
                ((unsigned char *)l->raddr)[8+5] = (unsigned char)(iret2>>16);
301
 
                ((unsigned char *)l->raddr)[8+6] = (unsigned char)(iret2>>8);
302
 
              } else
303
 
              if (l->rsize == 16) {
304
 
                ((unsigned char *)l->raddr)[8+0] = (unsigned char)(iret2>>56);
305
 
                ((unsigned char *)l->raddr)[8+1] = (unsigned char)(iret2>>48);
306
 
                ((unsigned char *)l->raddr)[8+2] = (unsigned char)(iret2>>40);
307
 
                ((unsigned char *)l->raddr)[8+3] = (unsigned char)(iret2>>32);
308
 
                ((unsigned char *)l->raddr)[8+4] = (unsigned char)(iret2>>24);
309
 
                ((unsigned char *)l->raddr)[8+5] = (unsigned char)(iret2>>16);
310
 
                ((unsigned char *)l->raddr)[8+6] = (unsigned char)(iret2>>8);
311
 
                ((unsigned char *)l->raddr)[8+7] = (unsigned char)(iret2);
312
 
              }
313
 
            }
314
 
          }
315
 
        }
316
 
      }
317
 
    }
318
 
  }
319
 
  return 0;
320
 
}
321
 
 
322
 
#endif /*_avcall_mips64_c */