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

« back to all changes in this revision

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