m68k: support ISA-A Coldfire CPUs
[libffi.git] / src / m68k / sysv.S
1 /* -----------------------------------------------------------------------
2         
3    sysv.S - Copyright (c) 2012 Alan Hourihane
4             Copyright (c) 1998, 2012 Andreas Schwab
5             Copyright (c) 2008 Red Hat, Inc.
6             Copyright (c) 2012, 2016 Thorsten Glaser
7
8    m68k Foreign Function Interface
9
10    Permission is hereby granted, free of charge, to any person obtaining
11    a copy of this software and associated documentation files (the
12    ``Software''), to deal in the Software without restriction, including
13    without limitation the rights to use, copy, modify, merge, publish,
14    distribute, sublicense, and/or sell copies of the Software, and to
15    permit persons to whom the Software is furnished to do so, subject to
16    the following conditions:
17
18    The above copyright notice and this permission notice shall be included
19    in all copies or substantial portions of the Software.
20
21    THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
22    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24    NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
25    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28    DEALINGS IN THE SOFTWARE.
29    ----------------------------------------------------------------------- */
30
31 #define LIBFFI_ASM      
32 #include <fficonfig.h>
33 #include <ffi.h>
34
35 #ifdef HAVE_AS_CFI_PSEUDO_OP
36 #define CFI_STARTPROC()         .cfi_startproc
37 #define CFI_OFFSET(reg,off)     .cfi_offset     reg,off
38 #define CFI_DEF_CFA(reg,off)    .cfi_def_cfa    reg,off
39 #define CFI_ENDPROC()           .cfi_endproc
40 #else
41 #define CFI_STARTPROC()
42 #define CFI_OFFSET(reg,off)
43 #define CFI_DEF_CFA(reg,off)
44 #define CFI_ENDPROC()
45 #endif
46
47 #ifdef __MINT__
48 #define CALLFUNC(funcname) _ ## funcname
49 #else
50 #define CALLFUNC(funcname) funcname
51 #endif
52
53         .text
54
55         .globl  CALLFUNC(ffi_call_SYSV)
56         .type   CALLFUNC(ffi_call_SYSV),@function
57         .align  4
58
59 CALLFUNC(ffi_call_SYSV):
60         CFI_STARTPROC()
61         link    %fp,#0
62         CFI_OFFSET(14,-8)
63         CFI_DEF_CFA(14,8)
64         move.l  %d2,-(%sp)
65         CFI_OFFSET(2,-12)
66
67         | Make room for all of the new args.
68         sub.l   12(%fp),%sp
69
70         | Call ffi_prep_args
71         move.l  8(%fp),-(%sp)
72         pea     4(%sp)
73 #if !defined __PIC__
74         jsr     CALLFUNC(ffi_prep_args)
75 #elif defined(__uClinux__) && defined(__ID_SHARED_LIBRARY__)
76         move.l  _current_shared_library_a5_offset_(%a5),%a0
77         move.l  CALLFUNC(ffi_prep_args@GOT)(%a0),%a0
78         jsr     (%a0)
79 #elif defined(__mcoldfire__) && !defined(__mcfisab__) && !defined(__mcfisac__)
80         move.l  #_GLOBAL_OFFSET_TABLE_@GOTPC,%a0
81         lea     (-6,%pc,%a0),%a0
82         move.l  CALLFUNC(ffi_prep_args@GOT)(%a0),%a0
83         jsr     (%a0)
84 #else
85         bsr.l   CALLFUNC(ffi_prep_args@PLTPC)
86 #endif
87         addq.l  #8,%sp  
88
89         | Pass pointer to struct value, if any
90 #ifdef __MINT__
91         move.l  %d0,%a1
92 #else
93         move.l  %a0,%a1
94 #endif
95
96         | Call the function
97         move.l  24(%fp),%a0
98         jsr     (%a0)
99
100         | Remove the space we pushed for the args
101         add.l   12(%fp),%sp
102
103         | Load the pointer to storage for the return value
104         move.l  20(%fp),%a1
105
106         | Load the return type code 
107         move.l  16(%fp),%d2
108
109         | If the return value pointer is NULL, assume no return value.
110         | NOTE: On the mc68000, tst on an address register is not supported.
111 #if !defined(__mc68020__) && !defined(__mc68030__) && !defined(__mc68040__) && !defined(__mc68060__) && !defined(__mcoldfire__)
112         cmp.w   #0, %a1
113 #else
114         tst.l   %a1
115 #endif
116         jbeq    noretval
117
118         btst    #0,%d2
119         jbeq    retlongint
120         move.l  %d0,(%a1)
121         jbra    epilogue
122
123 retlongint:
124         btst    #1,%d2
125         jbeq    retfloat
126         move.l  %d0,(%a1)
127         move.l  %d1,4(%a1)
128         jbra    epilogue
129
130 retfloat:
131         btst    #2,%d2
132         jbeq    retdouble
133 #if defined(__MC68881__) || defined(__HAVE_68881__)
134         fmove.s %fp0,(%a1)
135 #else
136         move.l  %d0,(%a1)
137 #endif
138         jbra    epilogue
139
140 retdouble:
141         btst    #3,%d2
142         jbeq    retlongdouble
143 #if defined(__MC68881__) || defined(__HAVE_68881__)
144         fmove.d %fp0,(%a1)
145 #else
146         move.l  %d0,(%a1)+
147         move.l  %d1,(%a1)
148 #endif
149         jbra    epilogue
150
151 retlongdouble:
152         btst    #4,%d2
153         jbeq    retpointer
154 #if defined(__MC68881__) || defined(__HAVE_68881__)
155         fmove.x %fp0,(%a1)
156 #else
157         move.l  %d0,(%a1)+
158         move.l  %d1,(%a1)+
159         move.l  %d2,(%a1)
160 #endif
161         jbra    epilogue
162
163 retpointer:
164         btst    #5,%d2
165         jbeq    retstruct1
166 #ifdef __MINT__
167         move.l  %d0,(%a1)
168 #else
169         move.l  %a0,(%a1)
170 #endif
171         jbra    epilogue
172
173 retstruct1:
174         btst    #6,%d2
175         jbeq    retstruct2
176         move.b  %d0,(%a1)
177         jbra    epilogue
178
179 retstruct2:
180         btst    #7,%d2
181         jbeq    retsint8
182         move.w  %d0,(%a1)
183         jbra    epilogue
184
185 retsint8:
186         btst    #8,%d2
187         jbeq    retsint16
188         | NOTE: On the mc68000, extb is not supported. 8->16, then 16->32.
189 #if !defined(__mc68020__) && !defined(__mc68030__) && !defined(__mc68040__) && !defined(__mc68060__) && !defined(__mcoldfire__)
190         ext.w   %d0
191         ext.l   %d0
192 #else
193         extb.l  %d0
194 #endif
195         move.l  %d0,(%a1)
196         jbra    epilogue
197
198 retsint16:
199         btst    #9,%d2
200         jbeq    noretval
201         ext.l   %d0
202         move.l  %d0,(%a1)
203
204 noretval:
205 epilogue:
206         move.l  (%sp)+,%d2
207         unlk    %fp
208         rts
209         CFI_ENDPROC()
210         .size   CALLFUNC(ffi_call_SYSV),.-CALLFUNC(ffi_call_SYSV)
211
212         .globl  CALLFUNC(ffi_closure_SYSV)
213         .type   CALLFUNC(ffi_closure_SYSV), @function
214         .align  4
215
216 CALLFUNC(ffi_closure_SYSV):
217         CFI_STARTPROC()
218         link    %fp,#-12
219         CFI_OFFSET(14,-8)
220         CFI_DEF_CFA(14,8)
221         move.l  %sp,-12(%fp)
222         pea     8(%fp)
223         pea     -12(%fp)
224         move.l  %a0,-(%sp)
225 #if !defined __PIC__
226         jsr     CALLFUNC(ffi_closure_SYSV_inner)
227 #elif defined(__uClinux__) && defined(__ID_SHARED_LIBRARY__)
228         move.l  _current_shared_library_a5_offset_(%a5),%a0
229         move.l  CALLFUNC(ffi_closure_SYSV_inner@GOT)(%a0),%a0
230         jsr     (%a0)
231 #elif defined(__mcoldfire__) && !defined(__mcfisab__) && !defined(__mcfisac__)
232         move.l  #_GLOBAL_OFFSET_TABLE_@GOTPC,%a0
233         lea     (-6,%pc,%a0),%a0
234         move.l  CALLFUNC(ffi_closure_SYSV_inner@GOT)(%a0),%a0
235         jsr     (%a0)
236 #else
237         bsr.l   CALLFUNC(ffi_closure_SYSV_inner@PLTPC)
238 #endif
239
240         lsr.l   #1,%d0
241         jne     1f
242         jcc     .Lcls_epilogue
243         | CIF_FLAGS_INT
244         move.l  -12(%fp),%d0
245 .Lcls_epilogue:
246         | no CIF_FLAGS_*
247         unlk    %fp
248         rts
249 1:
250         lea     -12(%fp),%a0
251         lsr.l   #2,%d0
252         jne     1f
253         jcs     .Lcls_ret_float
254         | CIF_FLAGS_DINT
255         move.l  (%a0)+,%d0
256         move.l  (%a0),%d1
257         jra     .Lcls_epilogue
258 .Lcls_ret_float:
259 #if defined(__MC68881__) || defined(__HAVE_68881__)
260         fmove.s (%a0),%fp0
261 #else
262         move.l  (%a0),%d0
263 #endif
264         jra     .Lcls_epilogue
265 1:
266         lsr.l   #2,%d0
267         jne     1f
268         jcs     .Lcls_ret_ldouble
269         | CIF_FLAGS_DOUBLE
270 #if defined(__MC68881__) || defined(__HAVE_68881__)
271         fmove.d (%a0),%fp0
272 #else
273         move.l  (%a0)+,%d0
274         move.l  (%a0),%d1
275 #endif
276         jra     .Lcls_epilogue
277 .Lcls_ret_ldouble:
278 #if defined(__MC68881__) || defined(__HAVE_68881__)
279         fmove.x (%a0),%fp0
280 #else
281         move.l  (%a0)+,%d0
282         move.l  (%a0)+,%d1
283         move.l  (%a0),%d2
284 #endif
285         jra     .Lcls_epilogue
286 1:
287         lsr.l   #2,%d0
288         jne     1f
289         jcs     .Lcls_ret_struct1
290         | CIF_FLAGS_POINTER
291         move.l  (%a0),%a0
292         move.l  %a0,%d0
293         jra     .Lcls_epilogue
294 .Lcls_ret_struct1:
295         move.b  (%a0),%d0
296         jra     .Lcls_epilogue
297 1:
298         lsr.l   #2,%d0
299         jne     1f
300         jcs     .Lcls_ret_sint8
301         | CIF_FLAGS_STRUCT2
302         move.w  (%a0),%d0
303         jra     .Lcls_epilogue
304 .Lcls_ret_sint8:
305         move.l  (%a0),%d0
306         | NOTE: On the mc68000, extb is not supported. 8->16, then 16->32.
307 #if !defined(__mc68020__) && !defined(__mc68030__) && !defined(__mc68040__) && !defined(__mc68060__) && !defined(__mcoldfire__)
308         ext.w   %d0
309         ext.l   %d0
310 #else
311         extb.l  %d0
312 #endif
313         jra     .Lcls_epilogue
314 1:
315         | CIF_FLAGS_SINT16
316         move.l  (%a0),%d0
317         ext.l   %d0
318         jra     .Lcls_epilogue
319         CFI_ENDPROC()
320
321         .size   CALLFUNC(ffi_closure_SYSV),.-CALLFUNC(ffi_closure_SYSV)
322
323         .globl  CALLFUNC(ffi_closure_struct_SYSV)
324         .type   CALLFUNC(ffi_closure_struct_SYSV), @function
325         .align  4
326
327 CALLFUNC(ffi_closure_struct_SYSV):
328         CFI_STARTPROC()
329         link    %fp,#0
330         CFI_OFFSET(14,-8)
331         CFI_DEF_CFA(14,8)
332         move.l  %sp,-12(%fp)
333         pea     8(%fp)
334         move.l  %a1,-(%sp)
335         move.l  %a0,-(%sp)
336 #if !defined __PIC__
337         jsr     CALLFUNC(ffi_closure_SYSV_inner)
338 #elif defined(__uClinux__) && defined(__ID_SHARED_LIBRARY__)
339         move.l  _current_shared_library_a5_offset_(%a5),%a0
340         move.l  CALLFUNC(ffi_closure_SYSV_inner@GOT)(%a0),%a0
341         jsr     (%a0)
342 #elif defined(__mcoldfire__) && !defined(__mcfisab__) && !defined(__mcfisac__)
343         move.l  #_GLOBAL_OFFSET_TABLE_@GOTPC,%a0
344         lea     (-6,%pc,%a0),%a0
345         move.l  CALLFUNC(ffi_closure_SYSV_inner@GOT)(%a0),%a0
346         jsr     (%a0)
347 #else
348         bsr.l   CALLFUNC(ffi_closure_SYSV_inner@PLTPC)
349 #endif
350         unlk    %fp
351         rts
352         CFI_ENDPROC()
353         .size   CALLFUNC(ffi_closure_struct_SYSV),.-CALLFUNC(ffi_closure_struct_SYSV)
354
355 #if defined __ELF__ && defined __linux__
356         .section        .note.GNU-stack,"",@progbits
357 #endif