Fix build on sparc64-linux-gnu.
[official-gcc.git] / libffi / src / avr32 / sysv.S
bloba984b3c88a3095a737bb8fdace60d48f92401515
1 /* -----------------------------------------------------------------------
2    sysv.S - Copyright (c) 2009  Bradley Smith <brad@brad-smith.co.uk>
4    AVR32 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,
18    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
21    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22    TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23    SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24    --------------------------------------------------------------------- */
26 #define LIBFFI_ASM
27 #include <fficonfig.h>
28 #include <ffi.h>
30     /* r12:  ffi_prep_args
31      * r11:  &ecif
32      * r10:  size
33      * r9:   cif->flags
34      * r8:   ecif.rvalue
35      * sp+0: cif->rstruct_flag
36      * sp+4: fn */
38     .text
39     .align  1
40     .globl  ffi_call_SYSV
41     .type   ffi_call_SYSV, @function
42 ffi_call_SYSV:
43     stm     --sp, r0,r1,lr
44     stm     --sp, r8-r12
45     mov     r0, sp
47     /* Make room for all of the new args. */
48     sub     sp, r10
49     /* Pad to make way for potential skipped registers */
50     sub     sp, 20
52     /* Call ffi_prep_args(stack, &ecif). */
53     /* r11 already set */
54     mov     r1, r12
55     mov     r12, sp
56     icall   r1
58     /* Save new argument size */
59     mov     r1, r12
61     /* Move first 5 parameters in registers. */
62     ldm     sp++, r8-r12
64     /* call (fn) (...). */
65     ld.w    r1, r0[36]
66     icall   r1
68     /* Remove the space we pushed for the args. */
69     mov     sp, r0
71     /* Load r1 with the rstruct flag. */
72     ld.w    r1, sp[32]
74     /* Load r9 with the return type code. */
75     ld.w    r9, sp[12]
77     /* Load r8 with the return value pointer. */
78     ld.w    r8, sp[16]
80     /* If the return value pointer is NULL, assume no return value. */
81     cp.w    r8, 0
82     breq    .Lend
84     /* Check if return type is actually a struct */
85     cp.w    r1, 0
86     breq    1f
88     /* Return 8bit */
89     cp.w    r9, FFI_TYPE_UINT8
90     breq    .Lstore8
92     /* Return 16bit */
93     cp.w    r9, FFI_TYPE_UINT16
94     breq    .Lstore16
97     /* Return 32bit */
98     cp.w    r9, FFI_TYPE_UINT32
99     breq    .Lstore32
100     cp.w    r9, FFI_TYPE_UINT16
101     breq    .Lstore32
102     cp.w    r9, FFI_TYPE_UINT8
103     breq    .Lstore32
105     /* Return 64bit */
106     cp.w    r9, FFI_TYPE_UINT64
107     breq    .Lstore64
109     /* Didn't match anything */
110     bral    .Lend
112 .Lstore64:
113     st.w    r8[0], r11
114     st.w    r8[4], r10
115     bral    .Lend
117 .Lstore32:
118     st.w    r8[0], r12
119     bral    .Lend
121 .Lstore16:
122     st.h    r8[0], r12
123     bral    .Lend
125 .Lstore8:
126     st.b    r8[0], r12
127     bral    .Lend
129 .Lend:
130     sub     sp, -20
131     ldm     sp++, r0,r1,pc
133     .size   ffi_call_SYSV, . - ffi_call_SYSV
136     /* r12:  __ctx
137      * r11:  __rstruct_flag
138      * r10:  __inner */
140     .align  1
141     .globl  ffi_closure_SYSV
142     .type   ffi_closure_SYSV, @function
143 ffi_closure_SYSV:
144     stm     --sp, r0,lr
145     mov     r0, r11
146     mov     r8, r10
147     sub     r10, sp, -8
148     sub     sp, 12
149     st.w    sp[8], sp
150     sub     r11, sp, -8
151     icall   r8
153     /* Check if return type is actually a struct */
154     cp.w    r0, 0
155     breq    1f
157     /* Return 8bit */
158     cp.w    r12, FFI_TYPE_UINT8
159     breq    .Lget8
161     /* Return 16bit */
162     cp.w    r12, FFI_TYPE_UINT16
163     breq    .Lget16
166     /* Return 32bit */
167     cp.w    r12, FFI_TYPE_UINT32
168     breq    .Lget32
169     cp.w    r12, FFI_TYPE_UINT16
170     breq    .Lget32
171     cp.w    r12, FFI_TYPE_UINT8
172     breq    .Lget32
174     /* Return 64bit */
175     cp.w    r12, FFI_TYPE_UINT64
176     breq    .Lget64
178     /* Didn't match anything */
179     bral    .Lclend
181 .Lget64:
182     ld.w    r11, sp[0]
183     ld.w    r10, sp[4]
184     bral    .Lclend
186 .Lget32:
187     ld.w    r12, sp[0]
188     bral    .Lclend
190 .Lget16:
191     ld.uh   r12, sp[0]
192     bral    .Lclend
194 .Lget8:
195     ld.ub   r12, sp[0]
196     bral    .Lclend
198 .Lclend:
199     sub     sp, -12
200     ldm     sp++, r0,lr
201     sub     sp, -20
202     mov     pc, lr
204     .size   ffi_closure_SYSV, . - ffi_closure_SYSV
206 #if defined __ELF__ && defined __linux__
207     .section    .note.GNU-stack,"",@progbits
208 #endif