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