comparison libffi/src/metag/sysv.S @ 111:04ced10e8804

gcc 7
author kono
date Fri, 27 Oct 2017 22:46:09 +0900
parents
children
comparison
equal deleted inserted replaced
68:561a7518be6b 111:04ced10e8804
1 /* -----------------------------------------------------------------------
2 sysv.S - Copyright (c) 2013 Imagination Technologies Ltd.
3
4 Meta 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
18 THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
19 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 DEALINGS IN THE SOFTWARE.
26 ----------------------------------------------------------------------- */
27
28 #define LIBFFI_ASM
29 #include <fficonfig.h>
30 #include <ffi.h>
31 #ifdef HAVE_MACHINE_ASM_H
32 #include <machine/asm.h>
33 #else
34 #ifdef __USER_LABEL_PREFIX__
35 #define CONCAT1(a, b) CONCAT2(a, b)
36 #define CONCAT2(a, b) a ## b
37
38 /* Use the right prefix for global labels. */
39 #define CNAME(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
40 #else
41 #define CNAME(x) x
42 #endif
43 #define ENTRY(x) .globl CNAME(x); .type CNAME(x), %function; CNAME(x):
44 #endif
45
46 #ifdef __ELF__
47 #define LSYM(x) .x
48 #else
49 #define LSYM(x) x
50 #endif
51
52 .macro call_reg x=
53 .text
54 .balign 4
55 mov D1RtP, \x
56 swap D1RtP, PC
57 .endm
58
59 ! Save register arguments
60 .macro SAVE_ARGS
61 .text
62 .balign 4
63 setl [A0StP++], D0Ar6, D1Ar5
64 setl [A0StP++], D0Ar4, D1Ar3
65 setl [A0StP++], D0Ar2, D1Ar1
66 .endm
67
68 ! Save retrun, frame pointer and other regs
69 .macro SAVE_REGS regs=
70 .text
71 .balign 4
72 setl [A0StP++], D0FrT, D1RtP
73 ! Needs to be a pair of regs
74 .ifnc "\regs",""
75 setl [A0StP++], \regs
76 .endif
77 .endm
78
79 ! Declare a global function
80 .macro METAG_FUNC_START name
81 .text
82 .balign 4
83 ENTRY(\name)
84 .endm
85
86 ! Return registers from the stack. Reverse SAVE_REGS operation
87 .macro RET_REGS regs=, cond=
88 .ifnc "\regs", ""
89 getl \regs, [--A0StP]
90 .endif
91 getl D0FrT, D1RtP, [--A0StP]
92 .endm
93
94 ! Return arguments
95 .macro RET_ARGS
96 getl D0Ar2, D1Ar1, [--A0StP]
97 getl D0Ar4, D1Ar3, [--A0StP]
98 getl D0Ar6, D1Ar5, [--A0StP]
99 .endm
100
101
102 ! D1Ar1: fn
103 ! D0Ar2: &ecif
104 ! D1Ar3: cif->bytes
105 ! D0Ar4: fig->flags
106 ! D1Ar5: ecif.rvalue
107
108 ! This assumes we are using GNU as
109 METAG_FUNC_START ffi_call_SYSV
110 ! Save argument registers
111
112 SAVE_ARGS
113
114 ! new frame
115 mov D0FrT, A0FrP
116 add A0FrP, A0StP, #0
117
118 ! Preserve the old frame pointer
119 SAVE_REGS "D1.5, D0.5"
120
121 ! Make room for new args. cifs->bytes is the total space for input
122 ! and return arguments
123
124 add A0StP, A0StP, D1Ar3
125
126 ! Preserve cifs->bytes & fn
127 mov D0.5, D1Ar3
128 mov D1.5, D1Ar1
129
130 ! Place all of the ffi_prep_args in position
131 mov D1Ar1, A0StP
132
133 ! Call ffi_prep_args(stack, &ecif)
134 #ifdef __PIC__
135 callr D1RtP, CNAME(ffi_prep_args@PLT)
136 #else
137 callr D1RtP, CNAME(ffi_prep_args)
138 #endif
139
140 ! Restore fn pointer
141
142 ! The foreign stack should look like this
143 ! XXXXX XXXXXX <--- stack pointer
144 ! FnArgN rvalue
145 ! FnArgN+2 FnArgN+1
146 ! FnArgN+4 FnArgN+3
147 ! ....
148 !
149
150 ! A0StP now points to the first (or return) argument + 4
151
152 ! Preserve cif->bytes
153 getl D0Ar2, D1Ar1, [--A0StP]
154 getl D0Ar4, D1Ar3, [--A0StP]
155 getl D0Ar6, D1Ar5, [--A0StP]
156
157 ! Place A0StP to the first argument again
158 add A0StP, A0StP, #24 ! That's because we loaded 6 regs x 4 byte each
159
160 ! A0FrP points to the initial stack without the reserved space for the
161 ! cifs->bytes, whilst A0StP points to the stack after the space allocation
162
163 ! fn was the first argument of ffi_call_SYSV.
164 ! The stack at this point looks like this:
165 !
166 ! A0StP(on entry to _SYSV) -> Arg6 Arg5 | low
167 ! Arg4 Arg3 |
168 ! Arg2 Arg1 |
169 ! A0FrP ----> D0FrtP D1RtP |
170 ! D1.5 D0.5 |
171 ! A0StP(bf prep_args) -> FnArgn FnArgn-1 |
172 ! FnArgn-2FnArgn-3 |
173 ! ................ | <= cifs->bytes
174 ! FnArg4 FnArg3 |
175 ! A0StP (prv_A0StP+cifs->bytes) FnArg2 FnArg1 | high
176 !
177 ! fn was in Arg1 so it's located in in A0FrP+#-0xC
178 !
179
180 ! D0Re0 contains the size of arguments stored in registers
181 sub A0StP, A0StP, D0Re0
182
183 ! Arg1 is the function pointer for the foreign call. This has been
184 ! preserved in D1.5
185
186 ! Time to call (fn). Arguments should be like this:
187 ! Arg1-Arg6 are loaded to regs
188 ! The rest of the arguments are stored in stack pointed by A0StP
189
190 call_reg D1.5
191
192 ! Reset stack.
193
194 mov A0StP, A0FrP
195
196 ! Load Arg1 with the pointer to storage for the return type
197 ! This was stored in Arg5
198
199 getd D1Ar1, [A0FrP+#-20]
200
201 ! Load D0Ar2 with the return type code. This was stored in Arg4 (flags)
202
203 getd D0Ar2, [A0FrP+#-16]
204
205 ! We are ready to start processing the return value
206 ! D0Re0 (and D1Re0) hold the return value
207
208 ! If the return value is NULL, assume no return value
209 cmp D1Ar1, #0
210 beq LSYM(Lepilogue)
211
212 ! return INT
213 cmp D0Ar2, #FFI_TYPE_INT
214 ! Sadly, there is no setd{cc} instruction so we need to workaround that
215 bne .INT64
216 setd [D1Ar1], D0Re0
217 b LSYM(Lepilogue)
218
219 ! return INT64
220 .INT64:
221 cmp D0Ar2, #FFI_TYPE_SINT64
222 setleq [D1Ar1], D0Re0, D1Re0
223
224 ! return DOUBLE
225 cmp D0Ar2, #FFI_TYPE_DOUBLE
226 setl [D1AR1++], D0Re0, D1Re0
227
228 LSYM(Lepilogue):
229 ! At this point, the stack pointer points right after the argument
230 ! saved area. We need to restore 4 regs, therefore we need to move
231 ! 16 bytes ahead.
232 add A0StP, A0StP, #16
233 RET_REGS "D1.5, D0.5"
234 RET_ARGS
235 getd D0Re0, [A0StP]
236 mov A0FrP, D0FrT
237 swap D1RtP, PC
238
239 .ffi_call_SYSV_end:
240 .size CNAME(ffi_call_SYSV),.ffi_call_SYSV_end-CNAME(ffi_call_SYSV)
241
242
243 /*
244 (called by ffi_metag_trampoline)
245 void ffi_closure_SYSV (ffi_closure*)
246
247 (called by ffi_closure_SYSV)
248 unsigned int FFI_HIDDEN
249 ffi_closure_SYSV_inner (closure,respp, args)
250 ffi_closure *closure;
251 void **respp;
252 void *args;
253 */
254
255 METAG_FUNC_START ffi_closure_SYSV
256 ! We assume that D1Ar1 holds the address of the
257 ! ffi_closure struct. We will use that to fetch the
258 ! arguments. The stack pointer points to an empty space
259 ! and it is ready to store more data.
260
261 ! D1Ar1 is ready
262 ! Allocate stack space for return value
263 add A0StP, A0StP, #8
264 ! Store it to D0Ar2
265 sub D0Ar2, A0StP, #8
266
267 sub D1Ar3, A0FrP, #4
268
269 ! D1Ar3 contains the address of the original D1Ar1 argument
270 ! We need to subtract #4 later on
271
272 ! Preverve D0Ar2
273 mov D0.5, D0Ar2
274
275 #ifdef __PIC__
276 callr D1RtP, CNAME(ffi_closure_SYSV_inner@PLT)
277 #else
278 callr D1RtP, CNAME(ffi_closure_SYSV_inner)
279 #endif
280
281 ! Check the return value and store it to D0.5
282 cmp D0Re0, #FFI_TYPE_INT
283 beq .Lretint
284 cmp D0Re0, #FFI_TYPE_DOUBLE
285 beq .Lretdouble
286 .Lclosure_epilogue:
287 sub A0StP, A0StP, #8
288 RET_REGS "D1.5, D0.5"
289 RET_ARGS
290 swap D1RtP, PC
291
292 .Lretint:
293 setd [D0.5], D0Re0
294 b .Lclosure_epilogue
295 .Lretdouble:
296 setl [D0.5++], D0Re0, D1Re0
297 b .Lclosure_epilogue
298 .ffi_closure_SYSV_end:
299 .size CNAME(ffi_closure_SYSV),.ffi_closure_SYSV_end-CNAME(ffi_closure_SYSV)
300
301
302 ENTRY(ffi_metag_trampoline)
303 SAVE_ARGS
304 ! New frame
305 mov A0FrP, A0StP
306 SAVE_REGS "D1.5, D0.5"
307 mov D0.5, PC
308 ! Load D1Ar1 the value of ffi_metag_trampoline
309 getd D1Ar1, [D0.5 + #8]
310 ! Jump to ffi_closure_SYSV
311 getd PC, [D0.5 + #12]