annotate libffi/src/metag/sysv.S @ 158:494b0b89df80 default tip

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