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#ifndef __s390x__ 33 34.text 35 36 # r2: cif->bytes 37 # r3: &ecif 38 # r4: ffi_prep_args 39 # r5: ret_type 40 # r6: ecif.rvalue 41 # ov: fn 42 43 # This assumes we are using gas. 44 .globl ffi_call_SYSV 45 .type ffi_call_SYSV,%function 46ffi_call_SYSV: 47.LFB1: 48 stm %r6,%r15,24(%r15) # Save registers 49.LCFI0: 50 basr %r13,0 # Set up base register 51.Lbase: 52 lr %r11,%r15 # Set up frame pointer 53.LCFI1: 54 sr %r15,%r2 55 ahi %r15,-96-48 # Allocate stack 56 lr %r8,%r6 # Save ecif.rvalue 57 sr %r9,%r9 58 ic %r9,.Ltable-.Lbase(%r13,%r5) # Load epilog address 59 l %r7,96(%r11) # Load function address 60 st %r11,0(%r15) # Set up back chain 61 ahi %r11,-48 # Register save area 62.LCFI2: 63 64 la %r2,96(%r15) # Save area 65 # r3 already holds &ecif 66 basr %r14,%r4 # Call ffi_prep_args 67 68 lm %r2,%r6,0(%r11) # Load arguments 69 ld %f0,32(%r11) 70 ld %f2,40(%r11) 71 la %r14,0(%r13,%r9) # Set return address 72 br %r7 # ... and call function 73 74.LretNone: # Return void 75 l %r4,48+56(%r11) 76 lm %r6,%r15,48+24(%r11) 77 br %r4 78 79.LretFloat: 80 l %r4,48+56(%r11) 81 ste %f0,0(%r8) # Return float 82 lm %r6,%r15,48+24(%r11) 83 br %r4 84 85.LretDouble: 86 l %r4,48+56(%r11) 87 std %f0,0(%r8) # Return double 88 lm %r6,%r15,48+24(%r11) 89 br %r4 90 91.LretInt32: 92 l %r4,48+56(%r11) 93 st %r2,0(%r8) # Return int 94 lm %r6,%r15,48+24(%r11) 95 br %r4 96 97.LretInt64: 98 l %r4,48+56(%r11) 99 stm %r2,%r3,0(%r8) # Return long long 100 lm %r6,%r15,48+24(%r11) 101 br %r4 102 103.Ltable: 104 .byte .LretNone-.Lbase # FFI390_RET_VOID 105 .byte .LretNone-.Lbase # FFI390_RET_STRUCT 106 .byte .LretFloat-.Lbase # FFI390_RET_FLOAT 107 .byte .LretDouble-.Lbase # FFI390_RET_DOUBLE 108 .byte .LretInt32-.Lbase # FFI390_RET_INT32 109 .byte .LretInt64-.Lbase # FFI390_RET_INT64 110 111.LFE1: 112.ffi_call_SYSV_end: 113 .size ffi_call_SYSV,.ffi_call_SYSV_end-ffi_call_SYSV 114 115 116 .globl ffi_closure_SYSV 117 .type ffi_closure_SYSV,%function 118ffi_closure_SYSV: 119.LFB2: 120 stm %r12,%r15,48(%r15) # Save registers 121.LCFI10: 122 basr %r13,0 # Set up base register 123.Lcbase: 124 stm %r2,%r6,8(%r15) # Save arguments 125 std %f0,64(%r15) 126 std %f2,72(%r15) 127 lr %r1,%r15 # Set up stack frame 128 ahi %r15,-96 129.LCFI11: 130 l %r12,.Lchelper-.Lcbase(%r13) # Get helper function 131 lr %r2,%r0 # Closure 132 la %r3,8(%r1) # GPRs 133 la %r4,64(%r1) # FPRs 134 la %r5,96(%r1) # Overflow 135 st %r1,0(%r15) # Set up back chain 136 137 bas %r14,0(%r12,%r13) # Call helper 138 139 l %r4,96+56(%r15) 140 ld %f0,96+64(%r15) # Load return registers 141 lm %r2,%r3,96+8(%r15) 142 lm %r12,%r15,96+48(%r15) 143 br %r4 144 145 .align 4 146.Lchelper: 147 .long ffi_closure_helper_SYSV-.Lcbase 148 149.LFE2: 150 151.ffi_closure_SYSV_end: 152 .size ffi_closure_SYSV,.ffi_closure_SYSV_end-ffi_closure_SYSV 153 154 155 .section .eh_frame,EH_FRAME_FLAGS,@progbits 156.Lframe1: 157 .4byte .LECIE1-.LSCIE1 # Length of Common Information Entry 158.LSCIE1: 159 .4byte 0x0 # CIE Identifier Tag 160 .byte 0x1 # CIE Version 161 .ascii "zR\0" # CIE Augmentation 162 .uleb128 0x1 # CIE Code Alignment Factor 163 .sleb128 -4 # CIE Data Alignment Factor 164 .byte 0xe # CIE RA Column 165 .uleb128 0x1 # Augmentation size 166 .byte 0x1b # FDE Encoding (pcrel sdata4) 167 .byte 0xc # DW_CFA_def_cfa 168 .uleb128 0xf 169 .uleb128 0x60 170 .align 4 171.LECIE1: 172.LSFDE1: 173 .4byte .LEFDE1-.LASFDE1 # FDE Length 174.LASFDE1: 175 .4byte .LASFDE1-.Lframe1 # FDE CIE offset 176 .4byte .LFB1-. # FDE initial location 177 .4byte .LFE1-.LFB1 # FDE address range 178 .uleb128 0x0 # Augmentation size 179 .byte 0x4 # DW_CFA_advance_loc4 180 .4byte .LCFI0-.LFB1 181 .byte 0x8f # DW_CFA_offset, column 0xf 182 .uleb128 0x9 183 .byte 0x8e # DW_CFA_offset, column 0xe 184 .uleb128 0xa 185 .byte 0x8d # DW_CFA_offset, column 0xd 186 .uleb128 0xb 187 .byte 0x8c # DW_CFA_offset, column 0xc 188 .uleb128 0xc 189 .byte 0x8b # DW_CFA_offset, column 0xb 190 .uleb128 0xd 191 .byte 0x8a # DW_CFA_offset, column 0xa 192 .uleb128 0xe 193 .byte 0x89 # DW_CFA_offset, column 0x9 194 .uleb128 0xf 195 .byte 0x88 # DW_CFA_offset, column 0x8 196 .uleb128 0x10 197 .byte 0x87 # DW_CFA_offset, column 0x7 198 .uleb128 0x11 199 .byte 0x86 # DW_CFA_offset, column 0x6 200 .uleb128 0x12 201 .byte 0x4 # DW_CFA_advance_loc4 202 .4byte .LCFI1-.LCFI0 203 .byte 0xd # DW_CFA_def_cfa_register 204 .uleb128 0xb 205 .byte 0x4 # DW_CFA_advance_loc4 206 .4byte .LCFI2-.LCFI1 207 .byte 0xe # DW_CFA_def_cfa_offset 208 .uleb128 0x90 209 .align 4 210.LEFDE1: 211.LSFDE2: 212 .4byte .LEFDE2-.LASFDE2 # FDE Length 213.LASFDE2: 214 .4byte .LASFDE2-.Lframe1 # FDE CIE offset 215 .4byte .LFB2-. # FDE initial location 216 .4byte .LFE2-.LFB2 # FDE address range 217 .uleb128 0x0 # Augmentation size 218 .byte 0x4 # DW_CFA_advance_loc4 219 .4byte .LCFI10-.LFB2 220 .byte 0x8f # DW_CFA_offset, column 0xf 221 .uleb128 0x9 222 .byte 0x8e # DW_CFA_offset, column 0xe 223 .uleb128 0xa 224 .byte 0x8d # DW_CFA_offset, column 0xd 225 .uleb128 0xb 226 .byte 0x8c # DW_CFA_offset, column 0xc 227 .uleb128 0xc 228 .byte 0x4 # DW_CFA_advance_loc4 229 .4byte .LCFI11-.LCFI10 230 .byte 0xe # DW_CFA_def_cfa_offset 231 .uleb128 0xc0 232 .align 4 233.LEFDE2: 234 235#else 236 237.text 238 239 # r2: cif->bytes 240 # r3: &ecif 241 # r4: ffi_prep_args 242 # r5: ret_type 243 # r6: ecif.rvalue 244 # ov: fn 245 246 # This assumes we are using gas. 247 .globl ffi_call_SYSV 248 .type ffi_call_SYSV,%function 249ffi_call_SYSV: 250.LFB1: 251 stmg %r6,%r15,48(%r15) # Save registers 252.LCFI0: 253 larl %r13,.Lbase # Set up base register 254 lgr %r11,%r15 # Set up frame pointer 255.LCFI1: 256 sgr %r15,%r2 257 aghi %r15,-160-80 # Allocate stack 258 lgr %r8,%r6 # Save ecif.rvalue 259 llgc %r9,.Ltable-.Lbase(%r13,%r5) # Load epilog address 260 lg %r7,160(%r11) # Load function address 261 stg %r11,0(%r15) # Set up back chain 262 aghi %r11,-80 # Register save area 263.LCFI2: 264 265 la %r2,160(%r15) # Save area 266 # r3 already holds &ecif 267 basr %r14,%r4 # Call ffi_prep_args 268 269 lmg %r2,%r6,0(%r11) # Load arguments 270 ld %f0,48(%r11) 271 ld %f2,56(%r11) 272 ld %f4,64(%r11) 273 ld %f6,72(%r11) 274 la %r14,0(%r13,%r9) # Set return address 275 br %r7 # ... and call function 276 277.Lbase: 278.LretNone: # Return void 279 lg %r4,80+112(%r11) 280 lmg %r6,%r15,80+48(%r11) 281 br %r4 282 283.LretFloat: 284 lg %r4,80+112(%r11) 285 ste %f0,0(%r8) # Return float 286 lmg %r6,%r15,80+48(%r11) 287 br %r4 288 289.LretDouble: 290 lg %r4,80+112(%r11) 291 std %f0,0(%r8) # Return double 292 lmg %r6,%r15,80+48(%r11) 293 br %r4 294 295.LretInt32: 296 lg %r4,80+112(%r11) 297 st %r2,0(%r8) # Return int 298 lmg %r6,%r15,80+48(%r11) 299 br %r4 300 301.LretInt64: 302 lg %r4,80+112(%r11) 303 stg %r2,0(%r8) # Return long 304 lmg %r6,%r15,80+48(%r11) 305 br %r4 306 307.Ltable: 308 .byte .LretNone-.Lbase # FFI390_RET_VOID 309 .byte .LretNone-.Lbase # FFI390_RET_STRUCT 310 .byte .LretFloat-.Lbase # FFI390_RET_FLOAT 311 .byte .LretDouble-.Lbase # FFI390_RET_DOUBLE 312 .byte .LretInt32-.Lbase # FFI390_RET_INT32 313 .byte .LretInt64-.Lbase # FFI390_RET_INT64 314 315.LFE1: 316.ffi_call_SYSV_end: 317 .size ffi_call_SYSV,.ffi_call_SYSV_end-ffi_call_SYSV 318 319 320 .globl ffi_closure_SYSV 321 .type ffi_closure_SYSV,%function 322ffi_closure_SYSV: 323.LFB2: 324 stmg %r14,%r15,112(%r15) # Save registers 325.LCFI10: 326 stmg %r2,%r6,16(%r15) # Save arguments 327 std %f0,128(%r15) 328 std %f2,136(%r15) 329 std %f4,144(%r15) 330 std %f6,152(%r15) 331 lgr %r1,%r15 # Set up stack frame 332 aghi %r15,-160 333.LCFI11: 334 lgr %r2,%r0 # Closure 335 la %r3,16(%r1) # GPRs 336 la %r4,128(%r1) # FPRs 337 la %r5,160(%r1) # Overflow 338 stg %r1,0(%r15) # Set up back chain 339 340 brasl %r14,ffi_closure_helper_SYSV # Call helper 341 342 lg %r14,160+112(%r15) 343 ld %f0,160+128(%r15) # Load return registers 344 lg %r2,160+16(%r15) 345 la %r15,160(%r15) 346 br %r14 347.LFE2: 348 349.ffi_closure_SYSV_end: 350 .size ffi_closure_SYSV,.ffi_closure_SYSV_end-ffi_closure_SYSV 351 352 353 354 .section .eh_frame,EH_FRAME_FLAGS,@progbits 355.Lframe1: 356 .4byte .LECIE1-.LSCIE1 # Length of Common Information Entry 357.LSCIE1: 358 .4byte 0x0 # CIE Identifier Tag 359 .byte 0x1 # CIE Version 360 .ascii "zR\0" # CIE Augmentation 361 .uleb128 0x1 # CIE Code Alignment Factor 362 .sleb128 -8 # CIE Data Alignment Factor 363 .byte 0xe # CIE RA Column 364 .uleb128 0x1 # Augmentation size 365 .byte 0x1b # FDE Encoding (pcrel sdata4) 366 .byte 0xc # DW_CFA_def_cfa 367 .uleb128 0xf 368 .uleb128 0xa0 369 .align 8 370.LECIE1: 371.LSFDE1: 372 .4byte .LEFDE1-.LASFDE1 # FDE Length 373.LASFDE1: 374 .4byte .LASFDE1-.Lframe1 # FDE CIE offset 375 .4byte .LFB1-. # FDE initial location 376 .4byte .LFE1-.LFB1 # FDE address range 377 .uleb128 0x0 # Augmentation size 378 .byte 0x4 # DW_CFA_advance_loc4 379 .4byte .LCFI0-.LFB1 380 .byte 0x8f # DW_CFA_offset, column 0xf 381 .uleb128 0x5 382 .byte 0x8e # DW_CFA_offset, column 0xe 383 .uleb128 0x6 384 .byte 0x8d # DW_CFA_offset, column 0xd 385 .uleb128 0x7 386 .byte 0x8c # DW_CFA_offset, column 0xc 387 .uleb128 0x8 388 .byte 0x8b # DW_CFA_offset, column 0xb 389 .uleb128 0x9 390 .byte 0x8a # DW_CFA_offset, column 0xa 391 .uleb128 0xa 392 .byte 0x89 # DW_CFA_offset, column 0x9 393 .uleb128 0xb 394 .byte 0x88 # DW_CFA_offset, column 0x8 395 .uleb128 0xc 396 .byte 0x87 # DW_CFA_offset, column 0x7 397 .uleb128 0xd 398 .byte 0x86 # DW_CFA_offset, column 0x6 399 .uleb128 0xe 400 .byte 0x4 # DW_CFA_advance_loc4 401 .4byte .LCFI1-.LCFI0 402 .byte 0xd # DW_CFA_def_cfa_register 403 .uleb128 0xb 404 .byte 0x4 # DW_CFA_advance_loc4 405 .4byte .LCFI2-.LCFI1 406 .byte 0xe # DW_CFA_def_cfa_offset 407 .uleb128 0xf0 408 .align 8 409.LEFDE1: 410.LSFDE2: 411 .4byte .LEFDE2-.LASFDE2 # FDE Length 412.LASFDE2: 413 .4byte .LASFDE2-.Lframe1 # FDE CIE offset 414 .4byte .LFB2-. # FDE initial location 415 .4byte .LFE2-.LFB2 # FDE address range 416 .uleb128 0x0 # Augmentation size 417 .byte 0x4 # DW_CFA_advance_loc4 418 .4byte .LCFI10-.LFB2 419 .byte 0x8f # DW_CFA_offset, column 0xf 420 .uleb128 0x5 421 .byte 0x8e # DW_CFA_offset, column 0xe 422 .uleb128 0x6 423 .byte 0x4 # DW_CFA_advance_loc4 424 .4byte .LCFI11-.LCFI10 425 .byte 0xe # DW_CFA_def_cfa_offset 426 .uleb128 0x140 427 .align 8 428.LEFDE2: 429 430#endif 431 432#if defined __ELF__ && defined __linux__ 433 .section .note.GNU-stack,"",@progbits 434#endif 435