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] 104 ffi_call_AIX: 105 #ifdef __64BIT__ 106 .llong .ffi_call_AIX, TOC[tc0], 0 107 .csect .text[PR] 108 .ffi_call_AIX: 109 /* Save registers we use. */ 110 mflr r0 111 112 std r28,-32(r1) 113 std r29,-24(r1) 114 std r30,-16(r1) 115 std r31, -8(r1) 116 117 std r0, 16(r1) 118 mr r28, r1 /* our AP. */ 119 stdux r1, r1, r4 120 121 /* Save arguments over call... */ 122 mr r31, r5 /* flags, */ 123 mr r30, r6 /* rvalue, */ 124 mr r29, r7 /* function address. */ 125 std r2, 40(r1) 126 127 /* Call ffi_prep_args. */ 128 mr r4, r1 129 bl .ffi_prep_args 130 nop 131 132 /* Now do the call. */ 133 ld r0, 0(r29) 134 ld r2, 8(r29) 135 ld r11, 16(r29) 136 /* Set up cr1 with bits 4-7 of the flags. */ 137 mtcrf 0x40, r31 138 mtctr r0 139 /* Load all those argument registers. */ 140 /* We have set up a nice stack frame, just load it into registers. */ 141 ld r3, 40+(1*8)(r1) 142 ld r4, 40+(2*8)(r1) 143 ld r5, 40+(3*8)(r1) 144 ld r6, 40+(4*8)(r1) 145 nop 146 ld r7, 40+(5*8)(r1) 147 ld r8, 40+(6*8)(r1) 148 ld r9, 40+(7*8)(r1) 149 ld r10,40+(8*8)(r1) 150 151 L1: 152 /* Load all the FP registers. */ 153 bf 6,L2 /* 2f + 0x18 */ 154 lfd f1,-32-(13*8)(r28) 155 lfd f2,-32-(12*8)(r28) 156 lfd f3,-32-(11*8)(r28) 157 lfd f4,-32-(10*8)(r28) 158 nop 159 lfd f5,-32-(9*8)(r28) 160 lfd f6,-32-(8*8)(r28) 161 lfd f7,-32-(7*8)(r28) 162 lfd f8,-32-(6*8)(r28) 163 nop 164 lfd f9,-32-(5*8)(r28) 165 lfd f10,-32-(4*8)(r28) 166 lfd f11,-32-(3*8)(r28) 167 lfd f12,-32-(2*8)(r28) 168 nop 169 lfd f13,-32-(1*8)(r28) 170 171 L2: 172 /* Make the call. */ 173 bctrl 174 ld r2, 40(r1) 175 176 /* Now, deal with the return value. */ 177 mtcrf 0x01, r31 178 179 bt 30, L(done_return_value) 180 bt 29, L(fp_return_value) 181 std r3, 0(r30) 182 183 /* Fall through... */ 184 185 L(done_return_value): 186 /* Restore the registers we used and return. */ 187 mr r1, r28 188 ld r0, 16(r28) 189 ld r28, -32(r1) 190 mtlr r0 191 ld r29, -24(r1) 192 ld r30, -16(r1) 193 ld r31, -8(r1) 194 blr 195 196 L(fp_return_value): 197 bf 28, L(float_return_value) 198 stfd f1, 0(r30) 199 bf 31, L(done_return_value) 200 stfd f2, 8(r30) 201 b L(done_return_value) 202 L(float_return_value): 203 stfs f1, 0(r30) 204 b L(done_return_value) 205 206 #else /* ! __64BIT__ */ 207 208 .long .ffi_call_AIX, TOC[tc0], 0 209 .csect .text[PR] 210 .ffi_call_AIX: 211 /* Save registers we use. */ 212 mflr r0 213 214 stw r28,-16(r1) 215 stw r29,-12(r1) 216 stw r30, -8(r1) 217 stw r31, -4(r1) 218 219 stw r0, 8(r1) 220 mr r28, r1 /* out AP. */ 221 stwux r1, r1, r4 222 223 /* Save arguments over call... */ 224 mr r31, r5 /* flags, */ 225 mr r30, r6 /* rvalue, */ 226 mr r29, r7 /* function address, */ 227 stw r2, 20(r1) 228 229 /* Call ffi_prep_args. */ 230 mr r4, r1 231 bl .ffi_prep_args 232 nop 233 234 /* Now do the call. */ 235 lwz r0, 0(r29) 236 lwz r2, 4(r29) 237 lwz r11, 8(r29) 238 /* Set up cr1 with bits 4-7 of the flags. */ 239 mtcrf 0x40, r31 240 mtctr r0 241 /* Load all those argument registers. */ 242 /* We have set up a nice stack frame, just load it into registers. */ 243 lwz r3, 20+(1*4)(r1) 244 lwz r4, 20+(2*4)(r1) 245 lwz r5, 20+(3*4)(r1) 246 lwz r6, 20+(4*4)(r1) 247 nop 248 lwz r7, 20+(5*4)(r1) 249 lwz r8, 20+(6*4)(r1) 250 lwz r9, 20+(7*4)(r1) 251 lwz r10,20+(8*4)(r1) 252 253 L1: 254 /* Load all the FP registers. */ 255 bf 6,L2 /* 2f + 0x18 */ 256 lfd f1,-16-(13*8)(r28) 257 lfd f2,-16-(12*8)(r28) 258 lfd f3,-16-(11*8)(r28) 259 lfd f4,-16-(10*8)(r28) 260 nop 261 lfd f5,-16-(9*8)(r28) 262 lfd f6,-16-(8*8)(r28) 263 lfd f7,-16-(7*8)(r28) 264 lfd f8,-16-(6*8)(r28) 265 nop 266 lfd f9,-16-(5*8)(r28) 267 lfd f10,-16-(4*8)(r28) 268 lfd f11,-16-(3*8)(r28) 269 lfd f12,-16-(2*8)(r28) 270 nop 271 lfd f13,-16-(1*8)(r28) 272 273 L2: 274 /* Make the call. */ 275 bctrl 276 lwz r2, 20(r1) 277 278 /* Now, deal with the return value. */ 279 mtcrf 0x01, r31 280 281 bt 30, L(done_return_value) 282 bt 29, L(fp_return_value) 283 stw r3, 0(r30) 284 bf 28, L(done_return_value) 285 stw r4, 4(r30) 286 287 /* Fall through... */ 288 289 L(done_return_value): 290 /* Restore the registers we used and return. */ 291 mr r1, r28 292 lwz r0, 8(r28) 293 lwz r28,-16(r1) 294 mtlr r0 295 lwz r29,-12(r1) 296 lwz r30, -8(r1) 297 lwz r31, -4(r1) 298 blr 299 300 L(fp_return_value): 301 bf 28, L(float_return_value) 302 stfd f1, 0(r30) 303 b L(done_return_value) 304 L(float_return_value): 305 stfs f1, 0(r30) 306 b L(done_return_value) 307 #endif 308 .long 0 309 .byte 0,0,0,1,128,4,0,0 310 /* END(ffi_call_AIX) */ 311 312 .csect .text[PR] 313 .align 2 314 .globl ffi_call_DARWIN 315 .globl .ffi_call_DARWIN 316 .csect ffi_call_DARWIN[DS] 317 ffi_call_DARWIN: 318 #ifdef __64BIT__ 319 .llong .ffi_call_DARWIN, TOC[tc0], 0 320 #else 321 .long .ffi_call_DARWIN, TOC[tc0], 0 322 #endif 323 .csect .text[PR] 324 .ffi_call_DARWIN: 325 blr 326 .long 0 327 .byte 0,0,0,0,0,0,0,0 328 /* END(ffi_call_DARWIN) */ 329