1/* ----------------------------------------------------------------------- 2 sysv.S - Copyright (c) 2000 Software AG 3 Copyright (c) 2008 Red Hat, Inc. 4 5 S390 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 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 32 .text 33 34#ifndef __s390x__ 35 36 # r2: frame 37 # r3: ret_type 38 # r4: ret_addr 39 # r5: fun 40 # r6: closure 41 42 # This assumes we are using gas. 43 .balign 8 44 .globl ffi_call_SYSV 45 FFI_HIDDEN(ffi_call_SYSV) 46 .type ffi_call_SYSV,%function 47ffi_call_SYSV: 48 .cfi_startproc 49 st %r6,44(%r2) # Save registers 50 stm %r12,%r14,48(%r2) 51 lr %r13,%r2 # Install frame pointer 52 .cfi_rel_offset r6, 44 53 .cfi_rel_offset r12, 48 54 .cfi_rel_offset r13, 52 55 .cfi_rel_offset r14, 56 56 .cfi_def_cfa_register r13 57 st %r2,0(%r15) # Set up back chain 58 sla %r3,3 # ret_type *= 8 59 lr %r12,%r4 # Save ret_addr 60 lr %r1,%r5 # Save fun 61 lr %r0,%r6 # Install static chain 62 63 # Set return address, so that there is only one indirect jump. 64#ifdef HAVE_AS_S390_ZARCH 65 larl %r14,.Ltable 66 ar %r14,%r3 67#else 68 basr %r14,0 690: la %r14,.Ltable-0b(%r14,%r3) 70#endif 71 72 lm %r2,%r6,8(%r13) # Load arguments 73 ld %f0,64(%r13) 74 ld %f2,72(%r13) 75 br %r1 # ... and call function 76 77 .balign 8 78.Ltable: 79# FFI390_RET_DOUBLE 80 std %f0,0(%r12) 81 j .Ldone 82 83 .balign 8 84# FFI390_RET_FLOAT 85 ste %f0,0(%r12) 86 j .Ldone 87 88 .balign 8 89# FFI390_RET_INT64 90 st %r3,4(%r12) 91 nop 92 # fallthru 93 94 .balign 8 95# FFI390_RET_INT32 96 st %r2,0(%r12) 97 nop 98 # fallthru 99 100 .balign 8 101# FFI390_RET_VOID 102.Ldone: 103 l %r14,56(%r13) 104 l %r12,48(%r13) 105 l %r6,44(%r13) 106 l %r13,52(%r13) 107 .cfi_restore 14 108 .cfi_restore 13 109 .cfi_restore 12 110 .cfi_restore 6 111 .cfi_def_cfa r15, 96 112 br %r14 113 .cfi_endproc 114 .size ffi_call_SYSV,.-ffi_call_SYSV 115 116 117 .balign 8 118 .globl ffi_go_closure_SYSV 119 FFI_HIDDEN(ffi_go_closure_SYSV) 120 .type ffi_go_closure_SYSV,%function 121ffi_go_closure_SYSV: 122 .cfi_startproc 123 stm %r2,%r6,8(%r15) # Save arguments 124 lr %r4,%r0 # Load closure -> user_data 125 l %r2,4(%r4) # ->cif 126 l %r3,8(%r4) # ->fun 127 j .Ldoclosure 128 .cfi_endproc 129 130 .balign 8 131 .globl ffi_closure_SYSV 132 FFI_HIDDEN(ffi_closure_SYSV) 133 .type ffi_closure_SYSV,%function 134ffi_closure_SYSV: 135 .cfi_startproc 136 stm %r2,%r6,8(%r15) # Save arguments 137 lr %r4,%r0 # Closure 138 l %r2,16(%r4) # ->cif 139 l %r3,20(%r4) # ->fun 140 l %r4,24(%r4) # ->user_data 141.Ldoclosure: 142 stm %r12,%r15,48(%r15) # Save registers 143 lr %r12,%r15 144 .cfi_def_cfa_register r12 145 .cfi_rel_offset r6, 24 146 .cfi_rel_offset r12, 48 147 .cfi_rel_offset r13, 52 148 .cfi_rel_offset r14, 56 149 .cfi_rel_offset r15, 60 150#ifndef HAVE_AS_S390_ZARCH 151 basr %r13,0 # Set up base register 152.Lcbase: 153 l %r1,.Lchelper-.Lcbase(%r13) # Get helper function 154#endif 155 ahi %r15,-96-8 # Set up stack frame 156 st %r12,0(%r15) # Set up back chain 157 158 std %f0,64(%r12) # Save fp arguments 159 std %f2,72(%r12) 160 161 la %r5,96(%r12) # Overflow 162 st %r5,96(%r15) 163 la %r6,64(%r12) # FPRs 164 la %r5,8(%r12) # GPRs 165#ifdef HAVE_AS_S390_ZARCH 166 brasl %r14,ffi_closure_helper_SYSV 167#else 168 bas %r14,0(%r1,%r13) # Call helper 169#endif 170 171 lr %r15,%r12 172 .cfi_def_cfa_register r15 173 lm %r12,%r14,48(%r12) # Restore saved registers 174 l %r6,24(%r15) 175 ld %f0,64(%r15) # Load return registers 176 lm %r2,%r3,8(%r15) 177 br %r14 178 .cfi_endproc 179 180#ifndef HAVE_AS_S390_ZARCH 181 .align 4 182.Lchelper: 183 .long ffi_closure_helper_SYSV-.Lcbase 184#endif 185 186 .size ffi_closure_SYSV,.-ffi_closure_SYSV 187 188#else 189 190 # r2: frame 191 # r3: ret_type 192 # r4: ret_addr 193 # r5: fun 194 # r6: closure 195 196 # This assumes we are using gas. 197 .balign 8 198 .globl ffi_call_SYSV 199 FFI_HIDDEN(ffi_call_SYSV) 200 .type ffi_call_SYSV,%function 201ffi_call_SYSV: 202 .cfi_startproc 203 stg %r6,88(%r2) # Save registers 204 stmg %r12,%r14,96(%r2) 205 lgr %r13,%r2 # Install frame pointer 206 .cfi_rel_offset r6, 88 207 .cfi_rel_offset r12, 96 208 .cfi_rel_offset r13, 104 209 .cfi_rel_offset r14, 112 210 .cfi_def_cfa_register r13 211 stg %r2,0(%r15) # Set up back chain 212 larl %r14,.Ltable # Set up return address 213 slag %r3,%r3,3 # ret_type *= 8 214 lgr %r12,%r4 # Save ret_addr 215 lgr %r1,%r5 # Save fun 216 lgr %r0,%r6 # Install static chain 217 agr %r14,%r3 218 lmg %r2,%r6,16(%r13) # Load arguments 219 ld %f0,128(%r13) 220 ld %f2,136(%r13) 221 ld %f4,144(%r13) 222 ld %f6,152(%r13) 223 br %r1 # ... and call function 224 225 .balign 8 226.Ltable: 227# FFI390_RET_DOUBLE 228 std %f0,0(%r12) 229 j .Ldone 230 231 .balign 8 232# FFI390_RET_DOUBLE 233 ste %f0,0(%r12) 234 j .Ldone 235 236 .balign 8 237# FFI390_RET_INT64 238 stg %r2,0(%r12) 239 240 .balign 8 241# FFI390_RET_INT32 242 # Never used, as we always store type ffi_arg. 243 # But the stg above is 6 bytes and we cannot 244 # jump around this case, so fall through. 245 nop 246 nop 247 248 .balign 8 249# FFI390_RET_VOID 250.Ldone: 251 lg %r14,112(%r13) 252 lg %r12,96(%r13) 253 lg %r6,88(%r13) 254 lg %r13,104(%r13) 255 .cfi_restore r14 256 .cfi_restore r13 257 .cfi_restore r12 258 .cfi_restore r6 259 .cfi_def_cfa r15, 160 260 br %r14 261 .cfi_endproc 262 .size ffi_call_SYSV,.-ffi_call_SYSV 263 264 265 .balign 8 266 .globl ffi_go_closure_SYSV 267 FFI_HIDDEN(ffi_go_closure_SYSV) 268 .type ffi_go_closure_SYSV,%function 269ffi_go_closure_SYSV: 270 .cfi_startproc 271 stmg %r2,%r6,16(%r15) # Save arguments 272 lgr %r4,%r0 # Load closure -> user_data 273 lg %r2,8(%r4) # ->cif 274 lg %r3,16(%r4) # ->fun 275 j .Ldoclosure 276 .cfi_endproc 277 .size ffi_go_closure_SYSV,.-ffi_go_closure_SYSV 278 279 280 .balign 8 281 .globl ffi_closure_SYSV 282 FFI_HIDDEN(ffi_closure_SYSV) 283 .type ffi_closure_SYSV,%function 284ffi_closure_SYSV: 285 .cfi_startproc 286 stmg %r2,%r6,16(%r15) # Save arguments 287 lgr %r4,%r0 # Load closure 288 lg %r2,32(%r4) # ->cif 289 lg %r3,40(%r4) # ->fun 290 lg %r4,48(%r4) # ->user_data 291.Ldoclosure: 292 stmg %r13,%r15,104(%r15) # Save registers 293 lgr %r13,%r15 294 .cfi_def_cfa_register r13 295 .cfi_rel_offset r6, 48 296 .cfi_rel_offset r13, 104 297 .cfi_rel_offset r14, 112 298 .cfi_rel_offset r15, 120 299 aghi %r15,-160-16 # Set up stack frame 300 stg %r13,0(%r15) # Set up back chain 301 302 std %f0,128(%r13) # Save fp arguments 303 std %f2,136(%r13) 304 std %f4,144(%r13) 305 std %f6,152(%r13) 306 la %r5,160(%r13) # Overflow 307 stg %r5,160(%r15) 308 la %r6,128(%r13) # FPRs 309 la %r5,16(%r13) # GPRs 310 brasl %r14,ffi_closure_helper_SYSV # Call helper 311 312 lgr %r15,%r13 313 .cfi_def_cfa_register r15 314 lmg %r13,%r14,104(%r13) # Restore saved registers 315 lg %r6,48(%r15) 316 ld %f0,128(%r15) # Load return registers 317 lg %r2,16(%r15) 318 br %r14 319 .cfi_endproc 320 .size ffi_closure_SYSV,.-ffi_closure_SYSV 321#endif /* !s390x */ 322 323#if defined __ELF__ && defined __linux__ 324 .section .note.GNU-stack,"",@progbits 325#endif 326