Merge from mainline (gomp-merge-2005-02-26).
[official-gcc.git] / libffi / src / arm / sysv.S
blobc3471a8a2ff1d8f1aeecd2b81d22cc5693931212
1 /* -----------------------------------------------------------------------
2    sysv.S - Copyright (c) 1998 Red Hat, Inc.
3    
4    ARM Foreign Function Interface 
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:
14    The above copyright notice and this permission notice shall be included
15    in all copies or substantial portions of the Software.
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    ----------------------------------------------------------------------- */
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
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
44 #ifdef __ELF__
45 #define LSYM(x) .x
46 #else
47 #define LSYM(x) x
48 #endif
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
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
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
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
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
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
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
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
139         @ Make room for all of the new args.
140         sub     sp, fp, r2
142         @ Place all of the ffi_prep_args in position
143         mov     ip, r0
144         mov     r0, sp
145         @     r1 already set
147         @ Call ffi_prep_args(stack, &ecif)
148         call_reg(ip)
150         @ move first 4 parameters in registers
151         ldmia   sp, {r0-r3}
153         @ and adjust stack
154         ldr     ip, [fp, #8]
155         cmp     ip, #16
156         movhs   ip, #16
157         add     sp, sp, ip
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
166         @ Load r2 with the pointer to storage for the return value
167         ldr     r2, [sp, #24]
169         @ Load r3 with the return type code 
170         ldr     r3, [sp, #12]
172         @ If the return value pointer is NULL, assume no return value.
173         cmp     r2, #0
174         beq     LSYM(Lepilogue)
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)
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}
191 #ifndef __SOFTFP__
192         beq     LSYM(Lepilogue)
194 @ return FLOAT
195         cmp     r3, #FFI_TYPE_FLOAT
196         stfeqs  f0, [r2]
197         beq     LSYM(Lepilogue)
199 @ return DOUBLE or LONGDOUBLE
200         cmp     r3, #FFI_TYPE_DOUBLE
201         stfeqd  f0, [r2]
202 #endif
204 LSYM(Lepilogue):
205         RETLDM  "r0-r3,fp"
207 .ffi_call_SYSV_end:
208         .size    CNAME(ffi_call_SYSV),.ffi_call_SYSV_end-CNAME(ffi_call_SYSV)