Thomas Heller | 8bdf81d | 2008-03-04 20:09:11 +0000 | [diff] [blame] | 1 | #if defined(__ppc__) || defined(__ppc64__) |
| 2 | |
| 3 | /* ----------------------------------------------------------------------- |
Ronald Oussoren | 16766d7 | 2009-09-20 18:54:16 +0000 | [diff] [blame^] | 4 | ppc-darwin.S - Copyright (c) 2000 John Hornkvist |
Thomas Heller | 8bdf81d | 2008-03-04 20:09:11 +0000 | [diff] [blame] | 5 | Copyright (c) 2004 Free Software Foundation, Inc. |
| 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 <fficonfig.h> |
| 32 | #include <ffi.h> |
| 33 | #include <ppc-darwin.h> |
| 34 | #include <architecture/ppc/mode_independent_asm.h> |
| 35 | |
| 36 | .text |
| 37 | .align 2 |
| 38 | .globl _ffi_prep_args |
| 39 | |
| 40 | .text |
| 41 | .align 2 |
| 42 | .globl _ffi_call_DARWIN |
| 43 | |
| 44 | .text |
| 45 | .align 2 |
| 46 | _ffi_call_DARWIN: |
| 47 | LFB0: |
| 48 | mr r12,r8 /* We only need r12 until the call, |
| 49 | so it doesn't have to be saved. */ |
| 50 | |
| 51 | LFB1: |
| 52 | /* Save the old stack pointer as AP. */ |
| 53 | mr r8,r1 |
| 54 | |
| 55 | LCFI0: |
| 56 | #if defined(__ppc64__) |
| 57 | /* Allocate the stack space we need. |
| 58 | r4 (size of input data) |
| 59 | 48 bytes (linkage area) |
| 60 | 40 bytes (saved registers) |
| 61 | 8 bytes (extra FPR) |
| 62 | r4 + 96 bytes total |
| 63 | */ |
| 64 | |
| 65 | addi r4,r4,-96 // Add our overhead. |
| 66 | li r0,-32 // Align to 32 bytes. |
| 67 | and r4,r4,r0 |
| 68 | #endif |
| 69 | stgux r1,r1,r4 // Grow the stack. |
| 70 | mflr r9 |
| 71 | |
| 72 | /* Save registers we use. */ |
| 73 | #if defined(__ppc64__) |
| 74 | std r27,-40(r8) |
| 75 | #endif |
| 76 | stg r28,MODE_CHOICE(-16,-32)(r8) |
| 77 | stg r29,MODE_CHOICE(-12,-24)(r8) |
| 78 | stg r30,MODE_CHOICE(-8,-16)(r8) |
| 79 | stg r31,MODE_CHOICE(-4,-8)(r8) |
| 80 | stg r9,SF_RETURN(r8) /* return address */ |
| 81 | #if !defined(POWERPC_DARWIN) /* TOC unused in OS X */ |
| 82 | stg r2,MODE_CHOICE(20,40)(r1) |
| 83 | #endif |
| 84 | |
| 85 | LCFI1: |
| 86 | #if defined(__ppc64__) |
| 87 | mr r27,r3 // our extended_cif |
| 88 | #endif |
| 89 | /* Save arguments over call. */ |
| 90 | mr r31,r5 /* flags, */ |
| 91 | mr r30,r6 /* rvalue, */ |
| 92 | mr r29,r7 /* function address, */ |
| 93 | mr r28,r8 /* our AP. */ |
| 94 | |
| 95 | LCFI2: |
| 96 | /* Call ffi_prep_args. */ |
| 97 | mr r4,r1 |
| 98 | li r9,0 |
| 99 | mtctr r12 /* r12 holds address of _ffi_prep_args. */ |
| 100 | bctrl |
| 101 | #if !defined(POWERPC_DARWIN) /* TOC unused in OS X */ |
| 102 | lg r2,MODE_CHOICE(20,40)(r1) |
| 103 | #endif |
| 104 | |
| 105 | /* Now do the call. |
| 106 | Set up cr1 with bits 4-7 of the flags. */ |
| 107 | mtcrf 0x40,r31 |
| 108 | |
| 109 | /* Load all those argument registers. |
| 110 | We have set up a nice stack frame, just load it into registers. */ |
| 111 | lg r3,SF_ARG1(r1) |
| 112 | lg r4,SF_ARG2(r1) |
| 113 | lg r5,SF_ARG3(r1) |
| 114 | lg r6,SF_ARG4(r1) |
| 115 | nop |
| 116 | lg r7,SF_ARG5(r1) |
| 117 | lg r8,SF_ARG6(r1) |
| 118 | lg r9,SF_ARG7(r1) |
| 119 | lg r10,SF_ARG8(r1) |
| 120 | |
| 121 | /* Load all the FP registers. */ |
| 122 | bf 6,L2 /* No floats to load. */ |
| 123 | #if defined(__ppc64__) |
| 124 | lfd f1,MODE_CHOICE(-16,-40)-(14*8)(r28) |
| 125 | lfd f2,MODE_CHOICE(-16,-40)-(13*8)(r28) |
| 126 | lfd f3,MODE_CHOICE(-16,-40)-(12*8)(r28) |
| 127 | lfd f4,MODE_CHOICE(-16,-40)-(11*8)(r28) |
| 128 | nop |
| 129 | lfd f5,MODE_CHOICE(-16,-40)-(10*8)(r28) |
| 130 | lfd f6,MODE_CHOICE(-16,-40)-(9*8)(r28) |
| 131 | lfd f7,MODE_CHOICE(-16,-40)-(8*8)(r28) |
| 132 | lfd f8,MODE_CHOICE(-16,-40)-(7*8)(r28) |
| 133 | nop |
| 134 | lfd f9,MODE_CHOICE(-16,-40)-(6*8)(r28) |
| 135 | lfd f10,MODE_CHOICE(-16,-40)-(5*8)(r28) |
| 136 | lfd f11,MODE_CHOICE(-16,-40)-(4*8)(r28) |
| 137 | lfd f12,MODE_CHOICE(-16,-40)-(3*8)(r28) |
| 138 | nop |
| 139 | lfd f13,MODE_CHOICE(-16,-40)-(2*8)(r28) |
| 140 | lfd f14,MODE_CHOICE(-16,-40)-(1*8)(r28) |
| 141 | #elif defined(__ppc__) |
| 142 | lfd f1,MODE_CHOICE(-16,-40)-(13*8)(r28) |
| 143 | lfd f2,MODE_CHOICE(-16,-40)-(12*8)(r28) |
| 144 | lfd f3,MODE_CHOICE(-16,-40)-(11*8)(r28) |
| 145 | lfd f4,MODE_CHOICE(-16,-40)-(10*8)(r28) |
| 146 | nop |
| 147 | lfd f5,MODE_CHOICE(-16,-40)-(9*8)(r28) |
| 148 | lfd f6,MODE_CHOICE(-16,-40)-(8*8)(r28) |
| 149 | lfd f7,MODE_CHOICE(-16,-40)-(7*8)(r28) |
| 150 | lfd f8,MODE_CHOICE(-16,-40)-(6*8)(r28) |
| 151 | nop |
| 152 | lfd f9,MODE_CHOICE(-16,-40)-(5*8)(r28) |
| 153 | lfd f10,MODE_CHOICE(-16,-40)-(4*8)(r28) |
| 154 | lfd f11,MODE_CHOICE(-16,-40)-(3*8)(r28) |
| 155 | lfd f12,MODE_CHOICE(-16,-40)-(2*8)(r28) |
| 156 | nop |
| 157 | lfd f13,MODE_CHOICE(-16,-40)-(1*8)(r28) |
| 158 | #else |
| 159 | #error undefined architecture |
| 160 | #endif |
| 161 | |
| 162 | L2: |
| 163 | mr r12,r29 // Put the target address in r12 as specified. |
| 164 | mtctr r12 // Get the address to call into CTR. |
| 165 | nop |
| 166 | nop |
| 167 | bctrl // Make the call. |
| 168 | |
| 169 | // Deal with the return value. |
| 170 | #if defined(__ppc64__) |
| 171 | mtcrf 0x3,r31 // flags in cr6 and cr7 |
| 172 | bt 27,L(st_return_value) |
| 173 | #elif defined(__ppc__) |
| 174 | mtcrf 0x1,r31 // flags in cr7 |
| 175 | #else |
| 176 | #error undefined architecture |
| 177 | #endif |
| 178 | |
| 179 | bt 30,L(done_return_value) |
| 180 | bt 29,L(fp_return_value) |
| 181 | stg r3,0(r30) |
| 182 | #if defined(__ppc__) |
| 183 | bf 28,L(done_return_value) // Store the second long if necessary. |
| 184 | stg r4,4(r30) |
| 185 | #endif |
| 186 | // Fall through |
| 187 | |
| 188 | L(done_return_value): |
| 189 | lg r1,0(r1) // Restore stack pointer. |
| 190 | // Restore the registers we used. |
| 191 | lg r9,SF_RETURN(r1) // return address |
| 192 | lg r31,MODE_CHOICE(-4,-8)(r1) |
| 193 | mtlr r9 |
| 194 | lg r30,MODE_CHOICE(-8,-16)(r1) |
| 195 | lg r29,MODE_CHOICE(-12,-24)(r1) |
| 196 | lg r28,MODE_CHOICE(-16,-32)(r1) |
| 197 | #if defined(__ppc64__) |
| 198 | ld r27,-40(r1) |
| 199 | #endif |
| 200 | blr |
| 201 | |
| 202 | #if defined(__ppc64__) |
| 203 | L(st_return_value): |
| 204 | // Grow the stack enough to fit the registers. Leave room for 8 args |
| 205 | // to trample the 1st 8 slots in param area. |
| 206 | stgu r1,-SF_ROUND(280)(r1) // 64 + 104 + 48 + 64 |
| 207 | |
| 208 | // Store GPRs |
| 209 | std r3,SF_ARG9(r1) |
| 210 | std r4,SF_ARG10(r1) |
| 211 | std r5,SF_ARG11(r1) |
| 212 | std r6,SF_ARG12(r1) |
| 213 | nop |
| 214 | std r7,SF_ARG13(r1) |
| 215 | std r8,SF_ARG14(r1) |
| 216 | std r9,SF_ARG15(r1) |
| 217 | std r10,SF_ARG16(r1) |
| 218 | |
| 219 | // Store FPRs |
| 220 | nop |
| 221 | bf 26,L(call_struct_to_ram_form) |
| 222 | stfd f1,SF_ARG17(r1) |
| 223 | stfd f2,SF_ARG18(r1) |
| 224 | stfd f3,SF_ARG19(r1) |
| 225 | stfd f4,SF_ARG20(r1) |
| 226 | nop |
| 227 | stfd f5,SF_ARG21(r1) |
| 228 | stfd f6,SF_ARG22(r1) |
| 229 | stfd f7,SF_ARG23(r1) |
| 230 | stfd f8,SF_ARG24(r1) |
| 231 | nop |
| 232 | stfd f9,SF_ARG25(r1) |
| 233 | stfd f10,SF_ARG26(r1) |
| 234 | stfd f11,SF_ARG27(r1) |
| 235 | stfd f12,SF_ARG28(r1) |
| 236 | nop |
| 237 | stfd f13,SF_ARG29(r1) |
| 238 | |
| 239 | L(call_struct_to_ram_form): |
| 240 | ld r3,0(r27) // extended_cif->cif* |
| 241 | ld r3,16(r3) // ffi_cif->rtype* |
| 242 | addi r4,r1,SF_ARG9 // stored GPRs |
| 243 | addi r6,r1,SF_ARG17 // stored FPRs |
| 244 | li r5,0 // GPR size ptr (NULL) |
| 245 | li r7,0 // FPR size ptr (NULL) |
| 246 | li r8,0 // FPR count ptr (NULL) |
| 247 | li r10,0 // struct offset (NULL) |
| 248 | mr r9,r30 // return area |
| 249 | bl Lffi64_struct_to_ram_form$stub |
| 250 | lg r1,0(r1) // Restore stack pointer. |
| 251 | b L(done_return_value) |
| 252 | #endif |
| 253 | |
| 254 | L(fp_return_value): |
| 255 | /* Do we have long double to store? */ |
| 256 | bf 31,L(fd_return_value) |
| 257 | stfd f1,0(r30) |
| 258 | stfd f2,8(r30) |
| 259 | b L(done_return_value) |
| 260 | |
| 261 | L(fd_return_value): |
| 262 | /* Do we have double to store? */ |
| 263 | bf 28,L(float_return_value) |
| 264 | stfd f1,0(r30) |
| 265 | b L(done_return_value) |
| 266 | |
| 267 | L(float_return_value): |
| 268 | /* We only have a float to store. */ |
| 269 | stfs f1,0(r30) |
| 270 | b L(done_return_value) |
| 271 | |
| 272 | LFE1: |
| 273 | /* END(_ffi_call_DARWIN) */ |
| 274 | |
| 275 | /* Provide a null definition of _ffi_call_AIX. */ |
| 276 | .text |
| 277 | .align 2 |
| 278 | .globl _ffi_call_AIX |
| 279 | .text |
| 280 | .align 2 |
| 281 | _ffi_call_AIX: |
| 282 | blr |
| 283 | /* END(_ffi_call_AIX) */ |
| 284 | |
| 285 | .section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms |
| 286 | EH_frame1: |
| 287 | .set L$set$0,LECIE1-LSCIE1 |
| 288 | .long L$set$0 ; Length of Common Information Entry |
| 289 | LSCIE1: |
| 290 | .long 0x0 ; CIE Identifier Tag |
| 291 | .byte 0x1 ; CIE Version |
| 292 | .ascii "zR\0" ; CIE Augmentation |
| 293 | .byte 0x1 ; uleb128 0x1; CIE Code Alignment Factor |
| 294 | .byte 0x7c ; sleb128 -4; CIE Data Alignment Factor |
| 295 | .byte 0x41 ; CIE RA Column |
| 296 | .byte 0x1 ; uleb128 0x1; Augmentation size |
Ronald Oussoren | 16766d7 | 2009-09-20 18:54:16 +0000 | [diff] [blame^] | 297 | .byte 0x10 ; FDE Encoding (pcrel) |
Thomas Heller | 8bdf81d | 2008-03-04 20:09:11 +0000 | [diff] [blame] | 298 | .byte 0xc ; DW_CFA_def_cfa |
| 299 | .byte 0x1 ; uleb128 0x1 |
| 300 | .byte 0x0 ; uleb128 0x0 |
| 301 | .align LOG2_GPR_BYTES |
| 302 | LECIE1: |
| 303 | .globl _ffi_call_DARWIN.eh |
| 304 | _ffi_call_DARWIN.eh: |
| 305 | LSFDE1: |
| 306 | .set L$set$1,LEFDE1-LASFDE1 |
| 307 | .long L$set$1 ; FDE Length |
| 308 | |
| 309 | LASFDE1: |
| 310 | .long LASFDE1-EH_frame1 ; FDE CIE offset |
Ronald Oussoren | 16766d7 | 2009-09-20 18:54:16 +0000 | [diff] [blame^] | 311 | .g_long LFB0-. ; FDE initial location |
Thomas Heller | 8bdf81d | 2008-03-04 20:09:11 +0000 | [diff] [blame] | 312 | .set L$set$3,LFE1-LFB0 |
| 313 | .g_long L$set$3 ; FDE address range |
| 314 | .byte 0x0 ; uleb128 0x0; Augmentation size |
| 315 | .byte 0x4 ; DW_CFA_advance_loc4 |
| 316 | .set L$set$4,LCFI0-LFB1 |
| 317 | .long L$set$4 |
| 318 | .byte 0xd ; DW_CFA_def_cfa_register |
| 319 | .byte 0x08 ; uleb128 0x08 |
| 320 | .byte 0x4 ; DW_CFA_advance_loc4 |
| 321 | .set L$set$5,LCFI1-LCFI0 |
| 322 | .long L$set$5 |
| 323 | .byte 0x11 ; DW_CFA_offset_extended_sf |
| 324 | .byte 0x41 ; uleb128 0x41 |
| 325 | .byte 0x7e ; sleb128 -2 |
| 326 | .byte 0x9f ; DW_CFA_offset, column 0x1f |
| 327 | .byte 0x1 ; uleb128 0x1 |
| 328 | .byte 0x9e ; DW_CFA_offset, column 0x1e |
| 329 | .byte 0x2 ; uleb128 0x2 |
| 330 | .byte 0x9d ; DW_CFA_offset, column 0x1d |
| 331 | .byte 0x3 ; uleb128 0x3 |
| 332 | .byte 0x9c ; DW_CFA_offset, column 0x1c |
| 333 | .byte 0x4 ; uleb128 0x4 |
| 334 | .byte 0x4 ; DW_CFA_advance_loc4 |
| 335 | .set L$set$6,LCFI2-LCFI1 |
| 336 | .long L$set$6 |
| 337 | .byte 0xd ; DW_CFA_def_cfa_register |
| 338 | .byte 0x1c ; uleb128 0x1c |
| 339 | .align LOG2_GPR_BYTES |
| 340 | LEFDE1: |
Thomas Heller | 8bdf81d | 2008-03-04 20:09:11 +0000 | [diff] [blame] | 341 | |
| 342 | #if defined(__ppc64__) |
| 343 | .section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32 |
| 344 | .align LOG2_GPR_BYTES |
| 345 | |
| 346 | Lffi64_struct_to_ram_form$stub: |
| 347 | .indirect_symbol _ffi64_struct_to_ram_form |
| 348 | mflr r0 |
| 349 | bcl 20,31,LO$ffi64_struct_to_ram_form |
| 350 | |
| 351 | LO$ffi64_struct_to_ram_form: |
| 352 | mflr r11 |
| 353 | addis r11,r11,ha16(L_ffi64_struct_to_ram_form$lazy_ptr - LO$ffi64_struct_to_ram_form) |
| 354 | mtlr r0 |
| 355 | lgu r12,lo16(L_ffi64_struct_to_ram_form$lazy_ptr - LO$ffi64_struct_to_ram_form)(r11) |
| 356 | mtctr r12 |
| 357 | bctr |
| 358 | |
| 359 | .lazy_symbol_pointer |
| 360 | L_ffi64_struct_to_ram_form$lazy_ptr: |
| 361 | .indirect_symbol _ffi64_struct_to_ram_form |
| 362 | .g_long dyld_stub_binding_helper |
| 363 | |
| 364 | #endif // __ppc64__ |
| 365 | #endif // __ppc__ || __ppc64__ |