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

« back to all changes in this revision

Viewing changes to ffcall/avcall/avcall-s390.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_s390_c                          /*-*- C -*-*/
2
 
#define _avcall_s390_c
3
 
/**
4
 
  Copyright 1993 Bill Triggs, <Bill.Triggs@inrialpes.fr>
5
 
  Copyright 1995-1999 Bruno Haible, <bruno@clisp.org>
6
 
  Copyright 2001 Gerhard Tonn, <gt@debian.org>
7
 
 
8
 
  This is free software distributed under the GNU General Public
9
 
  Licence described in the file COPYING. Contact the author if
10
 
  you don't have this or can't live with it. There is ABSOLUTELY
11
 
  NO WARRANTY, explicit or implied, on this software.
12
 
**/
13
 
/*----------------------------------------------------------------------
14
 
 
15
 
  Foreign function interface for an IBM S/390 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
 
  S390 Argument Passing Conventions:
21
 
 
22
 
  All arguments, except the first 5 words, are passed on the stack with
23
 
  word alignment. Doubles take two words. The first 2 doubles and floats
24
 
  are also passed in floating-point-registers.
25
 
  To return a structure, the called function copies the value to space
26
 
  pointed to by its first argument, and all other arguments are shifted
27
 
  down by one.
28
 
 
29
 
  Compile this routine with gcc -O2 to get the right register variables.
30
 
  For other compilers use the pre-compiled assembler version.
31
 
  ----------------------------------------------------------------------*/
32
 
#include "avcall.h"
33
 
 
34
 
#define STACK_OFFSET 24
35
 
 
36
 
#define RETURN(TYPE,VAL)        (*(TYPE*)l->raddr = (TYPE)(VAL))
37
 
 
38
 
register float  farg1   __asm__("f0");
39
 
register float  farg2   __asm__("f2");
40
 
register double darg1   __asm__("f0");
41
 
register double darg2   __asm__("f2");
42
 
 
43
 
int
44
 
__builtin_avcall(av_alist* l)
45
 
{
46
 
  register __avword*    sp      __asm__("r15");  /* C names for registers */
47
 
/*register __avword     iret    __asm__("r2"); */
48
 
  register __avword     iret2   __asm__("r3");
49
 
  register float        fret    __asm__("f0");
50
 
  register double       dret    __asm__("f0");
51
 
 
52
 
  __avword space[__AV_ALIST_WORDS];     /* space for callee's stack frame */
53
 
  __avword* argframe = sp + STACK_OFFSET;/* stack offset for argument list */
54
 
  int arglen = l->aptr - l->args;
55
 
  int farglen = l->faptr - l->fargs;
56
 
  int iargwords = (arglen-l->fargwords)<5?arglen-l->fargwords:5;
57
 
  __avword i;
58
 
 
59
 
  for (i = iargwords; i < arglen; i++) /* push function args onto stack */
60
 
   argframe[i-iargwords] = l->args[i];
61
 
 
62
 
  /* pass first 2 floating-point args in registers */
63
 
  if (farglen == 1) {
64
 
    if(l->fargsused[0])  farg1 = l->fargs[0]; else darg1 = l->dargs[0];
65
 
   }
66
 
  else if (farglen == 2) {
67
 
    if(l->fargsused[0] && l->fargsused[1]) {
68
 
       farg1 = l->fargs[0]; farg2 = l->fargs[1];
69
 
    }
70
 
    else if(l->fargsused[0] && !l->fargsused[1]) {
71
 
       farg1 = l->fargs[0]; darg2 = l->dargs[1];
72
 
    }
73
 
    else if(!l->fargsused[0] && l->fargsused[1]) {
74
 
       darg1 = l->dargs[0]; farg2 = l->fargs[1];
75
 
    }
76
 
    else if(!l->fargsused[0] && !l->fargsused[1]) {
77
 
       darg1 = l->dargs[0]; darg2 = l->dargs[1];
78
 
    }
79
 
  }
80
 
 
81
 
                                /* call function, pass 5 args in registers */
82
 
  i = (*l->func)(l->args[0], l->args[1], l->args[2], l->args[3],
83
 
                 l->args[4]);
84
 
 
85
 
  /* save return value */
86
 
  if (l->rtype == __AVvoid) {
87
 
  } else
88
 
  if (l->rtype == __AVword) {
89
 
    RETURN(__avword, i);
90
 
  } else
91
 
  if (l->rtype == __AVchar) {
92
 
    RETURN(char, i);
93
 
  } else
94
 
  if (l->rtype == __AVschar) {
95
 
    RETURN(signed char, i);
96
 
  } else
97
 
  if (l->rtype == __AVuchar) {
98
 
    RETURN(unsigned char, i);
99
 
  } else
100
 
  if (l->rtype == __AVshort) {
101
 
    RETURN(short, i);
102
 
  } else
103
 
  if (l->rtype == __AVushort) {
104
 
    RETURN(unsigned short, i);
105
 
  } else
106
 
  if (l->rtype == __AVint) {
107
 
    RETURN(int, i);
108
 
  } else
109
 
  if (l->rtype == __AVuint) {
110
 
    RETURN(unsigned int, i);
111
 
  } else
112
 
  if (l->rtype == __AVlong) {
113
 
    RETURN(long, i);
114
 
  } else
115
 
  if (l->rtype == __AVulong) {
116
 
    RETURN(unsigned long, i);
117
 
  } else
118
 
  if (l->rtype == __AVlonglong || l->rtype == __AVulonglong) {
119
 
    ((__avword*)l->raddr)[0] = i;
120
 
    ((__avword*)l->raddr)[1] = iret2;
121
 
  } else
122
 
  if (l->rtype == __AVfloat) {
123
 
    RETURN(float, fret);
124
 
  } else
125
 
  if (l->rtype == __AVdouble) {
126
 
    RETURN(double, dret);
127
 
  } else
128
 
  if (l->rtype == __AVvoidp) {
129
 
    RETURN(void*, i);
130
 
  } else
131
 
  if (l->rtype == __AVstruct) {
132
 
    if (l->flags & __AV_PCC_STRUCT_RETURN) {
133
 
      /* pcc struct return convention: need a  *(TYPE*)l->raddr = *(TYPE*)i;  */
134
 
      if (l->rsize == sizeof(char)) {
135
 
        RETURN(char, *(char*)i);
136
 
      } else
137
 
      if (l->rsize == sizeof(short)) {
138
 
        RETURN(short, *(short*)i);
139
 
      } else
140
 
      if (l->rsize == sizeof(int)) {
141
 
        RETURN(int, *(int*)i);
142
 
      } else
143
 
      if (l->rsize == sizeof(double)) {
144
 
        ((int*)l->raddr)[0] = ((int*)i)[0];
145
 
        ((int*)l->raddr)[1] = ((int*)i)[1];
146
 
      } else {
147
 
        int n = (l->rsize + sizeof(__avword)-1)/sizeof(__avword);
148
 
        while (--n >= 0)
149
 
          ((__avword*)l->raddr)[n] = ((__avword*)i)[n];
150
 
      }
151
 
    } else {
152
 
      /* normal struct return convention */
153
 
      if (l->flags & __AV_REGISTER_STRUCT_RETURN) {
154
 
        if (l->rsize == sizeof(char)) {
155
 
          RETURN(char, i);
156
 
        } else
157
 
        if (l->rsize == sizeof(short)) {
158
 
          RETURN(short, i);
159
 
        } else
160
 
        if (l->rsize == sizeof(int)) {
161
 
          RETURN(int, i);
162
 
        } else
163
 
        if (l->rsize == 2*sizeof(__avword)) {
164
 
          ((__avword*)l->raddr)[0] = i;
165
 
          ((__avword*)l->raddr)[1] = iret2;
166
 
        }
167
 
      }
168
 
    }
169
 
  }
170
 
  return 0;
171
 
}
172
 
 
173
 
#endif /*_avcall_s390_c */