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

« back to all changes in this revision

Viewing changes to ffcall/avcall/avcall-hppa.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_hppa_c                          /*-*- C -*-*/
2
 
#define _avcall_hppa_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 HP Precision Architecture 1.0 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
 
  HPPA Argument Passing Conventions:
21
 
 
22
 
  All arguments, except the first 4 words, are passed on the stack
23
 
  - growing down! - with word alignment. Doubles take two words and force
24
 
  double alignment. Small structures args are passed as true structures
25
 
  embedded in the argument stack. They force double alignment and - if they
26
 
  don't fit entirely in the 4 register words - are passed in memory.
27
 
  The first 2 words are passed like this:
28
 
    %r26 = first integer arg, %r25 = second integer arg, or
29
 
    %r26 = high word of double arg, %r25 = low word of double arg.
30
 
  Similarly for the next 2 words, passed in %r24 and %r23.
31
 
  Note that other calling conventions would be in effect if we would call
32
 
  an explicitly named function!
33
 
 
34
 
  To return a structure, the called function copies the return value to
35
 
  the address supplied in register "%r28".
36
 
 
37
 
  It is forbidden to modify the stack pointer.
38
 
 
39
 
  Compile this routine with gcc -O2 -fomit-frame-pointer to get the right
40
 
  register variables, then replace the -120 in the second save statement
41
 
  "stw %r3,-120(0,%r30)" by -1060, or use the assembler version.
42
 
  ----------------------------------------------------------------------*/
43
 
#include "avcall.h.in"
44
 
 
45
 
#define RETURN(TYPE,VAL)        (*(TYPE*)l->raddr = (TYPE)(VAL))
46
 
 
47
 
/* This declaration tells gcc not to modify %r28. */
48
 
register __avword*      sret    __asm__("%r28");  /* structure return pointer */
49
 
 
50
 
int
51
 
__builtin_avcall(av_alist* l)
52
 
{
53
 
  register __avword*    sp      __asm__("%r30");  /* C names for registers */
54
 
  register float        fret    __asm__("%fr4");
55
 
  register double       dret    __asm__("%fr4");
56
 
/*register __avword     iret1   __asm__("%r28"); */
57
 
  register __avword     iret2   __asm__("%r29");
58
 
 
59
 
  __avword space[__AV_ALIST_WORDS];     /* space for callee's stack frame */
60
 
  __avword* argframe = sp - 8;          /* stack offset for argument list */
61
 
  int arglen = &l->args[__AV_ALIST_WORDS] - l->aptr;
62
 
  __avword i;
63
 
 
64
 
  {
65
 
    int i;
66
 
    for (i = -arglen; i < -4; i++)      /* push function args onto stack */
67
 
      argframe[i] = l->args[__AV_ALIST_WORDS+i];
68
 
  }
69
 
 
70
 
  if (l->rtype == __AVstruct)           /* push struct return address */
71
 
    sret = l->raddr;
72
 
 
73
 
                                /* call function, pass 4 args in registers */
74
 
  i = (*l->func)(l->args[__AV_ALIST_WORDS-1], l->args[__AV_ALIST_WORDS-2],
75
 
                 l->args[__AV_ALIST_WORDS-3], l->args[__AV_ALIST_WORDS-4]);
76
 
 
77
 
  /* save return value */
78
 
  if (l->rtype == __AVvoid) {
79
 
  } else
80
 
  if (l->rtype == __AVword) {
81
 
    RETURN(__avword, i);
82
 
  } else
83
 
  if (l->rtype == __AVchar) {
84
 
    RETURN(char, i);
85
 
  } else
86
 
  if (l->rtype == __AVschar) {
87
 
    RETURN(signed char, i);
88
 
  } else
89
 
  if (l->rtype == __AVuchar) {
90
 
    RETURN(unsigned char, i);
91
 
  } else
92
 
  if (l->rtype == __AVshort) {
93
 
    RETURN(short, i);
94
 
  } else
95
 
  if (l->rtype == __AVushort) {
96
 
    RETURN(unsigned short, i);
97
 
  } else
98
 
  if (l->rtype == __AVint) {
99
 
    RETURN(int, i);
100
 
  } else
101
 
  if (l->rtype == __AVuint) {
102
 
    RETURN(unsigned int, i);
103
 
  } else
104
 
  if (l->rtype == __AVlong) {
105
 
    RETURN(long, i);
106
 
  } else
107
 
  if (l->rtype == __AVulong) {
108
 
    RETURN(unsigned long, i);
109
 
  } else
110
 
  if (l->rtype == __AVlonglong || l->rtype == __AVulonglong) {
111
 
    ((__avword*)l->raddr)[0] = i;
112
 
    ((__avword*)l->raddr)[1] = iret2;
113
 
  } else
114
 
  if (l->rtype == __AVfloat) {
115
 
    RETURN(float, fret);
116
 
  } else
117
 
  if (l->rtype == __AVdouble) {
118
 
    RETURN(double, dret);
119
 
  } else
120
 
  if (l->rtype == __AVvoidp) {
121
 
    RETURN(void*, i);
122
 
  } else
123
 
  if (l->rtype == __AVstruct) {
124
 
    if (l->flags & __AV_PCC_STRUCT_RETURN) {
125
 
      /* pcc struct return convention: need a  *(TYPE*)l->raddr = *(TYPE*)i;  */
126
 
      if (l->rsize == sizeof(char)) {
127
 
        RETURN(char, *(char*)i);
128
 
      } else
129
 
      if (l->rsize == sizeof(short)) {
130
 
        RETURN(short, *(short*)i);
131
 
      } else
132
 
      if (l->rsize == sizeof(int)) {
133
 
        RETURN(int, *(int*)i);
134
 
      } else
135
 
      if (l->rsize == sizeof(double)) {
136
 
        ((int*)l->raddr)[0] = ((int*)i)[0];
137
 
        ((int*)l->raddr)[1] = ((int*)i)[1];
138
 
      } else {
139
 
        int n = (l->rsize + sizeof(__avword)-1)/sizeof(__avword);
140
 
        while (--n >= 0)
141
 
          ((__avword*)l->raddr)[n] = ((__avword*)i)[n];
142
 
      }
143
 
    } else {
144
 
      /* normal struct return convention */
145
 
      if (l->flags & __AV_SMALL_STRUCT_RETURN) {
146
 
        if (l->flags & __AV_OLDGCC_STRUCT_RETURN) {
147
 
          /* gcc <= 2.6.3 returns structs of size 1,2,4 in registers. */
148
 
          if (l->rsize == sizeof(char)) {
149
 
            RETURN(char, i);
150
 
          } else
151
 
          if (l->rsize == sizeof(short)) {
152
 
            RETURN(short, i);
153
 
          } else
154
 
          if (l->rsize == sizeof(int)) {
155
 
            RETURN(int, i);
156
 
          }
157
 
        } else {
158
 
          /* cc, c89 and gcc >= 2.7 return structs of size <= 8 in registers. */
159
 
          if (l->rsize == 1) {
160
 
            ((unsigned char *)l->raddr)[0] = (unsigned char)(i);
161
 
          } else
162
 
          if (l->rsize == 2) {
163
 
            ((unsigned char *)l->raddr)[0] = (unsigned char)(i>>8);
164
 
            ((unsigned char *)l->raddr)[1] = (unsigned char)(i);
165
 
          } else
166
 
          if (l->rsize == 3) {
167
 
            ((unsigned char *)l->raddr)[0] = (unsigned char)(i>>16);
168
 
            ((unsigned char *)l->raddr)[1] = (unsigned char)(i>>8);
169
 
            ((unsigned char *)l->raddr)[2] = (unsigned char)(i);
170
 
          } else
171
 
          if (l->rsize == 4) {
172
 
            ((unsigned char *)l->raddr)[0] = (unsigned char)(i>>24);
173
 
            ((unsigned char *)l->raddr)[1] = (unsigned char)(i>>16);
174
 
            ((unsigned char *)l->raddr)[2] = (unsigned char)(i>>8);
175
 
            ((unsigned char *)l->raddr)[3] = (unsigned char)(i);
176
 
          } else
177
 
          if (l->rsize == 5) {
178
 
            ((unsigned char *)l->raddr)[0] = (unsigned char)(i>>24);
179
 
            ((unsigned char *)l->raddr)[1] = (unsigned char)(i>>16);
180
 
            ((unsigned char *)l->raddr)[2] = (unsigned char)(i>>8);
181
 
            ((unsigned char *)l->raddr)[3] = (unsigned char)(i);
182
 
            ((unsigned char *)l->raddr)[4] = (unsigned char)(iret2);
183
 
          } else
184
 
          if (l->rsize == 6) {
185
 
            ((unsigned char *)l->raddr)[0] = (unsigned char)(i>>24);
186
 
            ((unsigned char *)l->raddr)[1] = (unsigned char)(i>>16);
187
 
            ((unsigned char *)l->raddr)[2] = (unsigned char)(i>>8);
188
 
            ((unsigned char *)l->raddr)[3] = (unsigned char)(i);
189
 
            ((unsigned char *)l->raddr)[4] = (unsigned char)(iret2>>8);
190
 
            ((unsigned char *)l->raddr)[5] = (unsigned char)(iret2);
191
 
          } else
192
 
          if (l->rsize == 7) {
193
 
            ((unsigned char *)l->raddr)[0] = (unsigned char)(i>>24);
194
 
            ((unsigned char *)l->raddr)[1] = (unsigned char)(i>>16);
195
 
            ((unsigned char *)l->raddr)[2] = (unsigned char)(i>>8);
196
 
            ((unsigned char *)l->raddr)[3] = (unsigned char)(i);
197
 
            ((unsigned char *)l->raddr)[4] = (unsigned char)(iret2>>16);
198
 
            ((unsigned char *)l->raddr)[5] = (unsigned char)(iret2>>8);
199
 
            ((unsigned char *)l->raddr)[6] = (unsigned char)(iret2);
200
 
          } else
201
 
          if (l->rsize == 8) {
202
 
            ((unsigned char *)l->raddr)[0] = (unsigned char)(i>>24);
203
 
            ((unsigned char *)l->raddr)[1] = (unsigned char)(i>>16);
204
 
            ((unsigned char *)l->raddr)[2] = (unsigned char)(i>>8);
205
 
            ((unsigned char *)l->raddr)[3] = (unsigned char)(i);
206
 
            ((unsigned char *)l->raddr)[4] = (unsigned char)(iret2>>24);
207
 
            ((unsigned char *)l->raddr)[5] = (unsigned char)(iret2>>16);
208
 
            ((unsigned char *)l->raddr)[6] = (unsigned char)(iret2>>8);
209
 
            ((unsigned char *)l->raddr)[7] = (unsigned char)(iret2);
210
 
          }
211
 
        }
212
 
      }
213
 
    }
214
 
  }
215
 
  return 0;
216
 
}
217
 
 
218
 
#endif /*_avcall_hppa_c */