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

« back to all changes in this revision

Viewing changes to ffcall/avcall/avcall-arm.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_arm_c                           /*-*- C -*-*/
2
 
#define _avcall_arm_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 Acorn Risc Maschine 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
 
  ARM Argument Passing Conventions:
21
 
 
22
 
  All arguments, except the first 4 words, are passed on the stack with
23
 
  word alignment. Doubles take two words. Structure args are passed as
24
 
  true structures embedded in the argument stack. To return a structure,
25
 
  the called function copies the return value to the address supplied
26
 
  in register "%r0".
27
 
 
28
 
  Compile this routine with gcc -O (or -O2 or -g -O) to get the right
29
 
  register variables, or use the assembler version.
30
 
  ----------------------------------------------------------------------*/
31
 
#include "avcall.h.in"
32
 
 
33
 
#define RETURN(TYPE,VAL)        (*(TYPE*)l->raddr = (TYPE)(VAL))
34
 
 
35
 
int
36
 
__builtin_avcall(av_alist* l)
37
 
{
38
 
  register __avword*    sp      __asm__("r13");  /* C names for registers */
39
 
/*register __avword     iret    __asm__("r0"); */
40
 
  register __avword     iret2   __asm__("r1");
41
 
  register float        fret    __asm__("r0");  /* r0 */
42
 
  register double       dret    __asm__("r0");  /* r0,r1 */
43
 
 
44
 
  __avword space[__AV_ALIST_WORDS];     /* space for callee's stack frame */
45
 
  __avword* argframe = sp;              /* stack offset for argument list */
46
 
  int arglen = l->aptr - l->args;
47
 
  __avword i;
48
 
 
49
 
  for (i = 4; i < arglen; i++)          /* push function args onto stack */
50
 
    argframe[i-4] = l->args[i];
51
 
 
52
 
                                /* call function, pass 4 args in registers */
53
 
  i = (*l->func)(l->args[0], l->args[1], l->args[2], l->args[3]);
54
 
 
55
 
  /* save return value */
56
 
  if (l->rtype == __AVvoid) {
57
 
  } else
58
 
  if (l->rtype == __AVword) {
59
 
    RETURN(__avword, i);
60
 
  } else
61
 
  if (l->rtype == __AVchar) {
62
 
    RETURN(char, i);
63
 
  } else
64
 
  if (l->rtype == __AVschar) {
65
 
    RETURN(signed char, i);
66
 
  } else
67
 
  if (l->rtype == __AVuchar) {
68
 
    RETURN(unsigned char, i);
69
 
  } else
70
 
  if (l->rtype == __AVshort) {
71
 
    RETURN(short, i);
72
 
  } else
73
 
  if (l->rtype == __AVushort) {
74
 
    RETURN(unsigned short, i);
75
 
  } else
76
 
  if (l->rtype == __AVint) {
77
 
    RETURN(int, i);
78
 
  } else
79
 
  if (l->rtype == __AVuint) {
80
 
    RETURN(unsigned int, i);
81
 
  } else
82
 
  if (l->rtype == __AVlong) {
83
 
    RETURN(long, i);
84
 
  } else
85
 
  if (l->rtype == __AVulong) {
86
 
    RETURN(unsigned long, i);
87
 
  } else
88
 
  if (l->rtype == __AVlonglong || l->rtype == __AVulonglong) {
89
 
    ((__avword*)l->raddr)[0] = i;
90
 
    ((__avword*)l->raddr)[1] = iret2;
91
 
  } else
92
 
  if (l->rtype == __AVfloat) {
93
 
    RETURN(float, fret);
94
 
  } else
95
 
  if (l->rtype == __AVdouble) {
96
 
    RETURN(double, dret);
97
 
  } else
98
 
  if (l->rtype == __AVvoidp) {
99
 
    RETURN(void*, i);
100
 
  } else
101
 
  if (l->rtype == __AVstruct) {
102
 
    /* NB: On arm, all structure sizes are divisible by 4. */
103
 
    if (l->flags & __AV_PCC_STRUCT_RETURN) {
104
 
      /* pcc struct return convention: need a  *(TYPE*)l->raddr = *(TYPE*)i;  */
105
 
      if (l->rsize == sizeof(char)) { /* can't occur */
106
 
        RETURN(char, *(char*)i);
107
 
      } else
108
 
      if (l->rsize == sizeof(short)) { /* can't occur */
109
 
        RETURN(short, *(short*)i);
110
 
      } else
111
 
      if (l->rsize == sizeof(int)) {
112
 
        RETURN(int, *(int*)i);
113
 
      } else
114
 
      if (l->rsize == sizeof(double)) {
115
 
        ((int*)l->raddr)[0] = ((int*)i)[0];
116
 
        ((int*)l->raddr)[1] = ((int*)i)[1];
117
 
      } else {
118
 
        int n = (l->rsize+3)/4;
119
 
        while (--n >= 0)
120
 
          ((__avword*)l->raddr)[n] = ((__avword*)i)[n];
121
 
      }
122
 
    } else {
123
 
      /* normal struct return convention */
124
 
      if (l->flags & __AV_REGISTER_STRUCT_RETURN) {
125
 
        if (l->rsize == sizeof(char)) { /* can't occur */
126
 
          RETURN(char, i);
127
 
        } else
128
 
        if (l->rsize == sizeof(short)) { /* can't occur */
129
 
          RETURN(short, i);
130
 
        } else
131
 
        if (l->rsize == sizeof(int)) {
132
 
          RETURN(int, i);
133
 
        } else
134
 
        if (l->rsize == 2*sizeof(__avword)) {
135
 
          ((__avword*)l->raddr)[0] = i;
136
 
          ((__avword*)l->raddr)[1] = iret2;
137
 
        }
138
 
      }
139
 
    }
140
 
  }
141
 
  return 0;
142
 
}
143
 
 
144
 
#endif /*_avcall_arm_c */