1/* ----------------------------------------------------------------------- 2 aix_closure.S - Copyright (c) 2002, 2003, 2009 Free Software Foundation, Inc. 3 based on darwin_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 .set r0,0 28 .set r1,1 29 .set r2,2 30 .set r3,3 31 .set r4,4 32 .set r5,5 33 .set r6,6 34 .set r7,7 35 .set r8,8 36 .set r9,9 37 .set r10,10 38 .set r11,11 39 .set r12,12 40 .set r13,13 41 .set r14,14 42 .set r15,15 43 .set r16,16 44 .set r17,17 45 .set r18,18 46 .set r19,19 47 .set r20,20 48 .set r21,21 49 .set r22,22 50 .set r23,23 51 .set r24,24 52 .set r25,25 53 .set r26,26 54 .set r27,27 55 .set r28,28 56 .set r29,29 57 .set r30,30 58 .set r31,31 59 .set f0,0 60 .set f1,1 61 .set f2,2 62 .set f3,3 63 .set f4,4 64 .set f5,5 65 .set f6,6 66 .set f7,7 67 .set f8,8 68 .set f9,9 69 .set f10,10 70 .set f11,11 71 .set f12,12 72 .set f13,13 73 .set f14,14 74 .set f15,15 75 .set f16,16 76 .set f17,17 77 .set f18,18 78 .set f19,19 79 .set f20,20 80 .set f21,21 81 82 .extern .ffi_closure_helper_DARWIN 83 84#define LIBFFI_ASM 85#define JUMPTARGET(name) name 86#define L(x) x 87 .file "aix_closure.S" 88 .toc 89LC..60: 90 .tc L..60[TC],L..60 91 .csect .text[PR] 92 .align 2 93 94.csect .text[PR] 95 .align 2 96 .globl ffi_closure_ASM 97 .globl .ffi_closure_ASM 98.csect ffi_closure_ASM[DS] 99ffi_closure_ASM: 100#ifdef __64BIT__ 101 .llong .ffi_closure_ASM, TOC[tc0], 0 102 .csect .text[PR] 103.ffi_closure_ASM: 104/* we want to build up an area for the parameters passed */ 105/* in registers (both floating point and integer) */ 106 107 /* we store gpr 3 to gpr 10 (aligned to 4) 108 in the parents outgoing area */ 109 std r3, 48+(0*8)(r1) 110 std r4, 48+(1*8)(r1) 111 std r5, 48+(2*8)(r1) 112 std r6, 48+(3*8)(r1) 113 mflr r0 114 115 std r7, 48+(4*8)(r1) 116 std r8, 48+(5*8)(r1) 117 std r9, 48+(6*8)(r1) 118 std r10, 48+(7*8)(r1) 119 std r0, 16(r1) /* save the return address */ 120 121 122 /* 48 Bytes (Linkage Area) */ 123 /* 64 Bytes (params) */ 124 /* 16 Bytes (result) */ 125 /* 104 Bytes (13*8 from FPR) */ 126 /* 8 Bytes (alignment) */ 127 /* 240 Bytes */ 128 129 stdu r1, -240(r1) /* skip over caller save area 130 keep stack aligned to 16 */ 131 132 /* next save fpr 1 to fpr 13 (aligned to 8) */ 133 stfd f1, 128+(0*8)(r1) 134 stfd f2, 128+(1*8)(r1) 135 stfd f3, 128+(2*8)(r1) 136 stfd f4, 128+(3*8)(r1) 137 stfd f5, 128+(4*8)(r1) 138 stfd f6, 128+(5*8)(r1) 139 stfd f7, 128+(6*8)(r1) 140 stfd f8, 128+(7*8)(r1) 141 stfd f9, 128+(8*8)(r1) 142 stfd f10, 128+(9*8)(r1) 143 stfd f11, 128+(10*8)(r1) 144 stfd f12, 128+(11*8)(r1) 145 stfd f13, 128+(12*8)(r1) 146 147 /* set up registers for the routine that actually does the work */ 148 /* get the context pointer from the trampoline */ 149 mr r3, r11 150 151 /* now load up the pointer to the result storage */ 152 addi r4, r1, 112 153 154 /* now load up the pointer to the saved gpr registers */ 155 addi r5, r1, 288 156 157 /* now load up the pointer to the saved fpr registers */ 158 addi r6, r1, 128 159 160 /* make the call */ 161 bl .ffi_closure_helper_DARWIN 162 nop 163 164 /* now r3 contains the return type */ 165 /* so use it to look up in a table */ 166 /* so we know how to deal with each type */ 167 168 /* look up the proper starting point in table */ 169 /* by using return type as offset */ 170 lhz r3, 10(r3) /* load type from return type */ 171 ld r4, LC..60(2) /* get address of jump table */ 172 sldi r3, r3, 4 /* now multiply return type by 16 */ 173 ld r0, 240+16(r1) /* load return address */ 174 add r3, r3, r4 /* add contents of table to table address */ 175 mtctr r3 176 bctr /* jump to it */ 177 178/* Each fragment must be exactly 16 bytes long (4 instructions). 179 Align to 16 byte boundary for cache and dispatch efficiency. */ 180 .align 4 181 182L..60: 183/* case FFI_TYPE_VOID */ 184 mtlr r0 185 addi r1, r1, 240 186 blr 187 nop 188 189/* case FFI_TYPE_INT */ 190 lwa r3, 112+4(r1) 191 mtlr r0 192 addi r1, r1, 240 193 blr 194 195/* case FFI_TYPE_FLOAT */ 196 lfs f1, 112+0(r1) 197 mtlr r0 198 addi r1, r1, 240 199 blr 200 201/* case FFI_TYPE_DOUBLE */ 202 lfd f1, 112+0(r1) 203 mtlr r0 204 addi r1, r1, 240 205 blr 206 207/* case FFI_TYPE_LONGDOUBLE */ 208 lfd f1, 112+0(r1) 209 mtlr r0 210 lfd f2, 112+8(r1) 211 b L..finish 212 213/* case FFI_TYPE_UINT8 */ 214 lbz r3, 112+7(r1) 215 mtlr r0 216 addi r1, r1, 240 217 blr 218 219/* case FFI_TYPE_SINT8 */ 220 lbz r3, 112+7(r1) 221 mtlr r0 222 extsb r3, r3 223 b L..finish 224 225/* case FFI_TYPE_UINT16 */ 226 lhz r3, 112+6(r1) 227 mtlr r0 228L..finish: 229 addi r1, r1, 240 230 blr 231 232/* case FFI_TYPE_SINT16 */ 233 lha r3, 112+6(r1) 234 mtlr r0 235 addi r1, r1, 240 236 blr 237 238/* case FFI_TYPE_UINT32 */ 239 lwz r3, 112+4(r1) 240 mtlr r0 241 addi r1, r1, 240 242 blr 243 244/* case FFI_TYPE_SINT32 */ 245 lwa r3, 112+4(r1) 246 mtlr r0 247 addi r1, r1, 240 248 blr 249 250/* case FFI_TYPE_UINT64 */ 251 ld r3, 112+0(r1) 252 mtlr r0 253 addi r1, r1, 240 254 blr 255 256/* case FFI_TYPE_SINT64 */ 257 ld r3, 112+0(r1) 258 mtlr r0 259 addi r1, r1, 240 260 blr 261 262/* case FFI_TYPE_STRUCT */ 263 mtlr r0 264 addi r1, r1, 240 265 blr 266 nop 267 268/* case FFI_TYPE_POINTER */ 269 ld r3, 112+0(r1) 270 mtlr r0 271 addi r1, r1, 240 272 blr 273 274#else /* ! __64BIT__ */ 275 276 .long .ffi_closure_ASM, TOC[tc0], 0 277 .csect .text[PR] 278.ffi_closure_ASM: 279/* we want to build up an area for the parameters passed */ 280/* in registers (both floating point and integer) */ 281 282 /* we store gpr 3 to gpr 10 (aligned to 4) 283 in the parents outgoing area */ 284 stw r3, 24+(0*4)(r1) 285 stw r4, 24+(1*4)(r1) 286 stw r5, 24+(2*4)(r1) 287 stw r6, 24+(3*4)(r1) 288 mflr r0 289 290 stw r7, 24+(4*4)(r1) 291 stw r8, 24+(5*4)(r1) 292 stw r9, 24+(6*4)(r1) 293 stw r10, 24+(7*4)(r1) 294 stw r0, 8(r1) 295 296 /* 24 Bytes (Linkage Area) */ 297 /* 32 Bytes (params) */ 298 /* 16 Bytes (result) */ 299 /* 104 Bytes (13*8 from FPR) */ 300 /* 176 Bytes */ 301 302 stwu r1, -176(r1) /* skip over caller save area 303 keep stack aligned to 16 */ 304 305 /* next save fpr 1 to fpr 13 (aligned to 8) */ 306 stfd f1, 72+(0*8)(r1) 307 stfd f2, 72+(1*8)(r1) 308 stfd f3, 72+(2*8)(r1) 309 stfd f4, 72+(3*8)(r1) 310 stfd f5, 72+(4*8)(r1) 311 stfd f6, 72+(5*8)(r1) 312 stfd f7, 72+(6*8)(r1) 313 stfd f8, 72+(7*8)(r1) 314 stfd f9, 72+(8*8)(r1) 315 stfd f10, 72+(9*8)(r1) 316 stfd f11, 72+(10*8)(r1) 317 stfd f12, 72+(11*8)(r1) 318 stfd f13, 72+(12*8)(r1) 319 320 /* set up registers for the routine that actually does the work */ 321 /* get the context pointer from the trampoline */ 322 mr r3, r11 323 324 /* now load up the pointer to the result storage */ 325 addi r4, r1, 56 326 327 /* now load up the pointer to the saved gpr registers */ 328 addi r5, r1, 200 329 330 /* now load up the pointer to the saved fpr registers */ 331 addi r6, r1, 72 332 333 /* make the call */ 334 bl .ffi_closure_helper_DARWIN 335 nop 336 337 /* now r3 contains the return type */ 338 /* so use it to look up in a table */ 339 /* so we know how to deal with each type */ 340 341 /* look up the proper starting point in table */ 342 /* by using return type as offset */ 343 lhz r3, 6(r3) /* load type from return type */ 344 lwz r4, LC..60(2) /* get address of jump table */ 345 slwi r3, r3, 4 /* now multiply return type by 16 */ 346 lwz r0, 176+8(r1) /* load return address */ 347 add r3, r3, r4 /* add contents of table to table address */ 348 mtctr r3 349 bctr /* jump to it */ 350 351/* Each fragment must be exactly 16 bytes long (4 instructions). 352 Align to 16 byte boundary for cache and dispatch efficiency. */ 353 .align 4 354 355L..60: 356/* case FFI_TYPE_VOID */ 357 mtlr r0 358 addi r1, r1, 176 359 blr 360 nop 361 362/* case FFI_TYPE_INT */ 363 lwz r3, 56+0(r1) 364 mtlr r0 365 addi r1, r1, 176 366 blr 367 368/* case FFI_TYPE_FLOAT */ 369 lfs f1, 56+0(r1) 370 mtlr r0 371 addi r1, r1, 176 372 blr 373 374/* case FFI_TYPE_DOUBLE */ 375 lfd f1, 56+0(r1) 376 mtlr r0 377 addi r1, r1, 176 378 blr 379 380/* case FFI_TYPE_LONGDOUBLE */ 381 lfd f1, 56+0(r1) 382 mtlr r0 383 lfd f2, 56+8(r1) 384 b L..finish 385 386/* case FFI_TYPE_UINT8 */ 387 lbz r3, 56+3(r1) 388 mtlr r0 389 addi r1, r1, 176 390 blr 391 392/* case FFI_TYPE_SINT8 */ 393 lbz r3, 56+3(r1) 394 mtlr r0 395 extsb r3, r3 396 b L..finish 397 398/* case FFI_TYPE_UINT16 */ 399 lhz r3, 56+2(r1) 400 mtlr r0 401 addi r1, r1, 176 402 blr 403 404/* case FFI_TYPE_SINT16 */ 405 lha r3, 56+2(r1) 406 mtlr r0 407 addi r1, r1, 176 408 blr 409 410/* case FFI_TYPE_UINT32 */ 411 lwz r3, 56+0(r1) 412 mtlr r0 413 addi r1, r1, 176 414 blr 415 416/* case FFI_TYPE_SINT32 */ 417 lwz r3, 56+0(r1) 418 mtlr r0 419 addi r1, r1, 176 420 blr 421 422/* case FFI_TYPE_UINT64 */ 423 lwz r3, 56+0(r1) 424 mtlr r0 425 lwz r4, 56+4(r1) 426 b L..finish 427 428/* case FFI_TYPE_SINT64 */ 429 lwz r3, 56+0(r1) 430 mtlr r0 431 lwz r4, 56+4(r1) 432 b L..finish 433 434/* case FFI_TYPE_STRUCT */ 435 mtlr r0 436 addi r1, r1, 176 437 blr 438 nop 439 440/* case FFI_TYPE_POINTER */ 441 lwz r3, 56+0(r1) 442 mtlr r0 443L..finish: 444 addi r1, r1, 176 445 blr 446#endif 447/* END(ffi_closure_ASM) */ 448