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

« back to all changes in this revision

Viewing changes to libffi/src/arm/sysv.S

  • 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
   sysv.S - Copyright (c) 1998 Red Hat, Inc.
 
3
   
 
4
   ARM Foreign Function Interface 
 
5
 
 
6
   Permission is hereby granted, free of charge, to any person obtaining
 
7
   a copy of this software and associated documentation files (the
 
8
   ``Software''), to deal in the Software without restriction, including
 
9
   without limitation the rights to use, copy, modify, merge, publish,
 
10
   distribute, sublicense, and/or sell copies of the Software, and to
 
11
   permit persons to whom the Software is furnished to do so, subject to
 
12
   the following conditions:
 
13
 
 
14
   The above copyright notice and this permission notice shall be included
 
15
   in all copies or substantial portions of the Software.
 
16
 
 
17
   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
 
18
   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 
19
   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 
20
   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 
21
   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 
22
   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 
23
   OTHER DEALINGS IN THE SOFTWARE.
 
24
   ----------------------------------------------------------------------- */
 
25
 
 
26
#define LIBFFI_ASM      
 
27
#include <fficonfig.h>
 
28
#include <ffi.h>
 
29
#ifdef HAVE_MACHINE_ASM_H
 
30
#include <machine/asm.h>
 
31
#else
 
32
#ifdef __USER_LABEL_PREFIX__
 
33
#define CONCAT1(a, b) CONCAT2(a, b)
 
34
#define CONCAT2(a, b) a ## b
 
35
 
 
36
/* Use the right prefix for global labels.  */
 
37
#define CNAME(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
 
38
#else
 
39
#define CNAME(x) x
 
40
#endif
 
41
#define ENTRY(x) .globl CNAME(x); .type CNAME(x),%function; CNAME(x):
 
42
#endif
 
43
 
 
44
#ifdef __ELF__
 
45
#define LSYM(x) .x
 
46
#else
 
47
#define LSYM(x) x
 
48
#endif
 
49
 
 
50
/* We need a better way of testing for this, but for now, this is all 
 
51
   we can do.  */
 
52
@ This selects the minimum architecture level required.
 
53
#define __ARM_ARCH__ 3
 
54
 
 
55
#if defined(__ARM_ARCH_4__) || defined(__ARM_ARCH_4T__)
 
56
# undef __ARM_ARCH__
 
57
# define __ARM_ARCH__ 4
 
58
#endif
 
59
        
 
60
#if defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5T__) \
 
61
        || defined(__ARM_ARCH_5E__) || defined(__ARM_ARCH_5TE__) \
 
62
        || defined(__ARM_ARCH_5TEJ__)
 
63
# undef __ARM_ARCH__
 
64
# define __ARM_ARCH__ 5
 
65
#endif
 
66
 
 
67
#if defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \
 
68
        || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) \
 
69
        || defined(__ARM_ARCH_6ZK__)
 
70
# undef __ARM_ARCH__
 
71
# define __ARM_ARCH__ 6
 
72
#endif
 
73
 
 
74
#if __ARM_ARCH__ >= 5
 
75
# define call_reg(x)    blx     x
 
76
#elif defined (__ARM_ARCH_4T__)
 
77
# define call_reg(x)    mov     lr, pc ; bx     x
 
78
# if defined(__thumb__) || defined(__THUMB_INTERWORK__)
 
79
#  define __INTERWORKING__
 
80
# endif
 
81
#else
 
82
# define call_reg(x)    mov     lr, pc ; mov    pc, x
 
83
#endif
 
84
 
 
85
#if defined(__thumb__) && !defined(__THUMB_INTERWORK__)
 
86
.macro  ARM_FUNC_START name
 
87
        .text
 
88
        .align 0
 
89
        .thumb
 
90
        .thumb_func
 
91
        ENTRY(\name)
 
92
        bx      pc
 
93
        nop
 
94
        .arm
 
95
/* A hook to tell gdb that we've switched to ARM mode.  Also used to call
 
96
   directly from other local arm routines.  */
 
97
_L__\name:              
 
98
.endm
 
99
#else
 
100
.macro  ARM_FUNC_START name
 
101
        .text
 
102
        .align 0
 
103
        .arm
 
104
        ENTRY(\name)
 
105
.endm
 
106
#endif
 
107
 
 
108
.macro  RETLDM  regs=, cond=, dirn=ia
 
109
#if defined (__INTERWORKING__)
 
110
        .ifc "\regs",""
 
111
        ldr\cond        lr, [sp], #4
 
112
        .else
 
113
        ldm\cond\dirn   sp!, {\regs, lr}
 
114
        .endif
 
115
        bx\cond lr
 
116
#else
 
117
        .ifc "\regs",""
 
118
        ldr\cond        pc, [sp], #4
 
119
        .else
 
120
        ldm\cond\dirn   sp!, {\regs, pc}
 
121
        .endif
 
122
#endif
 
123
.endm
 
124
 
 
125
 
 
126
        @ r0:   ffi_prep_args
 
127
        @ r1:   &ecif
 
128
        @ r2:   cif->bytes
 
129
        @ r3:   fig->flags
 
130
        @ sp+0: ecif.rvalue
 
131
        @ sp+4: fn
 
132
 
 
133
        @ This assumes we are using gas.
 
134
ARM_FUNC_START ffi_call_SYSV
 
135
        @ Save registers
 
136
        stmfd   sp!, {r0-r3, fp, lr}
 
137
        mov     fp, sp
 
138
 
 
139
        @ Make room for all of the new args.
 
140
        sub     sp, fp, r2
 
141
 
 
142
        @ Place all of the ffi_prep_args in position
 
143
        mov     ip, r0
 
144
        mov     r0, sp
 
145
        @     r1 already set
 
146
 
 
147
        @ Call ffi_prep_args(stack, &ecif)
 
148
        call_reg(ip)
 
149
 
 
150
        @ move first 4 parameters in registers
 
151
        ldmia   sp, {r0-r3}
 
152
 
 
153
        @ and adjust stack
 
154
        ldr     ip, [fp, #8]
 
155
        cmp     ip, #16
 
156
        movhs   ip, #16
 
157
        add     sp, sp, ip
 
158
 
 
159
        @ call (fn) (...)
 
160
        ldr     ip, [fp, #28]
 
161
        call_reg(ip)
 
162
        
 
163
        @ Remove the space we pushed for the args
 
164
        mov     sp, fp
 
165
 
 
166
        @ Load r2 with the pointer to storage for the return value
 
167
        ldr     r2, [sp, #24]
 
168
 
 
169
        @ Load r3 with the return type code 
 
170
        ldr     r3, [sp, #12]
 
171
 
 
172
        @ If the return value pointer is NULL, assume no return value.
 
173
        cmp     r2, #0
 
174
        beq     LSYM(Lepilogue)
 
175
 
 
176
@ return INT
 
177
        cmp     r3, #FFI_TYPE_INT
 
178
#ifdef __SOFTFP__
 
179
        cmpne   r3, #FFI_TYPE_FLOAT
 
180
#endif
 
181
        streq   r0, [r2]
 
182
        beq     LSYM(Lepilogue)
 
183
 
 
184
        @ return INT64
 
185
        cmp     r3, #FFI_TYPE_SINT64
 
186
#ifdef __SOFTFP__
 
187
        cmpne   r3, #FFI_TYPE_DOUBLE
 
188
#endif
 
189
        stmeqia r2, {r0, r1}
 
190
 
 
191
#ifndef __SOFTFP__
 
192
        beq     LSYM(Lepilogue)
 
193
 
 
194
@ return FLOAT
 
195
        cmp     r3, #FFI_TYPE_FLOAT
 
196
        stfeqs  f0, [r2]
 
197
        beq     LSYM(Lepilogue)
 
198
 
 
199
@ return DOUBLE or LONGDOUBLE
 
200
        cmp     r3, #FFI_TYPE_DOUBLE
 
201
        stfeqd  f0, [r2]
 
202
#endif
 
203
 
 
204
LSYM(Lepilogue):
 
205
        RETLDM  "r0-r3,fp"
 
206
 
 
207
.ffi_call_SYSV_end:
 
208
        .size    CNAME(ffi_call_SYSV),.ffi_call_SYSV_end-CNAME(ffi_call_SYSV)
 
209