Home | History | Annotate | Download | only in powerpc
      1 /* -----------------------------------------------------------------------
      2    darwin.S - Copyright (c) 2000 John Hornkvist
      3 	      Copyright (c) 2004 Free Software Foundation, Inc.
      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 #if defined(__ppc64__)
     28 #define MODE_CHOICE(x, y) y
     29 #else
     30 #define MODE_CHOICE(x, y) x
     31 #endif
     32 
     33 #define g_long  MODE_CHOICE(long, quad)         /* usage is ".g_long" */
     34 
     35 #define LOG2_GPR_BYTES  MODE_CHOICE(2,3)        /* log2(GPR_BYTES) */
     36 
     37 #define LIBFFI_ASM
     38 #include <fficonfig.h>
     39 #include <ffi.h>
     40 #define JUMPTARGET(name) name
     41 #define L(x) x
     42 .text
     43 	.align 2
     44 .globl _ffi_prep_args
     45 
     46 .text
     47 	.align 2
     48 .globl _ffi_call_DARWIN
     49 .text
     50 	.align 2
     51 _ffi_call_DARWIN:
     52 LFB0:
     53 	mr   	r12,r8	/* We only need r12 until the call,
     54 			   so it doesn't have to be saved.  */
     55 LFB1:
     56 	/* Save the old stack pointer as AP.  */
     57 	mr	r8,r1
     58 LCFI0:
     59 	/* Allocate the stack space we need.  */
     60 	stwux	r1,r1,r4
     61 
     62 	/* Save registers we use.  */
     63 	mflr	r9
     64 
     65 	stw	r28,-16(r8)
     66 	stw	r29,-12(r8)
     67 	stw	r30,-8(r8)
     68 	stw	r31,-4(r8)
     69 
     70 	stw	r9,8(r8)
     71 	stw	r2,20(r1)
     72 LCFI1:
     73 
     74 	/* Save arguments over call.  */
     75 	mr	r31,r5	/* flags,  */
     76 	mr	r30,r6	/* rvalue,  */
     77 	mr	r29,r7	/* function address,  */
     78 	mr	r28,r8	/* our AP.  */
     79 LCFI2:
     80 	/* Call ffi_prep_args.  */
     81 	mr	r4,r1
     82 // ANDROID: these changes were necessary in 2.x; not yet tested in 3.x
     83 //	subi    r1,r1,32 /* Android: adjust stack for parameter / scratch area */
     84 	li	r9,0
     85 
     86 	mtctr	r12 /* r12 holds address of _ffi_prep_args.  */
     87 	bctrl
     88 //	addi    r1,r1,32 /* Android: readjust stack (see subi above) */
     89 	lwz     r2,20(r1)
     90 
     91 	/* Now do the call.
     92 	   Set up cr1 with bits 4-7 of the flags.  */
     93 	mtcrf	0x40,r31
     94 	/* Get the address to call into CTR.  */
     95 	mtctr	r29
     96 	/* Load all those argument registers.
     97 	   We have set up a nice stack frame, just load it into registers.  */
     98 	lwz     r3,20+(1*4)(r1)
     99 	lwz     r4,20+(2*4)(r1)
    100 	lwz     r5,20+(3*4)(r1)
    101 	lwz     r6,20+(4*4)(r1)
    102 	nop
    103 	lwz     r7,20+(5*4)(r1)
    104 	lwz     r8,20+(6*4)(r1)
    105 	lwz     r9,20+(7*4)(r1)
    106 	lwz     r10,20+(8*4)(r1)
    107 
    108 L1:
    109 	/* Load all the FP registers.  */
    110 	bf	6,L2	/* No floats to load.  */
    111 	lfd	f1,-16-(13*8)(r28)
    112 	lfd	f2,-16-(12*8)(r28)
    113 	lfd	f3,-16-(11*8)(r28)
    114 	lfd	f4,-16-(10*8)(r28)
    115 	nop
    116 	lfd	f5,-16-(9*8)(r28)
    117 	lfd	f6,-16-(8*8)(r28)
    118 	lfd	f7,-16-(7*8)(r28)
    119 	lfd	f8,-16-(6*8)(r28)
    120 	nop
    121 	lfd     f9,-16-(5*8)(r28)
    122 	lfd     f10,-16-(4*8)(r28)
    123 	lfd     f11,-16-(3*8)(r28)
    124 	lfd     f12,-16-(2*8)(r28)
    125 	nop
    126 	lfd     f13,-16-(1*8)(r28)
    127 
    128 L2:
    129 	mr	r12,r29	/* Put the target address in r12 as specified.  */
    130 	mtctr  	r12
    131 	nop
    132 	nop
    133 	/* Make the call.  */
    134 	bctrl
    135 
    136 	/* Now, deal with the return value.  */
    137 	mtcrf	0x01,r31
    138 
    139 	bt	30,L(done_return_value)
    140 	bt	29,L(fp_return_value)
    141 	stw	r3,0(r30)
    142 	bf	28,L(done_return_value)
    143 	stw	r4,4(r30)
    144 
    145 	/* Fall through.  */
    146 
    147 L(done_return_value):
    148 	/* Restore the registers we used and return.  */
    149 	lwz	r9,8(r28)
    150 	lwz	r31,-4(r28)
    151 	mtlr	r9
    152 	lwz	r30,-8(r28)
    153 	lwz	r29,-12(r28)
    154 	lwz	r28,-16(r28)
    155 	lwz	r1,0(r1)
    156 	blr
    157 
    158 L(fp_return_value):
    159 	/* Do we have long double to store?  */
    160 	bf	31,L(fd_return_value)
    161 	stfd	f1,0(r30)
    162 	stfd	f2,8(r30)
    163 	b	L(done_return_value)
    164 
    165 L(fd_return_value):
    166 	/* Do we have double to store?  */
    167 	bf	28,L(float_return_value)
    168 	stfd	f1,0(r30)
    169 	b	L(done_return_value)
    170 
    171 L(float_return_value):
    172 	/* We only have a float to store.  */
    173 	stfs	f1,0(r30)
    174 	b	L(done_return_value)
    175 
    176 LFE1:
    177 /* END(_ffi_call_DARWIN)  */
    178 
    179 /* Provide a null definition of _ffi_call_AIX.  */
    180 .text
    181 	.align 2
    182 .globl _ffi_call_AIX
    183 .text
    184 	.align 2
    185 _ffi_call_AIX:
    186 	blr
    187 /* END(_ffi_call_AIX)  */
    188 
    189 .data
    190 .section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms
    191 EH_frame1:
    192 	.set	L$set$0,LECIE1-LSCIE1
    193 	.long	L$set$0	; Length of Common Information Entry
    194 LSCIE1:
    195 	.long	0x0	; CIE Identifier Tag
    196 	.byte	0x1	; CIE Version
    197 	.ascii	"zR\0"	; CIE Augmentation
    198 	.byte	0x1	; uleb128 0x1; CIE Code Alignment Factor
    199 	.byte	0x7c	; sleb128 -4; CIE Data Alignment Factor
    200 	.byte	0x41	; CIE RA Column
    201 	.byte	0x1	; uleb128 0x1; Augmentation size
    202 	.byte	0x90	; FDE Encoding (indirect pcrel)
    203 	.byte	0xc	; DW_CFA_def_cfa
    204 	.byte	0x1	; uleb128 0x1
    205 	.byte	0x0	; uleb128 0x0
    206 	.align	LOG2_GPR_BYTES
    207 LECIE1:
    208 .globl _ffi_call_DARWIN.eh
    209 _ffi_call_DARWIN.eh:
    210 LSFDE1:
    211 	.set	L$set$1,LEFDE1-LASFDE1
    212 	.long	L$set$1	; FDE Length
    213 LASFDE1:
    214 	.long	LASFDE1-EH_frame1 ; FDE CIE offset
    215 	.g_long	LLFB0$non_lazy_ptr-.	; FDE initial location
    216 	.set	L$set$3,LFE1-LFB0
    217 	.g_long	L$set$3	; FDE address range
    218 	.byte   0x0     ; uleb128 0x0; Augmentation size
    219 	.byte	0x4	; DW_CFA_advance_loc4
    220 	.set	L$set$4,LCFI0-LFB1
    221 	.long	L$set$4
    222 	.byte	0xd	; DW_CFA_def_cfa_register
    223 	.byte	0x08	; uleb128 0x08
    224 	.byte	0x4	; DW_CFA_advance_loc4
    225 	.set	L$set$5,LCFI1-LCFI0
    226 	.long	L$set$5
    227 	.byte   0x11    ; DW_CFA_offset_extended_sf
    228 	.byte	0x41	; uleb128 0x41
    229 	.byte   0x7e    ; sleb128 -2
    230 	.byte	0x9f	; DW_CFA_offset, column 0x1f
    231 	.byte	0x1	; uleb128 0x1
    232 	.byte	0x9e	; DW_CFA_offset, column 0x1e
    233 	.byte	0x2	; uleb128 0x2
    234 	.byte	0x9d	; DW_CFA_offset, column 0x1d
    235 	.byte	0x3	; uleb128 0x3
    236 	.byte	0x9c	; DW_CFA_offset, column 0x1c
    237 	.byte	0x4	; uleb128 0x4
    238 	.byte	0x4	; DW_CFA_advance_loc4
    239 	.set	L$set$6,LCFI2-LCFI1
    240 	.long	L$set$6
    241 	.byte	0xd	; DW_CFA_def_cfa_register
    242 	.byte	0x1c	; uleb128 0x1c
    243 	.align LOG2_GPR_BYTES
    244 LEFDE1:
    245 .data
    246 	.align LOG2_GPR_BYTES
    247 LLFB0$non_lazy_ptr:
    248 	.g_long LFB0
    249