2018-23-01 Paul Thomas <pault@gcc.gnu.org>
[official-gcc.git] / libffi / src / microblaze / sysv.S
blobea43e9d5453943297be18372efcb2b958fcb333e
1 /* -----------------------------------------------------------------------
2    sysv.S - Copyright (c) 2012, 2013 Xilinx, Inc
4    MicroBlaze 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
20    NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
21    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24    DEALINGS IN THE SOFTWARE.
25    ----------------------------------------------------------------------- */
27 #define LIBFFI_ASM
28 #include <fficonfig.h>
29 #include <ffi.h>
31         /*
32          * arg[0] (r5)  = ffi_prep_args,
33          * arg[1] (r6)  = &ecif,
34          * arg[2] (r7)  = cif->bytes,
35          * arg[3] (r8)  = cif->flags,
36          * arg[4] (r9)  = ecif.rvalue,
37          * arg[5] (r10) = fn
38          * arg[6] (sp[0]) = cif->rtype->type
39          * arg[7] (sp[4]) = cif->rtype->size
40          */
41         .text
42         .globl ffi_call_SYSV
43         .type ffi_call_SYSV, @function
44 ffi_call_SYSV:
45         /* push callee saves */
46         addik r1, r1, -20
47         swi r19, r1, 0 /* Frame Pointer */
48         swi r20, r1, 4 /* PIC register */
49         swi r21, r1, 8 /* PIC register */
50         swi r22, r1, 12 /* save for locals */
51         swi r23, r1, 16 /* save for locals */
52         
53         /* save the r5-r10 registers in the stack */
54         addik r1, r1, -24 /* increment sp to store 6x 32-bit words */
55         swi r5, r1, 0
56         swi r6, r1, 4
57         swi r7, r1, 8
58         swi r8, r1, 12
59         swi r9, r1, 16
60         swi r10, r1, 20
62         /* save function pointer */
63         addik r3, r5, 0 /* copy ffi_prep_args into r3 */
64         addik r22, r1, 0 /* save sp for unallocated args into r22 (callee-saved) */
65         addik r23, r10, 0 /* save function address into r23 (callee-saved) */
67         /* prepare stack with allocation for n (bytes = r7) args */
68         rsub r1, r7, r1 /* subtract bytes from sp */
70         /* prep args for ffi_prep_args call */
71         addik r5, r1, 0 /* store stack pointer into arg[0] */
72         /* r6 still holds ecif for arg[1] */
74         /* Call ffi_prep_args(stack, &ecif). */
75         addik r1, r1, -4
76         swi r15, r1, 0 /* store the link register in the frame */
77         brald r15, r3
78         nop /* branch has delay slot */
79         lwi r15, r1, 0
80         addik r1, r1, 4 /* restore the link register from the frame */
81         /* returns calling stack pointer location */
83         /* prepare args for fn call, prep_args populates them onto the stack */
84         lwi r5, r1, 0 /* arg[0] */
85         lwi r6, r1, 4 /* arg[1] */
86         lwi r7, r1, 8 /* arg[2] */
87         lwi r8, r1, 12 /* arg[3] */
88         lwi r9, r1, 16 /* arg[4] */
89         lwi r10, r1, 20 /* arg[5] */
91         /* call (fn) (...). */
92         addik r1, r1, -4
93         swi r15, r1, 0 /* store the link register in the frame */
94         brald r15, r23
95         nop /* branch has delay slot */
96         lwi r15, r1, 0
97         addik r1, r1, 4 /* restore the link register from the frame */
99         /* Remove the space we pushed for the args. */
100         addik r1, r22, 0 /* restore old SP */
102         /* restore this functions parameters */
103         lwi r5, r1, 0 /* arg[0] */
104         lwi r6, r1, 4 /* arg[1] */
105         lwi r7, r1, 8 /* arg[2] */
106         lwi r8, r1, 12 /* arg[3] */
107         lwi r9, r1, 16 /* arg[4] */
108         lwi r10, r1, 20 /* arg[5] */
109         addik r1, r1, 24 /* decrement sp to de-allocate 6x 32-bit words */
111         /* If the return value pointer is NULL, assume no return value. */
112         beqi r9, ffi_call_SYSV_end
114         lwi r22, r1, 48 /* get return type (20 for locals + 28 for arg[6]) */
115         lwi r23, r1, 52 /* get return size (20 for locals + 32 for arg[7])  */
116         
117         /* Check if return type is actually a struct, do nothing */
118         rsubi r11, r22, FFI_TYPE_STRUCT
119         beqi r11, ffi_call_SYSV_end
121         /* Return 8bit */
122         rsubi r11, r23, 1
123         beqi r11, ffi_call_SYSV_store8
125         /* Return 16bit */
126         rsubi r11, r23, 2
127         beqi r11, ffi_call_SYSV_store16
129         /* Return 32bit */
130         rsubi r11, r23, 4
131         beqi r11, ffi_call_SYSV_store32
133         /* Return 64bit */
134         rsubi r11, r23, 8
135         beqi r11, ffi_call_SYSV_store64
137         /* Didn't match anything */
138         bri ffi_call_SYSV_end
140 ffi_call_SYSV_store64:
141         swi r3, r9, 0 /* store word r3 into return value */
142         swi r4, r9, 4 /* store word r4 into return value */
143         bri ffi_call_SYSV_end
145 ffi_call_SYSV_store32:
146         swi r3, r9, 0 /* store word r3 into return value */
147         bri ffi_call_SYSV_end
149 ffi_call_SYSV_store16:
150 #ifdef __BIG_ENDIAN__
151         shi r3, r9, 2 /* store half-word r3 into return value */
152 #else
153         shi r3, r9, 0 /* store half-word r3 into return value */
154 #endif
155         bri ffi_call_SYSV_end
157 ffi_call_SYSV_store8:
158 #ifdef __BIG_ENDIAN__
159         sbi r3, r9, 3 /* store byte r3 into return value */
160 #else
161         sbi r3, r9, 0 /* store byte r3 into return value */
162 #endif
163         bri ffi_call_SYSV_end
165 ffi_call_SYSV_end:
166         /* callee restores */
167         lwi r19, r1, 0 /* frame pointer */
168         lwi r20, r1, 4 /* PIC register */
169         lwi r21, r1, 8 /* PIC register */
170         lwi r22, r1, 12
171         lwi r23, r1, 16
172         addik r1, r1, 20
174         /* return from sub-routine (with delay slot) */
175         rtsd r15, 8
176         nop
178         .size ffi_call_SYSV, . - ffi_call_SYSV
180 /* ------------------------------------------------------------------------- */
182         /*
183          * args passed into this function, are passed down to the callee.
184          * this function is the target of the closure trampoline, as such r12 is 
185          * a pointer to the closure object.
186          */
187         .text
188         .globl ffi_closure_SYSV
189         .type ffi_closure_SYSV, @function
190 ffi_closure_SYSV:
191         /* push callee saves */
192         addik r11, r1, 28 /* save stack args start location (excluding regs/link) */
193         addik r1, r1, -12
194         swi r19, r1, 0 /* Frame Pointer */
195         swi r20, r1, 4 /* PIC register */
196         swi r21, r1, 8 /* PIC register */
198         /* store register args on stack */
199         addik r1, r1, -24
200         swi r5, r1, 0
201         swi r6, r1, 4
202         swi r7, r1, 8
203         swi r8, r1, 12
204         swi r9, r1, 16
205         swi r10, r1, 20
207         /* setup args */
208         addik r5, r1, 0 /* register_args */
209         addik r6, r11, 0 /* stack_args */
210         addik r7, r12, 0 /* closure object */
211         addik r1, r1, -8 /* allocate return value */
212         addik r8, r1, 0 /* void* rvalue */
213         addik r1, r1, -8 /* allocate for return type/size values */
214         addik r9, r1, 0 /* void* rtype */
215         addik r10, r1, 4 /* void* rsize */
217         /* call the wrap_call function */
218         addik r1, r1, -28 /* allocate args + link reg */
219         swi r15, r1, 0 /* store the link register in the frame */
220         brald r15, r3
221         nop /* branch has delay slot */
222         lwi r15, r1, 0
223         addik r1, r1, 28 /* restore the link register from the frame */
225 ffi_closure_SYSV_prepare_return:
226         lwi r9, r1, 0 /* rtype */
227         lwi r10, r1, 4 /* rsize */
228         addik r1, r1, 8 /* de-allocate return info values */
230         /* Check if return type is actually a struct, store 4 bytes */
231         rsubi r11, r9, FFI_TYPE_STRUCT
232         beqi r11, ffi_closure_SYSV_store32
234         /* Return 8bit */
235         rsubi r11, r10, 1
236         beqi r11, ffi_closure_SYSV_store8
238         /* Return 16bit */
239         rsubi r11, r10, 2
240         beqi r11, ffi_closure_SYSV_store16
242         /* Return 32bit */
243         rsubi r11, r10, 4
244         beqi r11, ffi_closure_SYSV_store32
246         /* Return 64bit */
247         rsubi r11, r10, 8
248         beqi r11, ffi_closure_SYSV_store64
250         /* Didn't match anything */
251         bri ffi_closure_SYSV_end
253 ffi_closure_SYSV_store64:
254         lwi r3, r1, 0 /* store word r3 into return value */
255         lwi r4, r1, 4 /* store word r4 into return value */
256         /* 64 bits == 2 words, no sign extend occurs */
257         bri ffi_closure_SYSV_end
259 ffi_closure_SYSV_store32:
260         lwi r3, r1, 0 /* store word r3 into return value */
261         /* 32 bits == 1 word, no sign extend occurs */
262         bri ffi_closure_SYSV_end
264 ffi_closure_SYSV_store16:
265 #ifdef __BIG_ENDIAN__
266         lhui r3, r1, 2 /* store half-word r3 into return value */
267 #else
268         lhui r3, r1, 0 /* store half-word r3 into return value */
269 #endif
270         rsubi r11, r9, FFI_TYPE_SINT16
271         bnei r11, ffi_closure_SYSV_end
272         sext16 r3, r3 /* fix sign extend of sint8 */
273         bri ffi_closure_SYSV_end
275 ffi_closure_SYSV_store8:
276 #ifdef __BIG_ENDIAN__
277         lbui r3, r1, 3 /* store byte r3 into return value */
278 #else
279         lbui r3, r1, 0 /* store byte r3 into return value */
280 #endif
281         rsubi r11, r9, FFI_TYPE_SINT8
282         bnei r11, ffi_closure_SYSV_end
283         sext8 r3, r3 /* fix sign extend of sint8 */
284         bri ffi_closure_SYSV_end
286 ffi_closure_SYSV_end:
287         addik r1, r1, 8 /* de-allocate return value */
289         /* de-allocate stored args */
290         addik r1, r1, 24
292         /* callee restores */
293         lwi r19, r1, 0 /* frame pointer */
294         lwi r20, r1, 4 /* PIC register */
295         lwi r21, r1, 8 /* PIC register */
296         addik r1, r1, 12
298         /* return from sub-routine (with delay slot) */
299         rtsd r15, 8
300         nop
302         .size ffi_closure_SYSV, . - ffi_closure_SYSV