Update README with a new port
[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 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 #else
76         bsr.l   CALLFUNC(ffi_prep_args@PLTPC)
77 #endif
78         addq.l  #8,%sp  
79
80         | Pass pointer to struct value, if any
81 #ifdef __MINT__
82         move.l  %d0,%a1
83 #else
84         move.l  %a0,%a1
85 #endif
86
87         | Call the function
88         move.l  24(%fp),%a0
89         jsr     (%a0)
90
91         | Remove the space we pushed for the args
92         add.l   12(%fp),%sp
93
94         | Load the pointer to storage for the return value
95         move.l  20(%fp),%a1
96
97         | Load the return type code 
98         move.l  16(%fp),%d2
99
100         | If the return value pointer is NULL, assume no return value.
101         | NOTE: On the mc68000, tst on an address register is not supported.
102 #if !defined(__mc68020__) && !defined(__mc68030__) && !defined(__mc68040__) && !defined(__mc68060__) && !defined(__mcoldfire__)
103         cmp.w   #0, %a1
104 #else
105         tst.l   %a1
106 #endif
107         jbeq    noretval
108
109         btst    #0,%d2
110         jbeq    retlongint
111         move.l  %d0,(%a1)
112         jbra    epilogue
113
114 retlongint:
115         btst    #1,%d2
116         jbeq    retfloat
117         move.l  %d0,(%a1)
118         move.l  %d1,4(%a1)
119         jbra    epilogue
120
121 retfloat:
122         btst    #2,%d2
123         jbeq    retdouble
124 #if defined(__MC68881__) || defined(__HAVE_68881__)
125         fmove.s %fp0,(%a1)
126 #else
127         move.l  %d0,(%a1)
128 #endif
129         jbra    epilogue
130
131 retdouble:
132         btst    #3,%d2
133         jbeq    retlongdouble
134 #if defined(__MC68881__) || defined(__HAVE_68881__)
135         fmove.d %fp0,(%a1)
136 #else
137         move.l  %d0,(%a1)+
138         move.l  %d1,(%a1)
139 #endif
140         jbra    epilogue
141
142 retlongdouble:
143         btst    #4,%d2
144         jbeq    retpointer
145 #if defined(__MC68881__) || defined(__HAVE_68881__)
146         fmove.x %fp0,(%a1)
147 #else
148         move.l  %d0,(%a1)+
149         move.l  %d1,(%a1)+
150         move.l  %d2,(%a1)
151 #endif
152         jbra    epilogue
153
154 retpointer:
155         btst    #5,%d2
156         jbeq    retstruct1
157 #ifdef __MINT__
158         move.l  %d0,(%a1)
159 #else
160         move.l  %a0,(%a1)
161 #endif
162         jbra    epilogue
163
164 retstruct1:
165         btst    #6,%d2
166         jbeq    retstruct2
167         move.b  %d0,(%a1)
168         jbra    epilogue
169
170 retstruct2:
171         btst    #7,%d2
172         jbeq    retsint8
173         move.w  %d0,(%a1)
174         jbra    epilogue
175
176 retsint8:
177         btst    #8,%d2
178         jbeq    retsint16
179         | NOTE: On the mc68000, extb is not supported. 8->16, then 16->32.
180 #if !defined(__mc68020__) && !defined(__mc68030__) && !defined(__mc68040__) && !defined(__mc68060__) && !defined(__mcoldfire__)
181         ext.w   %d0
182         ext.l   %d0
183 #else
184         extb.l  %d0
185 #endif
186         move.l  %d0,(%a1)
187         jbra    epilogue
188
189 retsint16:
190         btst    #9,%d2
191         jbeq    noretval
192         ext.l   %d0
193         move.l  %d0,(%a1)
194
195 noretval:
196 epilogue:
197         move.l  (%sp)+,%d2
198         unlk    %fp
199         rts
200         CFI_ENDPROC()
201         .size   CALLFUNC(ffi_call_SYSV),.-CALLFUNC(ffi_call_SYSV)
202
203         .globl  CALLFUNC(ffi_closure_SYSV)
204         .type   CALLFUNC(ffi_closure_SYSV), @function
205         .align  4
206
207 CALLFUNC(ffi_closure_SYSV):
208         CFI_STARTPROC()
209         link    %fp,#-12
210         CFI_OFFSET(14,-8)
211         CFI_DEF_CFA(14,8)
212         move.l  %sp,-12(%fp)
213         pea     8(%fp)
214         pea     -12(%fp)
215         move.l  %a0,-(%sp)
216 #if !defined __PIC__
217         jsr     CALLFUNC(ffi_closure_SYSV_inner)
218 #else
219         bsr.l   CALLFUNC(ffi_closure_SYSV_inner@PLTPC)
220 #endif
221
222         lsr.l   #1,%d0
223         jne     1f
224         jcc     .Lcls_epilogue
225         | CIF_FLAGS_INT
226         move.l  -12(%fp),%d0
227 .Lcls_epilogue:
228         | no CIF_FLAGS_*
229         unlk    %fp
230         rts
231 1:
232         lea     -12(%fp),%a0
233         lsr.l   #2,%d0
234         jne     1f
235         jcs     .Lcls_ret_float
236         | CIF_FLAGS_DINT
237         move.l  (%a0)+,%d0
238         move.l  (%a0),%d1
239         jra     .Lcls_epilogue
240 .Lcls_ret_float:
241 #if defined(__MC68881__) || defined(__HAVE_68881__)
242         fmove.s (%a0),%fp0
243 #else
244         move.l  (%a0),%d0
245 #endif
246         jra     .Lcls_epilogue
247 1:
248         lsr.l   #2,%d0
249         jne     1f
250         jcs     .Lcls_ret_ldouble
251         | CIF_FLAGS_DOUBLE
252 #if defined(__MC68881__) || defined(__HAVE_68881__)
253         fmove.d (%a0),%fp0
254 #else
255         move.l  (%a0)+,%d0
256         move.l  (%a0),%d1
257 #endif
258         jra     .Lcls_epilogue
259 .Lcls_ret_ldouble:
260 #if defined(__MC68881__) || defined(__HAVE_68881__)
261         fmove.x (%a0),%fp0
262 #else
263         move.l  (%a0)+,%d0
264         move.l  (%a0)+,%d1
265         move.l  (%a0),%d2
266 #endif
267         jra     .Lcls_epilogue
268 1:
269         lsr.l   #2,%d0
270         jne     1f
271         jcs     .Lcls_ret_struct1
272         | CIF_FLAGS_POINTER
273         move.l  (%a0),%a0
274         move.l  %a0,%d0
275         jra     .Lcls_epilogue
276 .Lcls_ret_struct1:
277         move.b  (%a0),%d0
278         jra     .Lcls_epilogue
279 1:
280         lsr.l   #2,%d0
281         jne     1f
282         jcs     .Lcls_ret_sint8
283         | CIF_FLAGS_STRUCT2
284         move.w  (%a0),%d0
285         jra     .Lcls_epilogue
286 .Lcls_ret_sint8:
287         move.l  (%a0),%d0
288         | NOTE: On the mc68000, extb is not supported. 8->16, then 16->32.
289 #if !defined(__mc68020__) && !defined(__mc68030__) && !defined(__mc68040__) && !defined(__mc68060__) && !defined(__mcoldfire__)
290         ext.w   %d0
291         ext.l   %d0
292 #else
293         extb.l  %d0
294 #endif
295         jra     .Lcls_epilogue
296 1:
297         | CIF_FLAGS_SINT16
298         move.l  (%a0),%d0
299         ext.l   %d0
300         jra     .Lcls_epilogue
301         CFI_ENDPROC()
302
303         .size   CALLFUNC(ffi_closure_SYSV),.-CALLFUNC(ffi_closure_SYSV)
304
305         .globl  CALLFUNC(ffi_closure_struct_SYSV)
306         .type   CALLFUNC(ffi_closure_struct_SYSV), @function
307         .align  4
308
309 CALLFUNC(ffi_closure_struct_SYSV):
310         CFI_STARTPROC()
311         link    %fp,#0
312         CFI_OFFSET(14,-8)
313         CFI_DEF_CFA(14,8)
314         move.l  %sp,-12(%fp)
315         pea     8(%fp)
316         move.l  %a1,-(%sp)
317         move.l  %a0,-(%sp)
318 #if !defined __PIC__
319         jsr     CALLFUNC(ffi_closure_SYSV_inner)
320 #else
321         bsr.l   CALLFUNC(ffi_closure_SYSV_inner@PLTPC)
322 #endif
323         unlk    %fp
324         rts
325         CFI_ENDPROC()
326         .size   CALLFUNC(ffi_closure_struct_SYSV),.-CALLFUNC(ffi_closure_struct_SYSV)
327
328 #if defined __ELF__ && defined __linux__
329         .section        .note.GNU-stack,"",@progbits
330 #endif