OSDN Git Service

* src/powerpc/ffi.c (ffi_prep_cif_machdep <FFI_LINUX64>): Correct
[pf3gnuchains/gcc-fork.git] / libffi / src / powerpc / linux64_closure.S
1 #define LIBFFI_ASM
2 #include <fficonfig.h>
3 #include <ffi.h>
4
5         .file   "linux64_closure.S"
6
7 #ifdef __powerpc64__
8         .hidden ffi_closure_LINUX64, .ffi_closure_LINUX64
9         .globl  ffi_closure_LINUX64, .ffi_closure_LINUX64
10         .section        ".opd","aw"
11         .align  3
12 ffi_closure_LINUX64:
13         .quad   .ffi_closure_LINUX64,.TOC.@tocbase,0
14         .size   ffi_closure_LINUX64,24
15         .type   .ffi_closure_LINUX64,@function
16         .text
17 .ffi_closure_LINUX64:
18 .LFB1:
19         # save general regs into parm save area
20         std     %r3, 48(%r1)
21         std     %r4, 56(%r1)
22         std     %r5, 64(%r1)
23         std     %r6, 72(%r1)
24         mflr    %r0
25
26         std     %r7, 80(%r1)
27         std     %r8, 88(%r1)
28         std     %r9, 96(%r1)
29         std     %r10, 104(%r1)
30         std     %r0, 16(%r1)
31
32         # mandatory 48 bytes special reg save area + 64 bytes parm save area
33         # + 16 bytes retval area + 13*8 bytes fpr save area + round to 16
34         stdu    %r1, -240(%r1)
35 .LCFI0:
36
37         # next save fpr 1 to fpr 13
38         stfd  %f1, 128+(0*8)(%r1)
39         stfd  %f2, 128+(1*8)(%r1)
40         stfd  %f3, 128+(2*8)(%r1)
41         stfd  %f4, 128+(3*8)(%r1)
42         stfd  %f5, 128+(4*8)(%r1)
43         stfd  %f6, 128+(5*8)(%r1)
44         stfd  %f7, 128+(6*8)(%r1)
45         stfd  %f8, 128+(7*8)(%r1)
46         stfd  %f9, 128+(8*8)(%r1)
47         stfd  %f10, 128+(9*8)(%r1)
48         stfd  %f11, 128+(10*8)(%r1)
49         stfd  %f12, 128+(11*8)(%r1)
50         stfd  %f13, 128+(12*8)(%r1)
51
52         # set up registers for the routine that actually does the work
53         # get the context pointer from the trampoline
54         mr %r3, %r11
55
56         # now load up the pointer to the result storage
57         addi %r4, %r1, 112
58
59         # now load up the pointer to the parameter save area
60         # in the previous frame
61         addi %r5, %r1, 240 + 48
62
63         # now load up the pointer to the saved fpr registers */
64         addi %r6, %r1, 128
65
66         # make the call
67         bl .ffi_closure_helper_LINUX64
68 .Lret:
69
70         # now r3 contains the return type
71         # so use it to look up in a table
72         # so we know how to deal with each type
73
74         # look up the proper starting point in table 
75         # by using return type as offset
76         mflr %r4                # move address of .Lret to r4
77         sldi %r3, %r3, 4        # now multiply return type by 16
78         addi %r4, %r4, .Lret_type0 - .Lret
79         ld %r0, 240+16(%r1)
80         add %r3, %r3, %r4       # add contents of table to table address
81         mtctr %r3
82         bctr                    # jump to it
83
84 # Each of the ret_typeX code fragments has to be exactly 16 bytes long
85 # (4 instructions). For cache effectiveness we align to a 16 byte boundary
86 # first.
87         .align 4
88
89 .Lret_type0:
90 # case FFI_TYPE_VOID
91         mtlr %r0
92         addi %r1, %r1, 240
93         blr
94         nop
95 # case FFI_TYPE_INT
96         lwa %r3, 112+4(%r1)
97         mtlr %r0
98         addi %r1, %r1, 240
99         blr
100 # case FFI_TYPE_FLOAT
101         lfs %f1, 112+0(%r1)
102         mtlr %r0
103         addi %r1, %r1, 240
104         blr
105 # case FFI_TYPE_DOUBLE
106         lfd %f1, 112+0(%r1)
107         mtlr %r0
108         addi %r1, %r1, 240
109         blr
110 # case FFI_TYPE_LONGDOUBLE
111         lfd %f1, 112+0(%r1)
112         mtlr %r0
113         lfd %f2, 112+8(%r1)
114         b .Lfinish
115 # case FFI_TYPE_UINT8
116         lbz %r3, 112+7(%r1)
117         mtlr %r0
118         addi %r1, %r1, 240
119         blr
120 # case FFI_TYPE_SINT8
121         lbz %r3, 112+7(%r1)
122         extsb %r3,%r3
123         mtlr %r0
124         b .Lfinish
125 # case FFI_TYPE_UINT16
126         lhz %r3, 112+6(%r1)
127         mtlr %r0
128 .Lfinish:
129         addi %r1, %r1, 240
130         blr
131 # case FFI_TYPE_SINT16
132         lha %r3, 112+6(%r1)
133         mtlr %r0
134         addi %r1, %r1, 240
135         blr
136 # case FFI_TYPE_UINT32
137         lwz %r3, 112+4(%r1)
138         mtlr %r0
139         addi %r1, %r1, 240
140         blr
141 # case FFI_TYPE_SINT32
142         lwa %r3, 112+4(%r1)
143         mtlr %r0
144         addi %r1, %r1, 240
145         blr
146 # case FFI_TYPE_UINT64
147         ld %r3, 112+0(%r1)
148         mtlr %r0
149         addi %r1, %r1, 240
150         blr
151 # case FFI_TYPE_SINT64
152         ld %r3, 112+0(%r1)
153         mtlr %r0
154         addi %r1, %r1, 240
155         blr
156 # case FFI_TYPE_STRUCT
157         mtlr %r0
158         addi %r1, %r1, 240
159         blr
160         nop
161 # case FFI_TYPE_POINTER
162         ld %r3, 112+0(%r1)
163         mtlr %r0
164         addi %r1, %r1, 240
165         blr
166 # esac
167 .LFE1:
168         .long   0
169         .byte   0,12,0,1,128,0,0,0
170         .size   .ffi_closure_LINUX64,.-.ffi_closure_LINUX64
171
172         .section        .eh_frame,EH_FRAME_FLAGS,@progbits
173 .Lframe1:
174         .4byte  .LECIE1-.LSCIE1  # Length of Common Information Entry
175 .LSCIE1:
176         .4byte  0x0      # CIE Identifier Tag
177         .byte   0x1      # CIE Version
178         .ascii "zR\0"    # CIE Augmentation
179         .uleb128 0x1     # CIE Code Alignment Factor
180         .sleb128 -8      # CIE Data Alignment Factor
181         .byte   0x41     # CIE RA Column
182         .uleb128 0x1     # Augmentation size
183         .byte   0x14     # FDE Encoding (pcrel udata8)
184         .byte   0xc      # DW_CFA_def_cfa
185         .uleb128 0x1
186         .uleb128 0x0
187         .align 3
188 .LECIE1:
189 .LSFDE1:
190         .4byte  .LEFDE1-.LASFDE1         # FDE Length
191 .LASFDE1:
192         .4byte  .LASFDE1-.Lframe1        # FDE CIE offset
193         .8byte  .LFB1-.  # FDE initial location
194         .8byte  .LFE1-.LFB1      # FDE address range
195         .uleb128 0x0     # Augmentation size
196         .byte   0x2      # DW_CFA_advance_loc1
197         .byte   .LCFI0-.LFB1
198         .byte   0xe      # DW_CFA_def_cfa_offset
199         .uleb128 240
200         .byte   0x11     # DW_CFA_offset_extended_sf
201         .uleb128 0x41
202         .sleb128 -2
203         .align 3
204 .LEFDE1:
205 #endif