~ubuntu-branches/ubuntu/lucid/gauche-c-wrapper/lucid

« back to all changes in this revision

Viewing changes to libffi/src/m68k/ffi.c

  • Committer: Bazaar Package Importer
  • Author(s): NIIBE Yutaka
  • Date: 2008-04-07 09:15:03 UTC
  • Revision ID: james.westby@ubuntu.com-20080407091503-wu0h414koe95kj4i
Tags: upstream-0.5.2
ImportĀ upstreamĀ versionĀ 0.5.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -----------------------------------------------------------------------
 
2
   ffi.c
 
3
   
 
4
   m68k Foreign Function Interface 
 
5
   ----------------------------------------------------------------------- */
 
6
 
 
7
#include <ffi.h>
 
8
#include <ffi_common.h>
 
9
 
 
10
#include <stdlib.h>
 
11
 
 
12
/* ffi_prep_args is called by the assembly routine once stack space has
 
13
   been allocated for the function's arguments.  */
 
14
 
 
15
static void *
 
16
ffi_prep_args (void *stack, extended_cif *ecif)
 
17
{
 
18
  unsigned int i;
 
19
  void **p_argv;
 
20
  char *argp;
 
21
  ffi_type **p_arg;
 
22
  void *struct_value_ptr;
 
23
 
 
24
  argp = stack;
 
25
 
 
26
  if (ecif->cif->rtype->type == FFI_TYPE_STRUCT
 
27
      && ecif->cif->rtype->size > 8)
 
28
    struct_value_ptr = ecif->rvalue;
 
29
  else
 
30
    struct_value_ptr = NULL;
 
31
 
 
32
  p_argv = ecif->avalue;
 
33
 
 
34
  for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
 
35
       i != 0;
 
36
       i--, p_arg++)
 
37
    {
 
38
      size_t z;
 
39
 
 
40
      /* Align if necessary.  */
 
41
      if (((*p_arg)->alignment - 1) & (unsigned) argp)
 
42
        argp = (char *) ALIGN (argp, (*p_arg)->alignment);
 
43
 
 
44
          z = (*p_arg)->size;
 
45
          if (z < sizeof (int))
 
46
            {
 
47
              switch ((*p_arg)->type)
 
48
                {
 
49
                case FFI_TYPE_SINT8:
 
50
                  *(signed int *) argp = (signed int) *(SINT8 *) *p_argv;
 
51
                  break;
 
52
 
 
53
                case FFI_TYPE_UINT8:
 
54
                  *(unsigned int *) argp = (unsigned int) *(UINT8 *) *p_argv;
 
55
                  break;
 
56
 
 
57
                case FFI_TYPE_SINT16:
 
58
                  *(signed int *) argp = (signed int) *(SINT16 *) *p_argv;
 
59
                  break;
 
60
 
 
61
                case FFI_TYPE_UINT16:
 
62
                  *(unsigned int *) argp = (unsigned int) *(UINT16 *) *p_argv;
 
63
                  break;
 
64
 
 
65
                case FFI_TYPE_STRUCT:
 
66
                  memcpy (argp + sizeof (int) - z, *p_argv, z);
 
67
                  break;
 
68
 
 
69
                default:
 
70
                  FFI_ASSERT (0);
 
71
                }
 
72
              z = sizeof (int);
 
73
            }
 
74
          else
 
75
            memcpy (argp, *p_argv, z);
 
76
          p_argv++;
 
77
          argp += z;
 
78
    }
 
79
 
 
80
  return struct_value_ptr;
 
81
}
 
82
 
 
83
#define CIF_FLAGS_INT           1
 
84
#define CIF_FLAGS_DINT          2
 
85
#define CIF_FLAGS_FLOAT         4
 
86
#define CIF_FLAGS_DOUBLE        8
 
87
#define CIF_FLAGS_LDOUBLE       16
 
88
#define CIF_FLAGS_POINTER       32
 
89
#define CIF_FLAGS_STRUCT        64
 
90
 
 
91
/* Perform machine dependent cif processing */
 
92
ffi_status
 
93
ffi_prep_cif_machdep (ffi_cif *cif)
 
94
{
 
95
  /* Set the return type flag */
 
96
  switch (cif->rtype->type)
 
97
    {
 
98
    case FFI_TYPE_VOID:
 
99
      cif->flags = 0;
 
100
      break;
 
101
 
 
102
    case FFI_TYPE_STRUCT:
 
103
      if (cif->rtype->size > 4 && cif->rtype->size <= 8)
 
104
        cif->flags = CIF_FLAGS_DINT;
 
105
      else if (cif->rtype->size <= 4)
 
106
        cif->flags = CIF_FLAGS_STRUCT;
 
107
      else
 
108
        cif->flags = 0;
 
109
      break;
 
110
 
 
111
    case FFI_TYPE_FLOAT:
 
112
      cif->flags = CIF_FLAGS_FLOAT;
 
113
      break;
 
114
 
 
115
    case FFI_TYPE_DOUBLE:
 
116
      cif->flags = CIF_FLAGS_DOUBLE;
 
117
      break;
 
118
 
 
119
    case FFI_TYPE_LONGDOUBLE:
 
120
      cif->flags = CIF_FLAGS_LDOUBLE;
 
121
      break;
 
122
 
 
123
    case FFI_TYPE_POINTER:
 
124
      cif->flags = CIF_FLAGS_POINTER;
 
125
      break;
 
126
 
 
127
    case FFI_TYPE_SINT64:
 
128
    case FFI_TYPE_UINT64:
 
129
      cif->flags = CIF_FLAGS_DINT;
 
130
      break;
 
131
 
 
132
    default:
 
133
      cif->flags = CIF_FLAGS_INT;
 
134
      break;
 
135
    }
 
136
 
 
137
  return FFI_OK;
 
138
}
 
139
 
 
140
extern void ffi_call_SYSV (void *(*) (void *, extended_cif *), 
 
141
                           extended_cif *, 
 
142
                           unsigned, unsigned, unsigned,
 
143
                           void *, void (*fn) ());
 
144
 
 
145
void
 
146
ffi_call (ffi_cif *cif, void (*fn) (), void *rvalue, void **avalue)
 
147
{
 
148
  extended_cif ecif;
 
149
 
 
150
  ecif.cif = cif;
 
151
  ecif.avalue = avalue;
 
152
  
 
153
  /* If the return value is a struct and we don't have a return value
 
154
     address then we need to make one.  */
 
155
 
 
156
  if (rvalue == NULL
 
157
      && cif->rtype->type == FFI_TYPE_STRUCT
 
158
      && cif->rtype->size > 8)
 
159
    ecif.rvalue = alloca (cif->rtype->size);
 
160
  else
 
161
    ecif.rvalue = rvalue;
 
162
    
 
163
  
 
164
  switch (cif->abi) 
 
165
    {
 
166
    case FFI_SYSV:
 
167
      ffi_call_SYSV (ffi_prep_args, &ecif, cif->bytes, 
 
168
                     cif->flags, cif->rtype->size * 8,
 
169
                     ecif.rvalue, fn);
 
170
      break;
 
171
 
 
172
    default:
 
173
      FFI_ASSERT (0);
 
174
      break;
 
175
    }
 
176
}