Thomas Heller | d4c9320 | 2006-03-08 19:35:11 +0000 | [diff] [blame] | 1 | /* ----------------------------------------------------------------------- |
doko@ubuntu.com | 2a91876 | 2012-06-26 17:56:44 +0200 | [diff] [blame] | 2 | sysv.S - Copyright (c) 1998, 2008, 2011 Red Hat, Inc. |
| 3 | Copyright (c) 2011 Plausible Labs Cooperative, Inc. |
Thomas Heller | d4c9320 | 2006-03-08 19:35:11 +0000 | [diff] [blame] | 4 | |
| 5 | ARM Foreign Function Interface |
| 6 | |
| 7 | Permission is hereby granted, free of charge, to any person obtaining |
| 8 | a copy of this software and associated documentation files (the |
| 9 | ``Software''), to deal in the Software without restriction, including |
| 10 | without limitation the rights to use, copy, modify, merge, publish, |
| 11 | distribute, sublicense, and/or sell copies of the Software, and to |
| 12 | permit persons to whom the Software is furnished to do so, subject to |
| 13 | the following conditions: |
| 14 | |
| 15 | The above copyright notice and this permission notice shall be included |
| 16 | in all copies or substantial portions of the Software. |
| 17 | |
Christian Heimes | 7864476 | 2008-03-04 23:39:23 +0000 | [diff] [blame] | 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. |
Thomas Heller | d4c9320 | 2006-03-08 19:35:11 +0000 | [diff] [blame] | 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 |
doko@ubuntu.com | 2a91876 | 2012-06-26 17:56:44 +0200 | [diff] [blame] | 43 | #ifdef __APPLE__ |
| 44 | #define ENTRY(x) .globl _##x; _##x: |
| 45 | #else |
Thomas Heller | d4c9320 | 2006-03-08 19:35:11 +0000 | [diff] [blame] | 46 | #define ENTRY(x) .globl CNAME(x); .type CNAME(x),%function; CNAME(x): |
doko@ubuntu.com | 2a91876 | 2012-06-26 17:56:44 +0200 | [diff] [blame] | 47 | #endif /* __APPLE__ */ |
Thomas Heller | d4c9320 | 2006-03-08 19:35:11 +0000 | [diff] [blame] | 48 | #endif |
| 49 | |
| 50 | #ifdef __ELF__ |
| 51 | #define LSYM(x) .x |
| 52 | #else |
| 53 | #define LSYM(x) x |
| 54 | #endif |
| 55 | |
doko@ubuntu.com | 2a91876 | 2012-06-26 17:56:44 +0200 | [diff] [blame] | 56 | /* Use the SOFTFP return value ABI on Mac OS X, as per the iOS ABI |
| 57 | Function Call Guide */ |
| 58 | #ifdef __APPLE__ |
| 59 | #define __SOFTFP__ |
| 60 | #endif |
| 61 | |
Thomas Heller | d4c9320 | 2006-03-08 19:35:11 +0000 | [diff] [blame] | 62 | /* We need a better way of testing for this, but for now, this is all |
| 63 | we can do. */ |
| 64 | @ This selects the minimum architecture level required. |
| 65 | #define __ARM_ARCH__ 3 |
| 66 | |
| 67 | #if defined(__ARM_ARCH_4__) || defined(__ARM_ARCH_4T__) |
| 68 | # undef __ARM_ARCH__ |
| 69 | # define __ARM_ARCH__ 4 |
| 70 | #endif |
| 71 | |
| 72 | #if defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5T__) \ |
| 73 | || defined(__ARM_ARCH_5E__) || defined(__ARM_ARCH_5TE__) \ |
| 74 | || defined(__ARM_ARCH_5TEJ__) |
| 75 | # undef __ARM_ARCH__ |
| 76 | # define __ARM_ARCH__ 5 |
| 77 | #endif |
| 78 | |
| 79 | #if defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \ |
| 80 | || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) \ |
Matthias Klose | a834975 | 2010-03-15 13:25:28 +0000 | [diff] [blame] | 81 | || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) \ |
| 82 | || defined(__ARM_ARCH_6M__) |
Thomas Heller | d4c9320 | 2006-03-08 19:35:11 +0000 | [diff] [blame] | 83 | # undef __ARM_ARCH__ |
| 84 | # define __ARM_ARCH__ 6 |
| 85 | #endif |
| 86 | |
Matthias Klose | a834975 | 2010-03-15 13:25:28 +0000 | [diff] [blame] | 87 | #if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) \ |
| 88 | || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) \ |
| 89 | || defined(__ARM_ARCH_7EM__) |
| 90 | # undef __ARM_ARCH__ |
| 91 | # define __ARM_ARCH__ 7 |
| 92 | #endif |
| 93 | |
Thomas Heller | d4c9320 | 2006-03-08 19:35:11 +0000 | [diff] [blame] | 94 | #if __ARM_ARCH__ >= 5 |
| 95 | # define call_reg(x) blx x |
| 96 | #elif defined (__ARM_ARCH_4T__) |
| 97 | # define call_reg(x) mov lr, pc ; bx x |
| 98 | # if defined(__thumb__) || defined(__THUMB_INTERWORK__) |
| 99 | # define __INTERWORKING__ |
| 100 | # endif |
| 101 | #else |
| 102 | # define call_reg(x) mov lr, pc ; mov pc, x |
| 103 | #endif |
| 104 | |
Christian Heimes | 7864476 | 2008-03-04 23:39:23 +0000 | [diff] [blame] | 105 | /* Conditionally compile unwinder directives. */ |
| 106 | #ifdef __ARM_EABI__ |
| 107 | #define UNWIND |
| 108 | #else |
| 109 | #define UNWIND @ |
| 110 | #endif |
| 111 | |
doko@ubuntu.com | 736a913 | 2014-08-09 22:36:35 +0200 | [diff] [blame] | 112 | .syntax unified |
| 113 | |
Thomas Heller | d4c9320 | 2006-03-08 19:35:11 +0000 | [diff] [blame] | 114 | #if defined(__thumb__) && !defined(__THUMB_INTERWORK__) |
doko@ubuntu.com | 736a913 | 2014-08-09 22:36:35 +0200 | [diff] [blame] | 115 | #define ARM_FUNC_START(name) \ |
| 116 | .text; \ |
| 117 | .align 2; \ |
| 118 | .thumb; \ |
| 119 | .thumb_func; \ |
| 120 | ENTRY(name); \ |
| 121 | bx pc; \ |
| 122 | nop; \ |
| 123 | .arm; \ |
| 124 | UNWIND .fnstart; \ |
| 125 | _L__##name: |
doko@ubuntu.com | 2a91876 | 2012-06-26 17:56:44 +0200 | [diff] [blame] | 126 | #else |
doko@ubuntu.com | 736a913 | 2014-08-09 22:36:35 +0200 | [diff] [blame] | 127 | #define ARM_FUNC_START(name) \ |
| 128 | .text; \ |
| 129 | .align 2; \ |
| 130 | .arm; \ |
| 131 | ENTRY(name); \ |
Christian Heimes | 7864476 | 2008-03-04 23:39:23 +0000 | [diff] [blame] | 132 | UNWIND .fnstart |
Thomas Heller | d4c9320 | 2006-03-08 19:35:11 +0000 | [diff] [blame] | 133 | #endif |
| 134 | |
| 135 | .macro RETLDM regs=, cond=, dirn=ia |
| 136 | #if defined (__INTERWORKING__) |
| 137 | .ifc "\regs","" |
| 138 | ldr\cond lr, [sp], #4 |
| 139 | .else |
| 140 | ldm\cond\dirn sp!, {\regs, lr} |
| 141 | .endif |
| 142 | bx\cond lr |
| 143 | #else |
| 144 | .ifc "\regs","" |
| 145 | ldr\cond pc, [sp], #4 |
| 146 | .else |
| 147 | ldm\cond\dirn sp!, {\regs, pc} |
| 148 | .endif |
| 149 | #endif |
| 150 | .endm |
| 151 | |
Thomas Heller | d4c9320 | 2006-03-08 19:35:11 +0000 | [diff] [blame] | 152 | @ r0: ffi_prep_args |
| 153 | @ r1: &ecif |
| 154 | @ r2: cif->bytes |
| 155 | @ r3: fig->flags |
| 156 | @ sp+0: ecif.rvalue |
Thomas Heller | d4c9320 | 2006-03-08 19:35:11 +0000 | [diff] [blame] | 157 | |
| 158 | @ This assumes we are using gas. |
doko@ubuntu.com | 736a913 | 2014-08-09 22:36:35 +0200 | [diff] [blame] | 159 | ARM_FUNC_START(ffi_call_SYSV) |
Thomas Heller | d4c9320 | 2006-03-08 19:35:11 +0000 | [diff] [blame] | 160 | @ Save registers |
| 161 | stmfd sp!, {r0-r3, fp, lr} |
Christian Heimes | 7864476 | 2008-03-04 23:39:23 +0000 | [diff] [blame] | 162 | UNWIND .save {r0-r3, fp, lr} |
Thomas Heller | d4c9320 | 2006-03-08 19:35:11 +0000 | [diff] [blame] | 163 | mov fp, sp |
| 164 | |
Christian Heimes | 7864476 | 2008-03-04 23:39:23 +0000 | [diff] [blame] | 165 | UNWIND .setfp fp, sp |
| 166 | |
Thomas Heller | d4c9320 | 2006-03-08 19:35:11 +0000 | [diff] [blame] | 167 | @ Make room for all of the new args. |
| 168 | sub sp, fp, r2 |
| 169 | |
| 170 | @ Place all of the ffi_prep_args in position |
Thomas Heller | d4c9320 | 2006-03-08 19:35:11 +0000 | [diff] [blame] | 171 | mov r0, sp |
| 172 | @ r1 already set |
| 173 | |
| 174 | @ Call ffi_prep_args(stack, &ecif) |
doko@ubuntu.com | 736a913 | 2014-08-09 22:36:35 +0200 | [diff] [blame] | 175 | bl CNAME(ffi_prep_args_SYSV) |
Thomas Heller | d4c9320 | 2006-03-08 19:35:11 +0000 | [diff] [blame] | 176 | |
| 177 | @ move first 4 parameters in registers |
| 178 | ldmia sp, {r0-r3} |
| 179 | |
| 180 | @ and adjust stack |
doko@ubuntu.com | 2a91876 | 2012-06-26 17:56:44 +0200 | [diff] [blame] | 181 | sub lr, fp, sp @ cif->bytes == fp - sp |
| 182 | ldr ip, [fp] @ load fn() in advance |
| 183 | cmp lr, #16 |
| 184 | movhs lr, #16 |
| 185 | add sp, sp, lr |
Thomas Heller | d4c9320 | 2006-03-08 19:35:11 +0000 | [diff] [blame] | 186 | |
| 187 | @ call (fn) (...) |
Thomas Heller | d4c9320 | 2006-03-08 19:35:11 +0000 | [diff] [blame] | 188 | call_reg(ip) |
| 189 | |
| 190 | @ Remove the space we pushed for the args |
| 191 | mov sp, fp |
| 192 | |
| 193 | @ Load r2 with the pointer to storage for the return value |
| 194 | ldr r2, [sp, #24] |
| 195 | |
| 196 | @ Load r3 with the return type code |
| 197 | ldr r3, [sp, #12] |
| 198 | |
| 199 | @ If the return value pointer is NULL, assume no return value. |
| 200 | cmp r2, #0 |
| 201 | beq LSYM(Lepilogue) |
| 202 | |
| 203 | @ return INT |
| 204 | cmp r3, #FFI_TYPE_INT |
Matthias Klose | a834975 | 2010-03-15 13:25:28 +0000 | [diff] [blame] | 205 | #if defined(__SOFTFP__) || defined(__ARM_EABI__) |
Thomas Heller | d4c9320 | 2006-03-08 19:35:11 +0000 | [diff] [blame] | 206 | cmpne r3, #FFI_TYPE_FLOAT |
| 207 | #endif |
| 208 | streq r0, [r2] |
| 209 | beq LSYM(Lepilogue) |
| 210 | |
| 211 | @ return INT64 |
| 212 | cmp r3, #FFI_TYPE_SINT64 |
Matthias Klose | a834975 | 2010-03-15 13:25:28 +0000 | [diff] [blame] | 213 | #if defined(__SOFTFP__) || defined(__ARM_EABI__) |
Thomas Heller | d4c9320 | 2006-03-08 19:35:11 +0000 | [diff] [blame] | 214 | cmpne r3, #FFI_TYPE_DOUBLE |
| 215 | #endif |
doko@ubuntu.com | 736a913 | 2014-08-09 22:36:35 +0200 | [diff] [blame] | 216 | stmiaeq r2, {r0, r1} |
Thomas Heller | d4c9320 | 2006-03-08 19:35:11 +0000 | [diff] [blame] | 217 | |
Matthias Klose | a834975 | 2010-03-15 13:25:28 +0000 | [diff] [blame] | 218 | #if !defined(__SOFTFP__) && !defined(__ARM_EABI__) |
Thomas Heller | d4c9320 | 2006-03-08 19:35:11 +0000 | [diff] [blame] | 219 | beq LSYM(Lepilogue) |
| 220 | |
| 221 | @ return FLOAT |
| 222 | cmp r3, #FFI_TYPE_FLOAT |
| 223 | stfeqs f0, [r2] |
| 224 | beq LSYM(Lepilogue) |
| 225 | |
| 226 | @ return DOUBLE or LONGDOUBLE |
| 227 | cmp r3, #FFI_TYPE_DOUBLE |
| 228 | stfeqd f0, [r2] |
| 229 | #endif |
| 230 | |
| 231 | LSYM(Lepilogue): |
doko@ubuntu.com | 2a91876 | 2012-06-26 17:56:44 +0200 | [diff] [blame] | 232 | #if defined (__INTERWORKING__) |
| 233 | ldmia sp!, {r0-r3,fp, lr} |
| 234 | bx lr |
| 235 | #else |
| 236 | ldmia sp!, {r0-r3,fp, pc} |
| 237 | #endif |
Thomas Heller | d4c9320 | 2006-03-08 19:35:11 +0000 | [diff] [blame] | 238 | |
| 239 | .ffi_call_SYSV_end: |
Christian Heimes | 7864476 | 2008-03-04 23:39:23 +0000 | [diff] [blame] | 240 | UNWIND .fnend |
doko@ubuntu.com | 2a91876 | 2012-06-26 17:56:44 +0200 | [diff] [blame] | 241 | #ifdef __ELF__ |
Thomas Heller | d4c9320 | 2006-03-08 19:35:11 +0000 | [diff] [blame] | 242 | .size CNAME(ffi_call_SYSV),.ffi_call_SYSV_end-CNAME(ffi_call_SYSV) |
doko@ubuntu.com | 2a91876 | 2012-06-26 17:56:44 +0200 | [diff] [blame] | 243 | #endif |
| 244 | |
Thomas Heller | d4c9320 | 2006-03-08 19:35:11 +0000 | [diff] [blame] | 245 | |
Christian Heimes | 7864476 | 2008-03-04 23:39:23 +0000 | [diff] [blame] | 246 | /* |
| 247 | unsigned int FFI_HIDDEN |
doko@ubuntu.com | 736a913 | 2014-08-09 22:36:35 +0200 | [diff] [blame] | 248 | ffi_closure_inner (closure, respp, args) |
Christian Heimes | 7864476 | 2008-03-04 23:39:23 +0000 | [diff] [blame] | 249 | ffi_closure *closure; |
| 250 | void **respp; |
| 251 | void *args; |
| 252 | */ |
| 253 | |
doko@ubuntu.com | 736a913 | 2014-08-09 22:36:35 +0200 | [diff] [blame] | 254 | ARM_FUNC_START(ffi_closure_SYSV) |
Christian Heimes | 7864476 | 2008-03-04 23:39:23 +0000 | [diff] [blame] | 255 | UNWIND .pad #16 |
| 256 | add ip, sp, #16 |
| 257 | stmfd sp!, {ip, lr} |
| 258 | UNWIND .save {r0, lr} |
| 259 | add r2, sp, #8 |
doko@ubuntu.com | 2a91876 | 2012-06-26 17:56:44 +0200 | [diff] [blame] | 260 | UNWIND .pad #16 |
Christian Heimes | 7864476 | 2008-03-04 23:39:23 +0000 | [diff] [blame] | 261 | sub sp, sp, #16 |
| 262 | str sp, [sp, #8] |
| 263 | add r1, sp, #8 |
doko@ubuntu.com | 736a913 | 2014-08-09 22:36:35 +0200 | [diff] [blame] | 264 | bl CNAME(ffi_closure_inner) |
Christian Heimes | 7864476 | 2008-03-04 23:39:23 +0000 | [diff] [blame] | 265 | cmp r0, #FFI_TYPE_INT |
| 266 | beq .Lretint |
| 267 | |
| 268 | cmp r0, #FFI_TYPE_FLOAT |
Matthias Klose | a834975 | 2010-03-15 13:25:28 +0000 | [diff] [blame] | 269 | #if defined(__SOFTFP__) || defined(__ARM_EABI__) |
Christian Heimes | 7864476 | 2008-03-04 23:39:23 +0000 | [diff] [blame] | 270 | beq .Lretint |
| 271 | #else |
| 272 | beq .Lretfloat |
| 273 | #endif |
| 274 | |
| 275 | cmp r0, #FFI_TYPE_DOUBLE |
Matthias Klose | a834975 | 2010-03-15 13:25:28 +0000 | [diff] [blame] | 276 | #if defined(__SOFTFP__) || defined(__ARM_EABI__) |
Christian Heimes | 7864476 | 2008-03-04 23:39:23 +0000 | [diff] [blame] | 277 | beq .Lretlonglong |
| 278 | #else |
| 279 | beq .Lretdouble |
| 280 | #endif |
| 281 | |
| 282 | cmp r0, #FFI_TYPE_LONGDOUBLE |
Matthias Klose | a834975 | 2010-03-15 13:25:28 +0000 | [diff] [blame] | 283 | #if defined(__SOFTFP__) || defined(__ARM_EABI__) |
Christian Heimes | 7864476 | 2008-03-04 23:39:23 +0000 | [diff] [blame] | 284 | beq .Lretlonglong |
| 285 | #else |
| 286 | beq .Lretlongdouble |
| 287 | #endif |
| 288 | |
| 289 | cmp r0, #FFI_TYPE_SINT64 |
| 290 | beq .Lretlonglong |
| 291 | .Lclosure_epilogue: |
| 292 | add sp, sp, #16 |
| 293 | ldmfd sp, {sp, pc} |
| 294 | .Lretint: |
| 295 | ldr r0, [sp] |
| 296 | b .Lclosure_epilogue |
| 297 | .Lretlonglong: |
| 298 | ldr r0, [sp] |
| 299 | ldr r1, [sp, #4] |
| 300 | b .Lclosure_epilogue |
| 301 | |
Matthias Klose | a834975 | 2010-03-15 13:25:28 +0000 | [diff] [blame] | 302 | #if !defined(__SOFTFP__) && !defined(__ARM_EABI__) |
Christian Heimes | 7864476 | 2008-03-04 23:39:23 +0000 | [diff] [blame] | 303 | .Lretfloat: |
| 304 | ldfs f0, [sp] |
| 305 | b .Lclosure_epilogue |
| 306 | .Lretdouble: |
| 307 | ldfd f0, [sp] |
| 308 | b .Lclosure_epilogue |
| 309 | .Lretlongdouble: |
| 310 | ldfd f0, [sp] |
| 311 | b .Lclosure_epilogue |
| 312 | #endif |
| 313 | |
| 314 | .ffi_closure_SYSV_end: |
| 315 | UNWIND .fnend |
doko@ubuntu.com | 2a91876 | 2012-06-26 17:56:44 +0200 | [diff] [blame] | 316 | #ifdef __ELF__ |
Christian Heimes | 7864476 | 2008-03-04 23:39:23 +0000 | [diff] [blame] | 317 | .size CNAME(ffi_closure_SYSV),.ffi_closure_SYSV_end-CNAME(ffi_closure_SYSV) |
doko@ubuntu.com | 2a91876 | 2012-06-26 17:56:44 +0200 | [diff] [blame] | 318 | #endif |
| 319 | |
| 320 | |
| 321 | /* Below are VFP hard-float ABI call and closure implementations. |
| 322 | Add VFP FPU directive here. This is only compiled into the library |
| 323 | under EABI. */ |
| 324 | #ifdef __ARM_EABI__ |
| 325 | .fpu vfp |
| 326 | |
| 327 | @ r0: fn |
| 328 | @ r1: &ecif |
| 329 | @ r2: cif->bytes |
| 330 | @ r3: fig->flags |
| 331 | @ sp+0: ecif.rvalue |
| 332 | |
doko@ubuntu.com | 736a913 | 2014-08-09 22:36:35 +0200 | [diff] [blame] | 333 | ARM_FUNC_START(ffi_call_VFP) |
doko@ubuntu.com | 2a91876 | 2012-06-26 17:56:44 +0200 | [diff] [blame] | 334 | @ Save registers |
| 335 | stmfd sp!, {r0-r3, fp, lr} |
| 336 | UNWIND .save {r0-r3, fp, lr} |
| 337 | mov fp, sp |
| 338 | UNWIND .setfp fp, sp |
| 339 | |
| 340 | @ Make room for all of the new args. |
| 341 | sub sp, sp, r2 |
| 342 | |
| 343 | @ Make room for loading VFP args |
| 344 | sub sp, sp, #64 |
| 345 | |
| 346 | @ Place all of the ffi_prep_args in position |
| 347 | mov r0, sp |
| 348 | @ r1 already set |
| 349 | sub r2, fp, #64 @ VFP scratch space |
| 350 | |
| 351 | @ Call ffi_prep_args(stack, &ecif, vfp_space) |
doko@ubuntu.com | 736a913 | 2014-08-09 22:36:35 +0200 | [diff] [blame] | 352 | bl CNAME(ffi_prep_args_VFP) |
doko@ubuntu.com | 2a91876 | 2012-06-26 17:56:44 +0200 | [diff] [blame] | 353 | |
| 354 | @ Load VFP register args if needed |
| 355 | cmp r0, #0 |
doko@ubuntu.com | 736a913 | 2014-08-09 22:36:35 +0200 | [diff] [blame] | 356 | mov ip, fp |
doko@ubuntu.com | 2a91876 | 2012-06-26 17:56:44 +0200 | [diff] [blame] | 357 | beq LSYM(Lbase_args) |
| 358 | |
| 359 | @ Load only d0 if possible |
| 360 | cmp r0, #3 |
| 361 | sub ip, fp, #64 |
| 362 | flddle d0, [ip] |
Chih-Hung Hsieh | ffb56c0 | 2018-01-17 15:01:59 -0800 | [diff] [blame^] | 363 | vldmiagt ip, {d0-d7} |
doko@ubuntu.com | 2a91876 | 2012-06-26 17:56:44 +0200 | [diff] [blame] | 364 | |
| 365 | LSYM(Lbase_args): |
| 366 | @ move first 4 parameters in registers |
| 367 | ldmia sp, {r0-r3} |
| 368 | |
| 369 | @ and adjust stack |
| 370 | sub lr, ip, sp @ cif->bytes == (fp - 64) - sp |
| 371 | ldr ip, [fp] @ load fn() in advance |
| 372 | cmp lr, #16 |
| 373 | movhs lr, #16 |
| 374 | add sp, sp, lr |
| 375 | |
| 376 | @ call (fn) (...) |
| 377 | call_reg(ip) |
| 378 | |
| 379 | @ Remove the space we pushed for the args |
| 380 | mov sp, fp |
| 381 | |
| 382 | @ Load r2 with the pointer to storage for |
| 383 | @ the return value |
| 384 | ldr r2, [sp, #24] |
| 385 | |
| 386 | @ Load r3 with the return type code |
| 387 | ldr r3, [sp, #12] |
| 388 | |
| 389 | @ If the return value pointer is NULL, |
| 390 | @ assume no return value. |
| 391 | cmp r2, #0 |
| 392 | beq LSYM(Lepilogue_vfp) |
| 393 | |
| 394 | cmp r3, #FFI_TYPE_INT |
| 395 | streq r0, [r2] |
| 396 | beq LSYM(Lepilogue_vfp) |
| 397 | |
| 398 | cmp r3, #FFI_TYPE_SINT64 |
Chih-Hung Hsieh | ffb56c0 | 2018-01-17 15:01:59 -0800 | [diff] [blame^] | 399 | stmiaeq r2, {r0, r1} |
doko@ubuntu.com | 2a91876 | 2012-06-26 17:56:44 +0200 | [diff] [blame] | 400 | beq LSYM(Lepilogue_vfp) |
| 401 | |
| 402 | cmp r3, #FFI_TYPE_FLOAT |
| 403 | fstseq s0, [r2] |
| 404 | beq LSYM(Lepilogue_vfp) |
| 405 | |
| 406 | cmp r3, #FFI_TYPE_DOUBLE |
| 407 | fstdeq d0, [r2] |
| 408 | beq LSYM(Lepilogue_vfp) |
| 409 | |
| 410 | cmp r3, #FFI_TYPE_STRUCT_VFP_FLOAT |
| 411 | cmpne r3, #FFI_TYPE_STRUCT_VFP_DOUBLE |
Chih-Hung Hsieh | ffb56c0 | 2018-01-17 15:01:59 -0800 | [diff] [blame^] | 412 | vstmiaeq r2, {d0-d3} |
doko@ubuntu.com | 2a91876 | 2012-06-26 17:56:44 +0200 | [diff] [blame] | 413 | |
| 414 | LSYM(Lepilogue_vfp): |
| 415 | RETLDM "r0-r3,fp" |
| 416 | |
| 417 | .ffi_call_VFP_end: |
| 418 | UNWIND .fnend |
| 419 | .size CNAME(ffi_call_VFP),.ffi_call_VFP_end-CNAME(ffi_call_VFP) |
| 420 | |
| 421 | |
doko@ubuntu.com | 736a913 | 2014-08-09 22:36:35 +0200 | [diff] [blame] | 422 | ARM_FUNC_START(ffi_closure_VFP) |
Chih-Hung Hsieh | ffb56c0 | 2018-01-17 15:01:59 -0800 | [diff] [blame^] | 423 | vpush {d0-d7} |
doko@ubuntu.com | 2a91876 | 2012-06-26 17:56:44 +0200 | [diff] [blame] | 424 | @ r0-r3, then d0-d7 |
| 425 | UNWIND .pad #80 |
| 426 | add ip, sp, #80 |
| 427 | stmfd sp!, {ip, lr} |
| 428 | UNWIND .save {r0, lr} |
| 429 | add r2, sp, #72 |
| 430 | add r3, sp, #8 |
| 431 | UNWIND .pad #72 |
| 432 | sub sp, sp, #72 |
| 433 | str sp, [sp, #64] |
| 434 | add r1, sp, #64 |
doko@ubuntu.com | 736a913 | 2014-08-09 22:36:35 +0200 | [diff] [blame] | 435 | bl CNAME(ffi_closure_inner) |
doko@ubuntu.com | 2a91876 | 2012-06-26 17:56:44 +0200 | [diff] [blame] | 436 | |
| 437 | cmp r0, #FFI_TYPE_INT |
| 438 | beq .Lretint_vfp |
| 439 | |
| 440 | cmp r0, #FFI_TYPE_FLOAT |
| 441 | beq .Lretfloat_vfp |
| 442 | |
| 443 | cmp r0, #FFI_TYPE_DOUBLE |
| 444 | cmpne r0, #FFI_TYPE_LONGDOUBLE |
| 445 | beq .Lretdouble_vfp |
| 446 | |
| 447 | cmp r0, #FFI_TYPE_SINT64 |
| 448 | beq .Lretlonglong_vfp |
| 449 | |
| 450 | cmp r0, #FFI_TYPE_STRUCT_VFP_FLOAT |
| 451 | beq .Lretfloat_struct_vfp |
| 452 | |
| 453 | cmp r0, #FFI_TYPE_STRUCT_VFP_DOUBLE |
| 454 | beq .Lretdouble_struct_vfp |
| 455 | |
| 456 | .Lclosure_epilogue_vfp: |
| 457 | add sp, sp, #72 |
| 458 | ldmfd sp, {sp, pc} |
| 459 | |
| 460 | .Lretfloat_vfp: |
| 461 | flds s0, [sp] |
| 462 | b .Lclosure_epilogue_vfp |
| 463 | .Lretdouble_vfp: |
| 464 | fldd d0, [sp] |
| 465 | b .Lclosure_epilogue_vfp |
| 466 | .Lretint_vfp: |
| 467 | ldr r0, [sp] |
| 468 | b .Lclosure_epilogue_vfp |
| 469 | .Lretlonglong_vfp: |
| 470 | ldmia sp, {r0, r1} |
| 471 | b .Lclosure_epilogue_vfp |
| 472 | .Lretfloat_struct_vfp: |
Chih-Hung Hsieh | ffb56c0 | 2018-01-17 15:01:59 -0800 | [diff] [blame^] | 473 | vldmia sp, {d0-d1} |
doko@ubuntu.com | 2a91876 | 2012-06-26 17:56:44 +0200 | [diff] [blame] | 474 | b .Lclosure_epilogue_vfp |
| 475 | .Lretdouble_struct_vfp: |
Chih-Hung Hsieh | ffb56c0 | 2018-01-17 15:01:59 -0800 | [diff] [blame^] | 476 | vldmia sp, {d0-d3} |
doko@ubuntu.com | 2a91876 | 2012-06-26 17:56:44 +0200 | [diff] [blame] | 477 | b .Lclosure_epilogue_vfp |
| 478 | |
| 479 | .ffi_closure_VFP_end: |
| 480 | UNWIND .fnend |
| 481 | .size CNAME(ffi_closure_VFP),.ffi_closure_VFP_end-CNAME(ffi_closure_VFP) |
| 482 | #endif |
| 483 | |
| 484 | ENTRY(ffi_arm_trampoline) |
| 485 | stmfd sp!, {r0-r3} |
| 486 | ldr r0, [pc] |
| 487 | ldr pc, [pc] |
Christian Heimes | 7864476 | 2008-03-04 23:39:23 +0000 | [diff] [blame] | 488 | |
| 489 | #if defined __ELF__ && defined __linux__ |
| 490 | .section .note.GNU-stack,"",%progbits |
| 491 | #endif |