Home | History | Annotate | Download | only in powerpc
      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