1 /* ----------------------------------------------------------------------- 2 darwin_closure.S - Copyright (c) 2002, 2003, 2004, Free Software Foundation, 3 Inc. based on ppc_closure.S 4 5 PowerPC Assembly glue. 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, EXPRESS 19 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR 22 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 23 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 24 OTHER DEALINGS IN THE SOFTWARE. 25 ----------------------------------------------------------------------- */ 26 27 #define LIBFFI_ASM 28 #define L(x) x 29 30 #if defined(__ppc64__) 31 #define MODE_CHOICE(x, y) y 32 #else 33 #define MODE_CHOICE(x, y) x 34 #endif 35 36 #define lgu MODE_CHOICE(lwzu, ldu) 37 38 #define g_long MODE_CHOICE(long, quad) /* usage is ".g_long" */ 39 40 #define LOG2_GPR_BYTES MODE_CHOICE(2,3) /* log2(GPR_BYTES) */ 41 42 .file "darwin_closure.S" 43 .text 44 .align LOG2_GPR_BYTES 45 .globl _ffi_closure_ASM 46 47 .text 48 .align LOG2_GPR_BYTES 49 _ffi_closure_ASM: 50 LFB1: 51 mflr r0 /* extract return address */ 52 stw r0,8(r1) /* save the return address */ 53 LCFI0: 54 /* 24 Bytes (Linkage Area) 55 32 Bytes (outgoing parameter area, always reserved) 56 104 Bytes (13*8 from FPR) 57 16 Bytes (result) 58 176 Bytes */ 59 60 stwu r1,-176(r1) /* skip over caller save area 61 keep stack aligned to 16. */ 62 LCFI1: 63 /* We want to build up an area for the parameters passed 64 in registers. (both floating point and integer) */ 65 66 /* We store gpr 3 to gpr 10 (aligned to 4) 67 in the parents outgoing area. */ 68 stw r3,200(r1) 69 stw r4,204(r1) 70 stw r5,208(r1) 71 stw r6,212(r1) 72 stw r7,216(r1) 73 stw r8,220(r1) 74 stw r9,224(r1) 75 stw r10,228(r1) 76 77 /* We save fpr 1 to fpr 13. (aligned to 8) */ 78 stfd f1,56(r1) 79 stfd f2,64(r1) 80 stfd f3,72(r1) 81 stfd f4,80(r1) 82 stfd f5,88(r1) 83 stfd f6,96(r1) 84 stfd f7,104(r1) 85 stfd f8,112(r1) 86 stfd f9,120(r1) 87 stfd f10,128(r1) 88 stfd f11,136(r1) 89 stfd f12,144(r1) 90 stfd f13,152(r1) 91 92 /* Set up registers for the routine that actually does the work 93 get the context pointer from the trampoline. */ 94 mr r3,r11 95 96 /* Now load up the pointer to the result storage. */ 97 addi r4,r1,160 98 99 /* Now load up the pointer to the saved gpr registers. */ 100 addi r5,r1,200 101 102 /* Now load up the pointer to the saved fpr registers. */ 103 addi r6,r1,56 104 105 /* Make the call. */ 106 bl Lffi_closure_helper_DARWIN$stub 107 108 /* Now r3 contains the return type 109 so use it to look up in a table 110 so we know how to deal with each type. */ 111 112 /* Look up the proper starting point in table 113 by using return type as offset. */ 114 addi r5,r1,160 /* Get pointer to results area. */ 115 bl Lget_ret_type0_addr /* Get pointer to Lret_type0 into LR. */ 116 mflr r4 /* Move to r4. */ 117 slwi r3,r3,4 /* Now multiply return type by 16. */ 118 add r3,r3,r4 /* Add contents of table to table address. */ 119 mtctr r3 120 bctr /* Jump to it. */ 121 LFE1: 122 /* Each of the ret_typeX code fragments has to be exactly 16 bytes long 123 (4 instructions). For cache effectiveness we align to a 16 byte boundary 124 first. */ 125 126 .align 4 127 128 nop 129 nop 130 nop 131 Lget_ret_type0_addr: 132 blrl 133 134 /* case FFI_TYPE_VOID */ 135 Lret_type0: 136 b Lfinish 137 nop 138 nop 139 nop 140 141 /* case FFI_TYPE_INT */ 142 Lret_type1: 143 lwz r3,0(r5) 144 b Lfinish 145 nop 146 nop 147 148 /* case FFI_TYPE_FLOAT */ 149 Lret_type2: 150 lfs f1,0(r5) 151 b Lfinish 152 nop 153 nop 154 155 /* case FFI_TYPE_DOUBLE */ 156 Lret_type3: 157 lfd f1,0(r5) 158 b Lfinish 159 nop 160 nop 161 162 /* case FFI_TYPE_LONGDOUBLE */ 163 Lret_type4: 164 lfd f1,0(r5) 165 lfd f2,8(r5) 166 b Lfinish 167 nop 168 169 /* case FFI_TYPE_UINT8 */ 170 Lret_type5: 171 lbz r3,3(r5) 172 b Lfinish 173 nop 174 nop 175 176 /* case FFI_TYPE_SINT8 */ 177 Lret_type6: 178 lbz r3,3(r5) 179 extsb r3,r3 180 b Lfinish 181 nop 182 183 /* case FFI_TYPE_UINT16 */ 184 Lret_type7: 185 lhz r3,2(r5) 186 b Lfinish 187 nop 188 nop 189 190 /* case FFI_TYPE_SINT16 */ 191 Lret_type8: 192 lha r3,2(r5) 193 b Lfinish 194 nop 195 nop 196 197 /* case FFI_TYPE_UINT32 */ 198 Lret_type9: 199 lwz r3,0(r5) 200 b Lfinish 201 nop 202 nop 203 204 /* case FFI_TYPE_SINT32 */ 205 Lret_type10: 206 lwz r3,0(r5) 207 b Lfinish 208 nop 209 nop 210 211 /* case FFI_TYPE_UINT64 */ 212 Lret_type11: 213 lwz r3,0(r5) 214 lwz r4,4(r5) 215 b Lfinish 216 nop 217 218 /* case FFI_TYPE_SINT64 */ 219 Lret_type12: 220 lwz r3,0(r5) 221 lwz r4,4(r5) 222 b Lfinish 223 nop 224 225 /* case FFI_TYPE_STRUCT */ 226 Lret_type13: 227 b Lfinish 228 nop 229 nop 230 nop 231 232 /* case FFI_TYPE_POINTER */ 233 Lret_type14: 234 lwz r3,0(r5) 235 b Lfinish 236 nop 237 nop 238 239 /* case done */ 240 Lfinish: 241 addi r1,r1,176 /* Restore stack pointer. */ 242 lwz r0,8(r1) /* Get return address. */ 243 mtlr r0 /* Reset link register. */ 244 blr 245 246 /* END(ffi_closure_ASM) */ 247 248 .data 249 .section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support 250 EH_frame1: 251 .set L$set$0,LECIE1-LSCIE1 252 .long L$set$0 ; Length of Common Information Entry 253 LSCIE1: 254 .long 0x0 ; CIE Identifier Tag 255 .byte 0x1 ; CIE Version 256 .ascii "zR\0" ; CIE Augmentation 257 .byte 0x1 ; uleb128 0x1; CIE Code Alignment Factor 258 .byte 0x7c ; sleb128 -4; CIE Data Alignment Factor 259 .byte 0x41 ; CIE RA Column 260 .byte 0x1 ; uleb128 0x1; Augmentation size 261 .byte 0x90 ; FDE Encoding (indirect pcrel) 262 .byte 0xc ; DW_CFA_def_cfa 263 .byte 0x1 ; uleb128 0x1 264 .byte 0x0 ; uleb128 0x0 265 .align LOG2_GPR_BYTES 266 LECIE1: 267 .globl _ffi_closure_ASM.eh 268 _ffi_closure_ASM.eh: 269 LSFDE1: 270 .set L$set$1,LEFDE1-LASFDE1 271 .long L$set$1 ; FDE Length 272 273 LASFDE1: 274 .long LASFDE1-EH_frame1 ; FDE CIE offset 275 .g_long LLFB1$non_lazy_ptr-. ; FDE initial location 276 .set L$set$3,LFE1-LFB1 277 .g_long L$set$3 ; FDE address range 278 .byte 0x0 ; uleb128 0x0; Augmentation size 279 .byte 0x4 ; DW_CFA_advance_loc4 280 .set L$set$3,LCFI1-LCFI0 281 .long L$set$3 282 .byte 0xe ; DW_CFA_def_cfa_offset 283 .byte 176,1 ; uleb128 176 284 .byte 0x4 ; DW_CFA_advance_loc4 285 .set L$set$4,LCFI0-LFB1 286 .long L$set$4 287 .byte 0x11 ; DW_CFA_offset_extended_sf 288 .byte 0x41 ; uleb128 0x41 289 .byte 0x7e ; sleb128 -2 290 .align LOG2_GPR_BYTES 291 LEFDE1: 292 .data 293 .align LOG2_GPR_BYTES 294 LDFCM0: 295 .section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32 296 .align LOG2_GPR_BYTES 297 Lffi_closure_helper_DARWIN$stub: 298 #if 1 299 .indirect_symbol _ffi_closure_helper_DARWIN 300 mflr r0 301 bcl 20,31,LO$ffi_closure_helper_DARWIN 302 LO$ffi_closure_helper_DARWIN: 303 mflr r11 304 addis r11,r11,ha16(L_ffi_closure_helper_DARWIN$lazy_ptr - LO$ffi_closure_helper_DARWIN) 305 mtlr r0 306 lgu r12,lo16(L_ffi_closure_helper_DARWIN$lazy_ptr - LO$ffi_closure_helper_DARWIN)(r11) 307 mtctr r12 308 bctr 309 .lazy_symbol_pointer 310 L_ffi_closure_helper_DARWIN$lazy_ptr: 311 .indirect_symbol _ffi_closure_helper_DARWIN 312 .g_long dyld_stub_binding_helper 313 #endif 314 .data 315 .align LOG2_GPR_BYTES 316 LLFB1$non_lazy_ptr: 317 .g_long LFB1 318