1/* ----------------------------------------------------------------------- 2 aix.S - Copyright (c) 2002, 2009 Free Software Foundation, Inc. 3 based on darwin.S by John Hornkvist 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_prep_args 83 84#define LIBFFI_ASM 85#include <fficonfig.h> 86#include <ffi.h> 87#define JUMPTARGET(name) name 88#define L(x) x 89 .file "aix.S" 90 .toc 91 92 /* void ffi_call_AIX(extended_cif *ecif, unsigned long bytes, 93 * unsigned int flags, unsigned int *rvalue, 94 * void (*fn)(), 95 * void (*prep_args)(extended_cif*, unsigned *const)); 96 * r3=ecif, r4=bytes, r5=flags, r6=rvalue, r7=fn, r8=prep_args 97 */ 98 99.csect .text[PR] 100 .align 2 101 .globl ffi_call_AIX 102 .globl .ffi_call_AIX 103.csect ffi_call_AIX[DS] 104ffi_call_AIX: 105#ifdef __64BIT__ 106 .llong .ffi_call_AIX, TOC[tc0], 0 107 .csect .text[PR] 108.ffi_call_AIX: 109 .function .ffi_call_AIX,.ffi_call_AIX,16,044,LFE..0-LFB..0 110 .bf __LINE__ 111 .line 1 112LFB..0: 113 /* Save registers we use. */ 114 mflr r0 115 116 std r28,-32(r1) 117 std r29,-24(r1) 118 std r30,-16(r1) 119 std r31, -8(r1) 120 121 std r0, 16(r1) 122LCFI..0: 123 mr r28, r1 /* our AP. */ 124 stdux r1, r1, r4 125LCFI..1: 126 127 /* Save arguments over call... */ 128 mr r31, r5 /* flags, */ 129 mr r30, r6 /* rvalue, */ 130 mr r29, r7 /* function address. */ 131 std r2, 40(r1) 132 133 /* Call ffi_prep_args. */ 134 mr r4, r1 135 bl .ffi_prep_args 136 nop 137 138 /* Now do the call. */ 139 ld r0, 0(r29) 140 ld r2, 8(r29) 141 ld r11, 16(r29) 142 /* Set up cr1 with bits 4-7 of the flags. */ 143 mtcrf 0x40, r31 144 mtctr r0 145 /* Load all those argument registers. */ 146 /* We have set up a nice stack frame, just load it into registers. */ 147 ld r3, 40+(1*8)(r1) 148 ld r4, 40+(2*8)(r1) 149 ld r5, 40+(3*8)(r1) 150 ld r6, 40+(4*8)(r1) 151 nop 152 ld r7, 40+(5*8)(r1) 153 ld r8, 40+(6*8)(r1) 154 ld r9, 40+(7*8)(r1) 155 ld r10,40+(8*8)(r1) 156 157L1: 158 /* Load all the FP registers. */ 159 bf 6,L2 /* 2f + 0x18 */ 160 lfd f1,-32-(13*8)(r28) 161 lfd f2,-32-(12*8)(r28) 162 lfd f3,-32-(11*8)(r28) 163 lfd f4,-32-(10*8)(r28) 164 nop 165 lfd f5,-32-(9*8)(r28) 166 lfd f6,-32-(8*8)(r28) 167 lfd f7,-32-(7*8)(r28) 168 lfd f8,-32-(6*8)(r28) 169 nop 170 lfd f9,-32-(5*8)(r28) 171 lfd f10,-32-(4*8)(r28) 172 lfd f11,-32-(3*8)(r28) 173 lfd f12,-32-(2*8)(r28) 174 nop 175 lfd f13,-32-(1*8)(r28) 176 177L2: 178 /* Make the call. */ 179 bctrl 180 ld r2, 40(r1) 181 182 /* Now, deal with the return value. */ 183 mtcrf 0x01, r31 184 185 bt 30, L(done_return_value) 186 bt 29, L(fp_return_value) 187 std r3, 0(r30) 188 189 /* Fall through... */ 190 191L(done_return_value): 192 /* Restore the registers we used and return. */ 193 mr r1, r28 194 ld r0, 16(r28) 195 ld r28, -32(r1) 196 mtlr r0 197 ld r29, -24(r1) 198 ld r30, -16(r1) 199 ld r31, -8(r1) 200 blr 201 202L(fp_return_value): 203 bf 28, L(float_return_value) 204 stfd f1, 0(r30) 205 bf 31, L(done_return_value) 206 stfd f2, 8(r30) 207 b L(done_return_value) 208L(float_return_value): 209 stfs f1, 0(r30) 210 b L(done_return_value) 211LFE..0: 212#else /* ! __64BIT__ */ 213 214 .long .ffi_call_AIX, TOC[tc0], 0 215 .csect .text[PR] 216.ffi_call_AIX: 217 .function .ffi_call_AIX,.ffi_call_AIX,16,044,LFE..0-LFB..0 218 .bf __LINE__ 219 .line 1 220LFB..0: 221 /* Save registers we use. */ 222 mflr r0 223 224 stw r28,-16(r1) 225 stw r29,-12(r1) 226 stw r30, -8(r1) 227 stw r31, -4(r1) 228 229 stw r0, 8(r1) 230LCFI..0: 231 mr r28, r1 /* out AP. */ 232 stwux r1, r1, r4 233LCFI..1: 234 235 /* Save arguments over call... */ 236 mr r31, r5 /* flags, */ 237 mr r30, r6 /* rvalue, */ 238 mr r29, r7 /* function address, */ 239 stw r2, 20(r1) 240 241 /* Call ffi_prep_args. */ 242 mr r4, r1 243 bl .ffi_prep_args 244 nop 245 246 /* Now do the call. */ 247 lwz r0, 0(r29) 248 lwz r2, 4(r29) 249 lwz r11, 8(r29) 250 /* Set up cr1 with bits 4-7 of the flags. */ 251 mtcrf 0x40, r31 252 mtctr r0 253 /* Load all those argument registers. */ 254 /* We have set up a nice stack frame, just load it into registers. */ 255 lwz r3, 20+(1*4)(r1) 256 lwz r4, 20+(2*4)(r1) 257 lwz r5, 20+(3*4)(r1) 258 lwz r6, 20+(4*4)(r1) 259 nop 260 lwz r7, 20+(5*4)(r1) 261 lwz r8, 20+(6*4)(r1) 262 lwz r9, 20+(7*4)(r1) 263 lwz r10,20+(8*4)(r1) 264 265L1: 266 /* Load all the FP registers. */ 267 bf 6,L2 /* 2f + 0x18 */ 268 lfd f1,-16-(13*8)(r28) 269 lfd f2,-16-(12*8)(r28) 270 lfd f3,-16-(11*8)(r28) 271 lfd f4,-16-(10*8)(r28) 272 nop 273 lfd f5,-16-(9*8)(r28) 274 lfd f6,-16-(8*8)(r28) 275 lfd f7,-16-(7*8)(r28) 276 lfd f8,-16-(6*8)(r28) 277 nop 278 lfd f9,-16-(5*8)(r28) 279 lfd f10,-16-(4*8)(r28) 280 lfd f11,-16-(3*8)(r28) 281 lfd f12,-16-(2*8)(r28) 282 nop 283 lfd f13,-16-(1*8)(r28) 284 285L2: 286 /* Make the call. */ 287 bctrl 288 lwz r2, 20(r1) 289 290 /* Now, deal with the return value. */ 291 mtcrf 0x01, r31 292 293 bt 30, L(done_return_value) 294 bt 29, L(fp_return_value) 295 stw r3, 0(r30) 296 bf 28, L(done_return_value) 297 stw r4, 4(r30) 298 299 /* Fall through... */ 300 301L(done_return_value): 302 /* Restore the registers we used and return. */ 303 mr r1, r28 304 lwz r0, 8(r28) 305 lwz r28,-16(r1) 306 mtlr r0 307 lwz r29,-12(r1) 308 lwz r30, -8(r1) 309 lwz r31, -4(r1) 310 blr 311 312L(fp_return_value): 313 bf 28, L(float_return_value) 314 stfd f1, 0(r30) 315 b L(done_return_value) 316L(float_return_value): 317 stfs f1, 0(r30) 318 b L(done_return_value) 319LFE..0: 320#endif 321 .ef __LINE__ 322 .long 0 323 .byte 0,0,0,1,128,4,0,0 324/* END(ffi_call_AIX) */ 325 326 /* void ffi_call_go_AIX(extended_cif *ecif, unsigned long bytes, 327 * unsigned int flags, unsigned int *rvalue, 328 * void (*fn)(), 329 * void (*prep_args)(extended_cif*, unsigned *const), 330 * void *closure); 331 * r3=ecif, r4=bytes, r5=flags, r6=rvalue, r7=fn, r8=prep_args, r9=closure 332 */ 333 334.csect .text[PR] 335 .align 2 336 .globl ffi_call_go_AIX 337 .globl .ffi_call_go_AIX 338.csect ffi_call_go_AIX[DS] 339ffi_call_go_AIX: 340#ifdef __64BIT__ 341 .llong .ffi_call_go_AIX, TOC[tc0], 0 342 .csect .text[PR] 343.ffi_call_go_AIX: 344 .function .ffi_call_go_AIX,.ffi_call_go_AIX,16,044,LFE..1-LFB..1 345 .bf __LINE__ 346 .line 1 347LFB..1: 348 /* Save registers we use. */ 349 mflr r0 350 351 std r28,-32(r1) 352 std r29,-24(r1) 353 std r30,-16(r1) 354 std r31, -8(r1) 355 356 std r9, 8(r1) /* closure, saved in cr field. */ 357 std r0, 16(r1) 358LCFI..2: 359 mr r28, r1 /* our AP. */ 360 stdux r1, r1, r4 361LCFI..3: 362 363 /* Save arguments over call... */ 364 mr r31, r5 /* flags, */ 365 mr r30, r6 /* rvalue, */ 366 mr r29, r7 /* function address, */ 367 std r2, 40(r1) 368 369 /* Call ffi_prep_args. */ 370 mr r4, r1 371 bl .ffi_prep_args 372 nop 373 374 /* Now do the call. */ 375 ld r0, 0(r29) 376 ld r2, 8(r29) 377 ld r11, 8(r28) /* closure */ 378 /* Set up cr1 with bits 4-7 of the flags. */ 379 mtcrf 0x40, r31 380 mtctr r0 381 /* Load all those argument registers. */ 382 /* We have set up a nice stack frame, just load it into registers. */ 383 ld r3, 40+(1*8)(r1) 384 ld r4, 40+(2*8)(r1) 385 ld r5, 40+(3*8)(r1) 386 ld r6, 40+(4*8)(r1) 387 nop 388 ld r7, 40+(5*8)(r1) 389 ld r8, 40+(6*8)(r1) 390 ld r9, 40+(7*8)(r1) 391 ld r10,40+(8*8)(r1) 392 393 b L1 394LFE..1: 395#else /* ! __64BIT__ */ 396 397 .long .ffi_call_go_AIX, TOC[tc0], 0 398 .csect .text[PR] 399.ffi_call_go_AIX: 400 .function .ffi_call_go_AIX,.ffi_call_go_AIX,16,044,LFE..1-LFB..1 401 .bf __LINE__ 402 .line 1 403 /* Save registers we use. */ 404LFB..1: 405 mflr r0 406 407 stw r28,-16(r1) 408 stw r29,-12(r1) 409 stw r30, -8(r1) 410 stw r31, -4(r1) 411 412 stw r9, 4(r1) /* closure, saved in cr field. */ 413 stw r0, 8(r1) 414LCFI..2: 415 mr r28, r1 /* out AP. */ 416 stwux r1, r1, r4 417LCFI..3: 418 419 /* Save arguments over call... */ 420 mr r31, r5 /* flags, */ 421 mr r30, r6 /* rvalue, */ 422 mr r29, r7 /* function address, */ 423 stw r2, 20(r1) 424 425 /* Call ffi_prep_args. */ 426 mr r4, r1 427 bl .ffi_prep_args 428 nop 429 430 /* Now do the call. */ 431 lwz r0, 0(r29) 432 lwz r2, 4(r29) 433 lwz r11, 4(r28) /* closure */ 434 /* Set up cr1 with bits 4-7 of the flags. */ 435 mtcrf 0x40, r31 436 mtctr r0 437 /* Load all those argument registers. */ 438 /* We have set up a nice stack frame, just load it into registers. */ 439 lwz r3, 20+(1*4)(r1) 440 lwz r4, 20+(2*4)(r1) 441 lwz r5, 20+(3*4)(r1) 442 lwz r6, 20+(4*4)(r1) 443 nop 444 lwz r7, 20+(5*4)(r1) 445 lwz r8, 20+(6*4)(r1) 446 lwz r9, 20+(7*4)(r1) 447 lwz r10,20+(8*4)(r1) 448 449 b L1 450LFE..1: 451#endif 452 .ef __LINE__ 453 .long 0 454 .byte 0,0,0,1,128,4,0,0 455/* END(ffi_call_go_AIX) */ 456 457.csect .text[PR] 458 .align 2 459 .globl ffi_call_DARWIN 460 .globl .ffi_call_DARWIN 461.csect ffi_call_DARWIN[DS] 462ffi_call_DARWIN: 463#ifdef __64BIT__ 464 .llong .ffi_call_DARWIN, TOC[tc0], 0 465#else 466 .long .ffi_call_DARWIN, TOC[tc0], 0 467#endif 468 .csect .text[PR] 469.ffi_call_DARWIN: 470 blr 471 .long 0 472 .byte 0,0,0,0,0,0,0,0 473/* END(ffi_call_DARWIN) */ 474 475/* EH frame stuff. */ 476 477#define LR_REGNO 0x41 /* Link Register (65), see rs6000.md */ 478#ifdef __64BIT__ 479#define PTRSIZE 8 480#define LOG2_PTRSIZE 3 481#define FDE_ENCODING 0x1c /* DW_EH_PE_pcrel|DW_EH_PE_sdata8 */ 482#define EH_DATA_ALIGN_FACT 0x78 /* LEB128 -8 */ 483#else 484#define PTRSIZE 4 485#define LOG2_PTRSIZE 2 486#define FDE_ENCODING 0x1b /* DW_EH_PE_pcrel|DW_EH_PE_sdata4 */ 487#define EH_DATA_ALIGN_FACT 0x7c /* LEB128 -4 */ 488#endif 489 .csect _unwind.ro_[RO],4 490 .align LOG2_PTRSIZE 491 .globl _GLOBAL__F_libffi_src_powerpc_aix 492_GLOBAL__F_libffi_src_powerpc_aix: 493Lframe..1: 494 .vbyte 4,LECIE..1-LSCIE..1 /* CIE Length */ 495LSCIE..1: 496 .vbyte 4,0 /* CIE Identifier Tag */ 497 .byte 0x3 /* CIE Version */ 498 .byte "zR" /* CIE Augmentation */ 499 .byte 0 500 .byte 0x1 /* uleb128 0x1; CIE Code Alignment Factor */ 501 .byte EH_DATA_ALIGN_FACT /* leb128 -4/-8; CIE Data Alignment Factor */ 502 .byte 0x41 /* CIE RA Column */ 503 .byte 0x1 /* uleb128 0x1; Augmentation size */ 504 .byte FDE_ENCODING /* FDE Encoding (pcrel|sdata4/8) */ 505 .byte 0xc /* DW_CFA_def_cfa */ 506 .byte 0x1 /* uleb128 0x1; Register r1 */ 507 .byte 0 /* uleb128 0x0; Offset 0 */ 508 .align LOG2_PTRSIZE 509LECIE..1: 510LSFDE..1: 511 .vbyte 4,LEFDE..1-LASFDE..1 /* FDE Length */ 512LASFDE..1: 513 .vbyte 4,LASFDE..1-Lframe..1 /* FDE CIE offset */ 514 .vbyte PTRSIZE,LFB..0-$ /* FDE initial location */ 515 .vbyte PTRSIZE,LFE..0-LFB..0 /* FDE address range */ 516 .byte 0 /* uleb128 0x0; Augmentation size */ 517 .byte 0x4 /* DW_CFA_advance_loc4 */ 518 .vbyte 4,LCFI..0-LFB..0 519 .byte 0x11 /* DW_CFA_def_offset_extended_sf */ 520 .byte LR_REGNO /* uleb128 LR_REGNO; Register LR */ 521 .byte 0x7e /* leb128 -2; Offset -2 (8/16) */ 522 .byte 0x9f /* DW_CFA_offset Register r31 */ 523 .byte 0x1 /* uleb128 0x1; Offset 1 (-4/-8) */ 524 .byte 0x9e /* DW_CFA_offset Register r30 */ 525 .byte 0x2 /* uleb128 0x2; Offset 2 (-8/-16) */ 526 .byte 0x9d /* DW_CFA_offset Register r29 */ 527 .byte 0x3 /* uleb128 0x3; Offset 3 (-12/-24) */ 528 .byte 0x9c /* DW_CFA_offset Register r28 */ 529 .byte 0x4 /* uleb128 0x4; Offset 4 (-16/-32) */ 530 .byte 0x4 /* DW_CFA_advance_loc4 */ 531 .vbyte 4,LCFI..1-LCFI..0 532 .byte 0xd /* DW_CFA_def_cfa_register */ 533 .byte 0x1c /* uleb128 28; Register r28 */ 534 .align LOG2_PTRSIZE 535LEFDE..1: 536LSFDE..2: 537 .vbyte 4,LEFDE..2-LASFDE..2 /* FDE Length */ 538LASFDE..2: 539 .vbyte 4,LASFDE..2-Lframe..1 /* FDE CIE offset */ 540 .vbyte PTRSIZE,LFB..1-$ /* FDE initial location */ 541 .vbyte PTRSIZE,LFE..1-LFB..1 /* FDE address range */ 542 .byte 0 /* uleb128 0x0; Augmentation size */ 543 .byte 0x4 /* DW_CFA_advance_loc4 */ 544 .vbyte 4,LCFI..2-LFB..1 545 .byte 0x11 /* DW_CFA_def_offset_extended_sf */ 546 .byte LR_REGNO /* uleb128 LR_REGNO; Register LR */ 547 .byte 0x7e /* leb128 -2; Offset -2 (8/16) */ 548 .byte 0x9f /* DW_CFA_offset Register r31 */ 549 .byte 0x1 /* uleb128 0x1; Offset 1 (-4/-8) */ 550 .byte 0x9e /* DW_CFA_offset Register r30 */ 551 .byte 0x2 /* uleb128 0x2; Offset 2 (-8/-16) */ 552 .byte 0x9d /* DW_CFA_offset Register r29 */ 553 .byte 0x3 /* uleb128 0x3; Offset 3 (-12/-24) */ 554 .byte 0x9c /* DW_CFA_offset Register r28 */ 555 .byte 0x4 /* uleb128 0x4; Offset 4 (-16/-32) */ 556 .byte 0x4 /* DW_CFA_advance_loc4 */ 557 .vbyte 4,LCFI..3-LCFI..2 558 .byte 0xd /* DW_CFA_def_cfa_register */ 559 .byte 0x1c /* uleb128 28; Register r28 */ 560 .align LOG2_PTRSIZE 561LEFDE..2: 562 .vbyte 4,0 /* End of FDEs */ 563 564 .csect .text[PR] 565 .ref _GLOBAL__F_libffi_src_powerpc_aix /* Prevents garbage collection by AIX linker */ 566 567