1#if defined(__ppc64__) 2 3/* ----------------------------------------------------------------------- 4 ppc64-darwin_closure.S - Copyright (c) 2002, 2003, 2004, Free Software Foundation, 5 Inc. based on ppc_closure.S 6 7 PowerPC Assembly glue. 8 9 Permission is hereby granted, free of charge, to any person obtaining 10 a copy of this software and associated documentation files (the 11 ``Software''), to deal in the Software without restriction, including 12 without limitation the rights to use, copy, modify, merge, publish, 13 distribute, sublicense, and/or sell copies of the Software, and to 14 permit persons to whom the Software is furnished to do so, subject to 15 the following conditions: 16 17 The above copyright notice and this permission notice shall be included 18 in all copies or substantial portions of the Software. 19 20 THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS 21 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 23 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR 24 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 25 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 26 OTHER DEALINGS IN THE SOFTWARE. 27 ----------------------------------------------------------------------- */ 28 29#define LIBFFI_ASM 30 31#include <ffi.h> 32#include <ppc-ffitarget.h> // for FFI_TRAMPOLINE_SIZE 33#include <ppc-darwin.h> 34#include <architecture/ppc/mode_independent_asm.h> 35 36 .file "ppc64-darwin_closure.S" 37.text 38 .align LOG2_GPR_BYTES 39 .globl _ffi_closure_ASM 40 41.text 42 .align LOG2_GPR_BYTES 43 44_ffi_closure_ASM: 45LFB1: 46 mflr r0 47 stg r0,SF_RETURN(r1) // save return address 48 49 // Save GPRs 3 - 10 (aligned to 8) in the parents outgoing area. 50 stg r3,SF_ARG1(r1) 51 stg r4,SF_ARG2(r1) 52 stg r5,SF_ARG3(r1) 53 stg r6,SF_ARG4(r1) 54 stg r7,SF_ARG5(r1) 55 stg r8,SF_ARG6(r1) 56 stg r9,SF_ARG7(r1) 57 stg r10,SF_ARG8(r1) 58 59LCFI0: 60/* 48 bytes (Linkage Area) 61 64 bytes (outgoing parameter area, always reserved) 62 112 bytes (14*8 for incoming FPR) 63 ? bytes (result) 64 112 bytes (14*8 for outgoing FPR) 65 16 bytes (2 saved registers) 66 352 + ? total bytes 67*/ 68 69 std r31,-8(r1) // Save registers we use. 70 std r30,-16(r1) 71 mr r30,r1 // Save the old SP. 72 mr r31,r11 // Save the ffi_closure around ffi64_data_size. 73 74 // Calculate the space we need. 75 stdu r1,-SF_MINSIZE(r1) 76 ld r3,FFI_TRAMPOLINE_SIZE(r31) // ffi_closure->cif* 77 ld r3,16(r3) // ffi_cif->rtype* 78 bl Lffi64_data_size$stub 79 ld r1,0(r1) 80 81 addi r3,r3,352 // Add our overhead. 82 neg r3,r3 83 li r0,-32 // Align to 32 bytes. 84 and r3,r3,r0 85 stdux r1,r1,r3 // Grow the stack. 86 87 mr r11,r31 // Copy the ffi_closure back. 88 89LCFI1: 90 // We want to build up an area for the parameters passed 91 // in registers. (both floating point and integer) 92 93/* 320 bytes (callee stack frame aligned to 32) 94 48 bytes (caller linkage area) 95 368 (start of caller parameter area aligned to 8) 96*/ 97 98 // Save FPRs 1 - 14. (aligned to 8) 99 stfd f1,112(r1) 100 stfd f2,120(r1) 101 stfd f3,128(r1) 102 stfd f4,136(r1) 103 stfd f5,144(r1) 104 stfd f6,152(r1) 105 stfd f7,160(r1) 106 stfd f8,168(r1) 107 stfd f9,176(r1) 108 stfd f10,184(r1) 109 stfd f11,192(r1) 110 stfd f12,200(r1) 111 stfd f13,208(r1) 112 stfd f14,216(r1) 113 114 // Set up registers for the routine that actually does the work. 115 mr r3,r11 // context pointer from the trampoline 116 addi r4,r1,224 // result storage 117 addi r5,r30,SF_ARG1 // saved GPRs 118 addi r6,r1,112 // saved FPRs 119 bl Lffi_closure_helper_DARWIN$stub 120 121 // Look the proper starting point in table 122 // by using return type as an offset. 123 addi r5,r1,224 // Get pointer to results area. 124 bl Lget_ret_type0_addr // Get pointer to Lret_type0 into LR. 125 mflr r4 // Move to r4. 126 slwi r3,r3,4 // Now multiply return type by 16. 127 add r3,r3,r4 // Add contents of table to table address. 128 mtctr r3 129 bctr 130 131LFE1: 132 // Each of the ret_typeX code fragments has to be exactly 16 bytes long 133 // (4 instructions). For cache effectiveness we align to a 16 byte 134 // boundary first. 135 .align 4 136 nop 137 nop 138 nop 139 140Lget_ret_type0_addr: 141 blrl 142 143// case FFI_TYPE_VOID 144Lret_type0: 145 b Lfinish 146 nop 147 nop 148 nop 149 150// case FFI_TYPE_INT 151Lret_type1: 152 lwz r3,4(r5) 153 b Lfinish 154 nop 155 nop 156 157// case FFI_TYPE_FLOAT 158Lret_type2: 159 lfs f1,0(r5) 160 b Lfinish 161 nop 162 nop 163 164// case FFI_TYPE_DOUBLE 165Lret_type3: 166 lfd f1,0(r5) 167 b Lfinish 168 nop 169 nop 170 171// case FFI_TYPE_LONGDOUBLE 172Lret_type4: 173 lfd f1,0(r5) 174 lfd f2,8(r5) 175 b Lfinish 176 nop 177 178// case FFI_TYPE_UINT8 179Lret_type5: 180 lbz r3,7(r5) 181 b Lfinish 182 nop 183 nop 184 185// case FFI_TYPE_SINT8 186Lret_type6: 187 lbz r3,7(r5) 188 extsb r3,r3 189 b Lfinish 190 nop 191 192// case FFI_TYPE_UINT16 193Lret_type7: 194 lhz r3,6(r5) 195 b Lfinish 196 nop 197 nop 198 199// case FFI_TYPE_SINT16 200Lret_type8: 201 lha r3,6(r5) 202 b Lfinish 203 nop 204 nop 205 206// case FFI_TYPE_UINT32 207Lret_type9: // same as Lret_type1 208 lwz r3,4(r5) 209 b Lfinish 210 nop 211 nop 212 213// case FFI_TYPE_SINT32 214Lret_type10: // same as Lret_type1 215 lwz r3,4(r5) 216 b Lfinish 217 nop 218 nop 219 220// case FFI_TYPE_UINT64 221Lret_type11: 222 ld r3,0(r5) 223 b Lfinish 224 nop 225 nop 226 227// case FFI_TYPE_SINT64 228Lret_type12: // same as Lret_type11 229 ld r3,0(r5) 230 b Lfinish 231 nop 232 nop 233 234// case FFI_TYPE_STRUCT 235Lret_type13: 236 b Lret_struct 237 nop 238 nop 239 nop 240 241// ** End 16-byte aligned cases ** 242// case FFI_TYPE_POINTER 243// This case assumes that FFI_TYPE_POINTER == FFI_TYPE_LAST. If more types 244// are added in future, the following code will need to be updated and 245// padded to 16 bytes. 246Lret_type14: 247 lg r3,0(r5) 248 b Lfinish 249 250// copy struct into registers 251Lret_struct: 252 ld r31,FFI_TRAMPOLINE_SIZE(r31) // ffi_closure->cif* 253 ld r3,16(r31) // ffi_cif->rtype* 254 ld r31,24(r31) // ffi_cif->flags 255 mr r4,r5 // copy struct* to 2nd arg 256 addi r7,r1,SF_ARG9 // GPR return area 257 addi r9,r30,-16-(14*8) // FPR return area 258 li r5,0 // struct offset ptr (NULL) 259 li r6,0 // FPR used count ptr (NULL) 260 li r8,0 // GPR return area size ptr (NULL) 261 li r10,0 // FPR return area size ptr (NULL) 262 bl Lffi64_struct_to_reg_form$stub 263 264 // Load GPRs 265 ld r3,SF_ARG9(r1) 266 ld r4,SF_ARG10(r1) 267 ld r5,SF_ARG11(r1) 268 ld r6,SF_ARG12(r1) 269 nop 270 ld r7,SF_ARG13(r1) 271 ld r8,SF_ARG14(r1) 272 ld r9,SF_ARG15(r1) 273 ld r10,SF_ARG16(r1) 274 nop 275 276 // Load FPRs 277 mtcrf 0x2,r31 278 bf 26,Lfinish 279 lfd f1,-16-(14*8)(r30) 280 lfd f2,-16-(13*8)(r30) 281 lfd f3,-16-(12*8)(r30) 282 lfd f4,-16-(11*8)(r30) 283 nop 284 lfd f5,-16-(10*8)(r30) 285 lfd f6,-16-(9*8)(r30) 286 lfd f7,-16-(8*8)(r30) 287 lfd f8,-16-(7*8)(r30) 288 nop 289 lfd f9,-16-(6*8)(r30) 290 lfd f10,-16-(5*8)(r30) 291 lfd f11,-16-(4*8)(r30) 292 lfd f12,-16-(3*8)(r30) 293 nop 294 lfd f13,-16-(2*8)(r30) 295 lfd f14,-16-(1*8)(r30) 296 // Fall through 297 298// case done 299Lfinish: 300 lg r1,0(r1) // Restore stack pointer. 301 ld r31,-8(r1) // Restore registers we used. 302 ld r30,-16(r1) 303 lg r0,SF_RETURN(r1) // Get return address. 304 mtlr r0 // Reset link register. 305 blr 306 307// END(ffi_closure_ASM) 308 309.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support 310EH_frame1: 311 .set L$set$0,LECIE1-LSCIE1 312 .long L$set$0 ; Length of Common Information Entry 313LSCIE1: 314 .long 0x0 ; CIE Identifier Tag 315 .byte 0x1 ; CIE Version 316 .ascii "zR\0" ; CIE Augmentation 317 .byte 0x1 ; uleb128 0x1; CIE Code Alignment Factor 318 .byte 0x7c ; sleb128 -4; CIE Data Alignment Factor 319 .byte 0x41 ; CIE RA Column 320 .byte 0x1 ; uleb128 0x1; Augmentation size 321 .byte 0x10 ; FDE Encoding (pcrel) 322 .byte 0xc ; DW_CFA_def_cfa 323 .byte 0x1 ; uleb128 0x1 324 .byte 0x0 ; uleb128 0x0 325 .align LOG2_GPR_BYTES 326LECIE1: 327.globl _ffi_closure_ASM.eh 328_ffi_closure_ASM.eh: 329LSFDE1: 330 .set L$set$1,LEFDE1-LASFDE1 331 .long L$set$1 ; FDE Length 332 333LASFDE1: 334 .long LASFDE1-EH_frame1 ; FDE CIE offset 335 .g_long LFB1-. ; FDE initial location 336 .set L$set$3,LFE1-LFB1 337 .g_long L$set$3 ; FDE address range 338 .byte 0x0 ; uleb128 0x0; Augmentation size 339 .byte 0x4 ; DW_CFA_advance_loc4 340 .set L$set$3,LCFI1-LCFI0 341 .long L$set$3 342 .byte 0xe ; DW_CFA_def_cfa_offset 343 .byte 176,1 ; uleb128 176 344 .byte 0x4 ; DW_CFA_advance_loc4 345 .set L$set$4,LCFI0-LFB1 346 .long L$set$4 347 .byte 0x11 ; DW_CFA_offset_extended_sf 348 .byte 0x41 ; uleb128 0x41 349 .byte 0x7e ; sleb128 -2 350 .align LOG2_GPR_BYTES 351 352LEFDE1: 353.data 354 .align LOG2_GPR_BYTES 355LDFCM0: 356.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32 357 .align LOG2_GPR_BYTES 358 359Lffi_closure_helper_DARWIN$stub: 360 .indirect_symbol _ffi_closure_helper_DARWIN 361 mflr r0 362 bcl 20,31,LO$ffi_closure_helper_DARWIN 363 364LO$ffi_closure_helper_DARWIN: 365 mflr r11 366 addis r11,r11,ha16(L_ffi_closure_helper_DARWIN$lazy_ptr - LO$ffi_closure_helper_DARWIN) 367 mtlr r0 368 lgu r12,lo16(L_ffi_closure_helper_DARWIN$lazy_ptr - LO$ffi_closure_helper_DARWIN)(r11) 369 mtctr r12 370 bctr 371 372.lazy_symbol_pointer 373L_ffi_closure_helper_DARWIN$lazy_ptr: 374 .indirect_symbol _ffi_closure_helper_DARWIN 375 .g_long dyld_stub_binding_helper 376 377.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32 378 .align LOG2_GPR_BYTES 379 380Lffi64_struct_to_reg_form$stub: 381 .indirect_symbol _ffi64_struct_to_reg_form 382 mflr r0 383 bcl 20,31,LO$ffi64_struct_to_reg_form 384 385LO$ffi64_struct_to_reg_form: 386 mflr r11 387 addis r11,r11,ha16(L_ffi64_struct_to_reg_form$lazy_ptr - LO$ffi64_struct_to_reg_form) 388 mtlr r0 389 lgu r12,lo16(L_ffi64_struct_to_reg_form$lazy_ptr - LO$ffi64_struct_to_reg_form)(r11) 390 mtctr r12 391 bctr 392 393.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32 394 .align LOG2_GPR_BYTES 395 396Lffi64_data_size$stub: 397 .indirect_symbol _ffi64_data_size 398 mflr r0 399 bcl 20,31,LO$ffi64_data_size 400 401LO$ffi64_data_size: 402 mflr r11 403 addis r11,r11,ha16(L_ffi64_data_size$lazy_ptr - LO$ffi64_data_size) 404 mtlr r0 405 lgu r12,lo16(L_ffi64_data_size$lazy_ptr - LO$ffi64_data_size)(r11) 406 mtctr r12 407 bctr 408 409.lazy_symbol_pointer 410L_ffi64_struct_to_reg_form$lazy_ptr: 411 .indirect_symbol _ffi64_struct_to_reg_form 412 .g_long dyld_stub_binding_helper 413 414L_ffi64_data_size$lazy_ptr: 415 .indirect_symbol _ffi64_data_size 416 .g_long dyld_stub_binding_helper 417 418#endif // __ppc64__ 419