19f1b51b9a75885ed8c681a63cc379ad7c45f6cb
[libffi.git] / libffi / src / sh64 / sysv.S
1 /* -----------------------------------------------------------------------
2    sysv.S - Copyright (c) 2003, 2004 Kaz Kojima
3    
4    SuperH SHmedia Foreign Function Interface 
5
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:
13
14    The above copyright notice and this permission notice shall be included
15    in all copies or substantial portions of the Software.
16
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    ----------------------------------------------------------------------- */
25
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 /* XXX these lose for some platforms, I'm sure. */
33 #define CNAME(x) x
34 #define ENTRY(x) .globl CNAME(x); .type CNAME(x),%function; CNAME(x):
35 #endif
36
37 #ifdef __LITTLE_ENDIAN__
38 #define OFS_FLT 0
39 #else
40 #define OFS_FLT 4
41 #endif
42
43         .section        .text..SHmedia32,"ax"
44
45         # r2:   ffi_prep_args
46         # r3:   &ecif
47         # r4:   bytes
48         # r5:   flags
49         # r6:   flags2
50         # r7:   rvalue
51         # r8:   fn
52
53         # This assumes we are using gas.
54         .align  5
55 ENTRY(ffi_call_SYSV)
56         # Save registers
57 .LFB1:
58         addi.l  r15, -48, r15
59 .LCFI0:
60         st.q    r15, 40, r32
61         st.q    r15, 32, r31
62         st.q    r15, 24, r30
63         st.q    r15, 16, r29
64         st.q    r15, 8, r28
65         st.l    r15, 4, r18
66         st.l    r15, 0, r14
67 .LCFI1:
68         add.l   r15, r63, r14
69 .LCFI2:
70 #       add     r4, r63, r28
71         add     r5, r63, r29
72         add     r6, r63, r30
73         add     r7, r63, r31
74         add     r8, r63, r32
75
76         addi    r4, (64 + 7), r4
77         andi    r4, ~7, r4
78         sub.l   r15, r4, r15
79
80         ptabs/l r2, tr0
81         add     r15, r63, r2
82         blink   tr0, r18
83
84         addi    r15, 64, r22
85         movi    0, r0
86         movi    0, r1
87
88         pt/l    1f, tr1
89         bnei/l  r29, FFI_TYPE_STRUCT, tr1
90         ld.l    r15, 0, r19
91         addi    r15, 8, r15
92         addi    r0, 1, r0
93 1:
94
95 .L_pass:
96         andi    r30, 3, r20
97         shlri   r30, 2, r30
98
99         pt/l    .L_call_it, tr0
100         pt/l    .L_pass_i, tr1
101         pt/l    .L_pass_f, tr2
102
103         beqi/l  r20, FFI_TYPE_VOID, tr0
104         beqi/l  r20, FFI_TYPE_INT, tr1
105         beqi/l  r20, FFI_TYPE_FLOAT, tr2
106
107 .L_pass_d:
108         addi    r0, 1, r0
109         addi    r1, 1, r1
110         andi    r1, ~1, r1
111
112         pt/l    3f, tr0
113         movi    12, r20
114         bge/l   r1, r20, tr0
115
116         pt/l    .L_pop_d, tr1
117         pt/l    2f, tr0
118         blink   tr1, r63
119 2:
120         addi.l  r15, 8, r15
121 3:
122         pt/l    .L_pass, tr0
123         addi    r1, 2, r1
124         blink   tr0, r63
125
126 .L_pop_d:
127         pt/l    .L_pop_d_tbl, tr1
128         gettr   tr1, r20
129         shlli   r1, 2, r21
130         add     r20, r21, r20
131         ptabs/l r20, tr1
132         blink   tr1, r63
133
134 .L_pop_d_tbl:
135         fld.d   r15, 0, dr0
136         blink   tr0, r63
137         fld.d   r15, 0, dr2
138         blink   tr0, r63
139         fld.d   r15, 0, dr4
140         blink   tr0, r63
141         fld.d   r15, 0, dr6
142         blink   tr0, r63
143         fld.d   r15, 0, dr8
144         blink   tr0, r63
145         fld.d   r15, 0, dr10
146         blink   tr0, r63
147
148 .L_pass_f:
149         addi    r0, 1, r0
150         pt/l    3f, tr0
151         movi    12, r20
152         bge/l   r1, r20, tr0
153
154         pt/l    .L_pop_f, tr1
155         pt/l    2f, tr0
156         blink   tr1, r63
157 2:
158         addi.l  r15, 8, r15
159 3:
160         pt/l    .L_pass, tr0
161         addi    r1, 1, r1
162         blink   tr0, r63
163
164 .L_pop_f:
165         pt/l    .L_pop_f_tbl, tr1
166         gettr   tr1, r20
167         shlli   r1, 3, r21
168         add     r20, r21, r20
169         ptabs/l r20, tr1
170         blink   tr1, r63
171
172 .L_pop_f_tbl:
173         fld.s   r15, OFS_FLT, fr0
174         blink   tr0, r63
175         fld.s   r15, OFS_FLT, fr1
176         blink   tr0, r63
177         fld.s   r15, OFS_FLT, fr2
178         blink   tr0, r63
179         fld.s   r15, OFS_FLT, fr3
180         blink   tr0, r63
181         fld.s   r15, OFS_FLT, fr4
182         blink   tr0, r63
183         fld.s   r15, OFS_FLT, fr5
184         blink   tr0, r63
185         fld.s   r15, OFS_FLT, fr6
186         blink   tr0, r63
187         fld.s   r15, OFS_FLT, fr7
188         blink   tr0, r63
189         fld.s   r15, OFS_FLT, fr8
190         blink   tr0, r63
191         fld.s   r15, OFS_FLT, fr9
192         blink   tr0, r63
193         fld.s   r15, OFS_FLT, fr10
194         blink   tr0, r63
195         fld.s   r15, OFS_FLT, fr11
196         blink   tr0, r63
197
198 .L_pass_i:
199         pt/l    3f, tr0
200         movi    8, r20
201         bge/l   r0, r20, tr0
202
203         pt/l    .L_pop_i, tr1
204         pt/l    2f, tr0
205         blink   tr1, r63
206 2:
207         addi.l  r15, 8, r15
208 3:
209         pt/l    .L_pass, tr0
210         addi    r0, 1, r0
211         blink   tr0, r63
212
213 .L_pop_i:
214         pt/l    .L_pop_i_tbl, tr1
215         gettr   tr1, r20
216         shlli   r0, 3, r21
217         add     r20, r21, r20
218         ptabs/l r20, tr1
219         blink   tr1, r63
220
221 .L_pop_i_tbl:
222         ld.q    r15, 0, r2
223         blink   tr0, r63
224         ld.q    r15, 0, r3
225         blink   tr0, r63
226         ld.q    r15, 0, r4
227         blink   tr0, r63
228         ld.q    r15, 0, r5
229         blink   tr0, r63
230         ld.q    r15, 0, r6
231         blink   tr0, r63
232         ld.q    r15, 0, r7
233         blink   tr0, r63
234         ld.q    r15, 0, r8
235         blink   tr0, r63
236         ld.q    r15, 0, r9
237         blink   tr0, r63
238
239 .L_call_it:
240         # call function
241         pt/l    1f, tr1
242         bnei/l  r29, FFI_TYPE_STRUCT, tr1
243         add     r19, r63, r2
244 1:
245         add     r22, r63, r15
246         ptabs/l r32, tr0
247         blink   tr0, r18
248
249         pt/l    .L_ret_i, tr0
250         pt/l    .L_ret_ll, tr1
251         pt/l    .L_ret_d, tr2
252         pt/l    .L_ret_f, tr3
253         pt/l    .L_epilogue, tr4
254
255         beqi/l  r29, FFI_TYPE_INT, tr0
256         beqi/l  r29, FFI_TYPE_UINT32, tr0
257         beqi/l  r29, FFI_TYPE_SINT64, tr1
258         beqi/l  r29, FFI_TYPE_UINT64, tr1
259         beqi/l  r29, FFI_TYPE_DOUBLE, tr2
260         beqi/l  r29, FFI_TYPE_FLOAT, tr3
261
262         pt/l    .L_ret_q, tr0
263         pt/l    .L_ret_h, tr1
264
265         beqi/l  r29, FFI_TYPE_UINT8, tr0
266         beqi/l  r29, FFI_TYPE_UINT16, tr1
267         blink   tr4, r63
268
269 .L_ret_d:
270         fst.d   r31, 0, dr0
271         blink   tr4, r63
272
273 .L_ret_ll:
274         st.q    r31, 0, r2
275         blink   tr4, r63
276
277 .L_ret_f:
278         fst.s   r31, OFS_FLT, fr0
279         blink   tr4, r63
280
281 .L_ret_q:
282         st.b    r31, 0, r2
283         blink   tr4, r63
284
285 .L_ret_h:
286         st.w    r31, 0, r2
287         blink   tr4, r63
288
289 .L_ret_i:
290         st.l    r31, 0, r2
291         # Fall
292
293 .L_epilogue:
294         # Remove the space we pushed for the args
295         add     r14, r63, r15
296
297         ld.l    r15, 0, r14
298         ld.l    r15, 4, r18
299         ld.q    r15, 8, r28
300         ld.q    r15, 16, r29
301         ld.q    r15, 24, r30
302         ld.q    r15, 32, r31
303         ld.q    r15, 40, r32
304         addi.l  r15, 48, r15
305         ptabs   r18, tr0
306         blink   tr0, r63
307
308 .LFE1:
309 .ffi_call_SYSV_end:
310         .size    CNAME(ffi_call_SYSV),.ffi_call_SYSV_end-CNAME(ffi_call_SYSV)
311
312         .align  5
313 ENTRY(ffi_closure_SYSV)
314 .LFB2:
315         addi.l  r15, -136, r15
316 .LCFI3:
317         st.l    r15, 12, r18
318         st.l    r15, 8, r14
319         st.l    r15, 4, r12
320 .LCFI4:
321         add     r15, r63, r14
322 .LCFI5:
323         /* Stack layout:        
324            ...
325            64 bytes (register parameters)
326            48 bytes (floating register parameters)
327             8 bytes (result)
328             4 bytes (r18)
329             4 bytes (r14)
330             4 bytes (r12)
331             4 bytes (for align)
332            <- new stack pointer
333         */
334         fst.d   r14, 24, dr0
335         fst.d   r14, 32, dr2
336         fst.d   r14, 40, dr4
337         fst.d   r14, 48, dr6
338         fst.d   r14, 56, dr8
339         fst.d   r14, 64, dr10
340         st.q    r14, 72, r2
341         st.q    r14, 80, r3
342         st.q    r14, 88, r4
343         st.q    r14, 96, r5
344         st.q    r14, 104, r6
345         st.q    r14, 112, r7
346         st.q    r14, 120, r8
347         st.q    r14, 128, r9
348
349         add     r1, r63, r2
350         addi    r14, 16, r3
351         addi    r14, 72, r4
352         addi    r14, 24, r5
353         addi    r14, 136, r6
354 #ifdef PIC
355         movi    (((datalabel _GLOBAL_OFFSET_TABLE_-(.LPCS0-.)) >> 16) & 65535), r12
356         shori   ((datalabel _GLOBAL_OFFSET_TABLE_-(.LPCS0-.)) & 65535), r12
357 .LPCS0: ptrel/u r12, tr0
358         movi    ((ffi_closure_helper_SYSV@GOTPLT) & 65535), r1
359         gettr   tr0, r12
360         ldx.l   r1, r12, r1
361         ptabs   r1, tr0
362 #else
363         pt/l    ffi_closure_helper_SYSV, tr0
364 #endif
365         blink   tr0, r18
366
367         shlli   r2, 1, r1
368         movi    (((datalabel .L_table) >> 16) & 65535), r2
369         shori   ((datalabel .L_table) & 65535), r2
370         ldx.w   r2, r1, r1
371         add     r1, r2, r1
372         pt/l    .L_case_v, tr1
373         ptabs   r1, tr0
374         blink   tr0, r63
375
376         .align 2
377 .L_table:
378         .word   .L_case_v - datalabel .L_table  /* FFI_TYPE_VOID */
379         .word   .L_case_i - datalabel .L_table  /* FFI_TYPE_INT */
380         .word   .L_case_f - datalabel .L_table  /* FFI_TYPE_FLOAT */
381         .word   .L_case_d - datalabel .L_table  /* FFI_TYPE_DOUBLE */
382         .word   .L_case_d - datalabel .L_table  /* FFI_TYPE_LONGDOUBLE */
383         .word   .L_case_uq - datalabel .L_table /* FFI_TYPE_UINT8 */
384         .word   .L_case_q - datalabel .L_table  /* FFI_TYPE_SINT8 */
385         .word   .L_case_uh - datalabel .L_table /* FFI_TYPE_UINT16 */
386         .word   .L_case_h - datalabel .L_table  /* FFI_TYPE_SINT16 */
387         .word   .L_case_i - datalabel .L_table  /* FFI_TYPE_UINT32 */
388         .word   .L_case_i - datalabel .L_table  /* FFI_TYPE_SINT32 */
389         .word   .L_case_ll - datalabel .L_table /* FFI_TYPE_UINT64 */
390         .word   .L_case_ll - datalabel .L_table /* FFI_TYPE_SINT64 */
391         .word   .L_case_v - datalabel .L_table  /* FFI_TYPE_STRUCT */
392         .word   .L_case_i - datalabel .L_table  /* FFI_TYPE_POINTER */
393
394         .align 2
395 .L_case_d:
396         fld.d   r14, 16, dr0
397         blink   tr1, r63
398 .L_case_f:
399         fld.s   r14, 16, fr0
400         blink   tr1, r63
401 .L_case_ll:
402         ld.q    r14, 16, r2
403         blink   tr1, r63
404 .L_case_i:
405         ld.l    r14, 16, r2
406         blink   tr1, r63
407 .L_case_q:
408         ld.b    r14, 16, r2
409         blink   tr1, r63
410 .L_case_uq:
411         ld.ub   r14, 16, r2
412         blink   tr1, r63
413 .L_case_h:
414         ld.w    r14, 16, r2
415         blink   tr1, r63
416 .L_case_uh:
417         ld.uw   r14, 16, r2
418         blink   tr1, r63
419 .L_case_v:
420         add.l   r14, r63, r15
421         ld.l    r15, 4, r12
422         ld.l    r15, 8, r14
423         ld.l    r15, 12, r18
424         addi.l  r15, 136, r15
425         ptabs   r18, tr0
426         blink   tr0, r63
427
428 .LFE2:
429 .ffi_closure_SYSV_end:
430         .size    CNAME(ffi_closure_SYSV),.ffi_closure_SYSV_end-CNAME(ffi_closure_SYSV)
431
432         .section        ".eh_frame","aw",@progbits
433 __FRAME_BEGIN__:
434         .4byte  .LECIE1-.LSCIE1 /* Length of Common Information Entry */
435 .LSCIE1:
436         .4byte  0x0     /* CIE Identifier Tag */
437         .byte   0x1     /* CIE Version */
438 #ifdef PIC
439         .ascii "zR\0"   /* CIE Augmentation */
440 #else
441         .byte   0x0     /* CIE Augmentation */
442 #endif
443         .uleb128 0x1    /* CIE Code Alignment Factor */
444         .sleb128 -4     /* CIE Data Alignment Factor */
445         .byte   0x12    /* CIE RA Column */
446 #ifdef PIC
447         .uleb128 0x1    /* Augmentation size */
448         .byte   0x10    /* FDE Encoding (pcrel) */
449 #endif
450         .byte   0xc     /* DW_CFA_def_cfa */
451         .uleb128 0xf
452         .uleb128 0x0
453         .align  2
454 .LECIE1:
455 .LSFDE1:
456         .4byte  datalabel .LEFDE1-datalabel .LASFDE1    /* FDE Length */
457 .LASFDE1:
458         .4byte  datalabel .LASFDE1-datalabel __FRAME_BEGIN__
459 #ifdef PIC
460         .4byte  .LFB1-. /* FDE initial location */
461 #else
462         .4byte  .LFB1   /* FDE initial location */
463 #endif
464         .4byte  datalabel .LFE1-datalabel .LFB1 /* FDE address range */
465 #ifdef PIC
466         .uleb128 0x0    /* Augmentation size */
467 #endif
468         .byte   0x4     /* DW_CFA_advance_loc4 */
469         .4byte  datalabel .LCFI0-datalabel .LFB1
470         .byte   0xe     /* DW_CFA_def_cfa_offset */
471         .uleb128 0x30
472         .byte   0x4     /* DW_CFA_advance_loc4 */
473         .4byte  datalabel .LCFI1-datalabel .LCFI0
474         .byte   0x8e    /* DW_CFA_offset, column 0xe */
475         .uleb128 0xc
476         .byte   0x92    /* DW_CFA_offset, column 0x12 */
477         .uleb128 0xb
478         .byte   0x9c    /* DW_CFA_offset, column 0x1c */
479         .uleb128 0xa
480         .byte   0x9d    /* DW_CFA_offset, column 0x1d */
481         .uleb128 0x8
482         .byte   0x9e    /* DW_CFA_offset, column 0x1e */
483         .uleb128 0x6
484         .byte   0x9f    /* DW_CFA_offset, column 0x1f */
485         .uleb128 0x4
486         .byte   0xa0    /* DW_CFA_offset, column 0x20 */
487         .uleb128 0x2
488         .byte   0x4     /* DW_CFA_advance_loc4 */
489         .4byte  datalabel .LCFI2-datalabel .LCFI1
490         .byte   0xd     /* DW_CFA_def_cfa_register */
491         .uleb128 0xe
492         .align  2
493 .LEFDE1:
494
495 .LSFDE3:
496         .4byte  datalabel .LEFDE3-datalabel .LASFDE3    /* FDE Length */
497 .LASFDE3:
498         .4byte  datalabel .LASFDE3-datalabel __FRAME_BEGIN__
499 #ifdef PIC
500         .4byte  .LFB2-. /* FDE initial location */
501 #else
502         .4byte  .LFB2   /* FDE initial location */
503 #endif
504         .4byte  datalabel .LFE2-datalabel .LFB2 /* FDE address range */
505 #ifdef PIC
506         .uleb128 0x0    /* Augmentation size */
507 #endif
508         .byte   0x4     /* DW_CFA_advance_loc4 */
509         .4byte  datalabel .LCFI3-datalabel .LFB2
510         .byte   0xe     /* DW_CFA_def_cfa_offset */
511         .uleb128 0x88
512         .byte   0x4     /* DW_CFA_advance_loc4 */
513         .4byte  datalabel .LCFI4-datalabel .LCFI3
514         .byte   0x8c    /* DW_CFA_offset, column 0xc */
515         .uleb128 0x21
516         .byte   0x8e    /* DW_CFA_offset, column 0xe */
517         .uleb128 0x20
518         .byte   0x92    /* DW_CFA_offset, column 0x12 */
519         .uleb128 0x1f
520         .byte   0x4     /* DW_CFA_advance_loc4 */
521         .4byte  datalabel .LCFI5-datalabel .LCFI4
522         .byte   0xd     /* DW_CFA_def_cfa_register */
523         .uleb128 0xe
524         .align  2
525 .LEFDE3: