Home | History | Annotate | Download | only in powerpc
      1 /* -----------------------------------------------------------------------
      2    sysv.h - Copyright (c) 2003 Jakub Jelinek <jakub (at) redhat.com>
      3 	    Copyright (c) 2008 Red Hat, Inc.
      4 
      5    PowerPC64 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,
     19    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     20    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
     21    NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
     22    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
     23    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     24    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
     25    DEALINGS IN THE SOFTWARE.
     26    ----------------------------------------------------------------------- */
     27 
     28 #define LIBFFI_ASM
     29 #include <fficonfig.h>
     30 #include <ffi.h>
     31 
     32 #ifdef POWERPC64
     33 	.hidden	ffi_call_LINUX64
     34 	.globl	ffi_call_LINUX64
     35 # if _CALL_ELF == 2
     36 	.text
     37 ffi_call_LINUX64:
     38 	addis	%r2, %r12, .TOC.-ffi_call_LINUX64@ha
     39 	addi	%r2, %r2, .TOC.-ffi_call_LINUX64@l
     40 	.localentry ffi_call_LINUX64, . - ffi_call_LINUX64
     41 # else
     42 	.section	".opd","aw"
     43 	.align	3
     44 ffi_call_LINUX64:
     45 #  ifdef _CALL_LINUX
     46 	.quad	.L.ffi_call_LINUX64,.TOC.@tocbase,0
     47 	.type	ffi_call_LINUX64,@function
     48 	.text
     49 .L.ffi_call_LINUX64:
     50 #  else
     51 	.hidden	.ffi_call_LINUX64
     52 	.globl	.ffi_call_LINUX64
     53 	.quad	.ffi_call_LINUX64,.TOC.@tocbase,0
     54 	.size	ffi_call_LINUX64,24
     55 	.type	.ffi_call_LINUX64,@function
     56 	.text
     57 .ffi_call_LINUX64:
     58 #  endif
     59 # endif
     60 .LFB1:
     61 	mflr	%r0
     62 	std	%r28, -32(%r1)
     63 	std	%r29, -24(%r1)
     64 	std	%r30, -16(%r1)
     65 	std	%r31, -8(%r1)
     66 	std	%r0, 16(%r1)
     67 
     68 	mr	%r28, %r1	/* our AP.  */
     69 .LCFI0:
     70 	stdux	%r1, %r1, %r4
     71 	mr	%r31, %r5	/* flags, */
     72 	mr	%r30, %r6	/* rvalue, */
     73 	mr	%r29, %r7	/* function address.  */
     74 /* Save toc pointer, not for the ffi_prep_args64 call, but for the later
     75    bctrl function call.  */
     76 # if _CALL_ELF == 2
     77 	std	%r2, 24(%r1)
     78 # else
     79 	std	%r2, 40(%r1)
     80 # endif
     81 
     82 	/* Call ffi_prep_args64.  */
     83 	mr	%r4, %r1
     84 # if defined _CALL_LINUX || _CALL_ELF == 2
     85 	bl	ffi_prep_args64
     86 # else
     87 	bl	.ffi_prep_args64
     88 # endif
     89 
     90 # if _CALL_ELF == 2
     91 	mr	%r12, %r29
     92 # else
     93 	ld	%r12, 0(%r29)
     94 	ld	%r2, 8(%r29)
     95 	ld	%r11, 16(%r29)
     96 # endif
     97 	/* Now do the call.  */
     98 	/* Set up cr1 with bits 4-7 of the flags.  */
     99 	mtcrf	0x40, %r31
    100 
    101 	/* Get the address to call into CTR.  */
    102 	mtctr	%r12
    103 	/* Load all those argument registers.  */
    104 	ld	%r3, -32-(8*8)(%r28)
    105 	ld	%r4, -32-(7*8)(%r28)
    106 	ld	%r5, -32-(6*8)(%r28)
    107 	ld	%r6, -32-(5*8)(%r28)
    108 	bf-	5, 1f
    109 	ld	%r7, -32-(4*8)(%r28)
    110 	ld	%r8, -32-(3*8)(%r28)
    111 	ld	%r9, -32-(2*8)(%r28)
    112 	ld	%r10, -32-(1*8)(%r28)
    113 1:
    114 
    115 	/* Load all the FP registers.  */
    116 	bf-	6, 2f
    117 	lfd	%f1, -32-(21*8)(%r28)
    118 	lfd	%f2, -32-(20*8)(%r28)
    119 	lfd	%f3, -32-(19*8)(%r28)
    120 	lfd	%f4, -32-(18*8)(%r28)
    121 	lfd	%f5, -32-(17*8)(%r28)
    122 	lfd	%f6, -32-(16*8)(%r28)
    123 	lfd	%f7, -32-(15*8)(%r28)
    124 	lfd	%f8, -32-(14*8)(%r28)
    125 	lfd	%f9, -32-(13*8)(%r28)
    126 	lfd	%f10, -32-(12*8)(%r28)
    127 	lfd	%f11, -32-(11*8)(%r28)
    128 	lfd	%f12, -32-(10*8)(%r28)
    129 	lfd	%f13, -32-(9*8)(%r28)
    130 2:
    131 
    132 	/* Make the call.  */
    133 	bctrl
    134 
    135 	/* This must follow the call immediately, the unwinder
    136 	   uses this to find out if r2 has been saved or not.  */
    137 # if _CALL_ELF == 2
    138 	ld	%r2, 24(%r1)
    139 # else
    140 	ld	%r2, 40(%r1)
    141 # endif
    142 
    143 	/* Now, deal with the return value.  */
    144 	mtcrf	0x01, %r31
    145 	bt	31, .Lstruct_return_value
    146 	bt	30, .Ldone_return_value
    147 	bt	29, .Lfp_return_value
    148 	std	%r3, 0(%r30)
    149 	/* Fall through...  */
    150 
    151 .Ldone_return_value:
    152 	/* Restore the registers we used and return.  */
    153 	mr	%r1, %r28
    154 	ld	%r0, 16(%r28)
    155 	ld	%r28, -32(%r28)
    156 	mtlr	%r0
    157 	ld	%r29, -24(%r1)
    158 	ld	%r30, -16(%r1)
    159 	ld	%r31, -8(%r1)
    160 	blr
    161 
    162 .Lfp_return_value:
    163 	bf	28, .Lfloat_return_value
    164 	stfd	%f1, 0(%r30)
    165 	mtcrf	0x02, %r31 /* cr6  */
    166 	bf	27, .Ldone_return_value
    167 	stfd	%f2, 8(%r30)
    168 	b	.Ldone_return_value
    169 .Lfloat_return_value:
    170 	stfs	%f1, 0(%r30)
    171 	b	.Ldone_return_value
    172 
    173 .Lstruct_return_value:
    174 	bf	29, .Lsmall_struct
    175 	bf	28, .Lfloat_homog_return_value
    176 	stfd	%f1, 0(%r30)
    177 	stfd	%f2, 8(%r30)
    178 	stfd	%f3, 16(%r30)
    179 	stfd	%f4, 24(%r30)
    180 	stfd	%f5, 32(%r30)
    181 	stfd	%f6, 40(%r30)
    182 	stfd	%f7, 48(%r30)
    183 	stfd	%f8, 56(%r30)
    184 	b	.Ldone_return_value
    185 
    186 .Lfloat_homog_return_value:
    187 	stfs	%f1, 0(%r30)
    188 	stfs	%f2, 4(%r30)
    189 	stfs	%f3, 8(%r30)
    190 	stfs	%f4, 12(%r30)
    191 	stfs	%f5, 16(%r30)
    192 	stfs	%f6, 20(%r30)
    193 	stfs	%f7, 24(%r30)
    194 	stfs	%f8, 28(%r30)
    195 	b	.Ldone_return_value
    196 
    197 .Lsmall_struct:
    198 	std	%r3, 0(%r30)
    199 	std	%r4, 8(%r30)
    200 	b	.Ldone_return_value
    201 
    202 .LFE1:
    203 	.long	0
    204 	.byte	0,12,0,1,128,4,0,0
    205 # if _CALL_ELF == 2
    206 	.size	ffi_call_LINUX64,.-ffi_call_LINUX64
    207 # else
    208 #  ifdef _CALL_LINUX
    209 	.size	ffi_call_LINUX64,.-.L.ffi_call_LINUX64
    210 #  else
    211 	.size	.ffi_call_LINUX64,.-.ffi_call_LINUX64
    212 #  endif
    213 # endif
    214 
    215 	.section	.eh_frame,EH_FRAME_FLAGS,@progbits
    216 .Lframe1:
    217 	.4byte	.LECIE1-.LSCIE1	 # Length of Common Information Entry
    218 .LSCIE1:
    219 	.4byte	0x0	 # CIE Identifier Tag
    220 	.byte	0x1	 # CIE Version
    221 	.ascii "zR\0"	 # CIE Augmentation
    222 	.uleb128 0x1	 # CIE Code Alignment Factor
    223 	.sleb128 -8	 # CIE Data Alignment Factor
    224 	.byte	0x41	 # CIE RA Column
    225 	.uleb128 0x1	 # Augmentation size
    226 	.byte	0x14	 # FDE Encoding (pcrel udata8)
    227 	.byte	0xc	 # DW_CFA_def_cfa
    228 	.uleb128 0x1
    229 	.uleb128 0x0
    230 	.align 3
    231 .LECIE1:
    232 .LSFDE1:
    233 	.4byte	.LEFDE1-.LASFDE1	 # FDE Length
    234 .LASFDE1:
    235 	.4byte	.LASFDE1-.Lframe1	 # FDE CIE offset
    236 	.8byte	.LFB1-.	 # FDE initial location
    237 	.8byte	.LFE1-.LFB1	 # FDE address range
    238 	.uleb128 0x0	 # Augmentation size
    239 	.byte	0x2	 # DW_CFA_advance_loc1
    240 	.byte	.LCFI0-.LFB1
    241 	.byte	0xd	 # DW_CFA_def_cfa_register
    242 	.uleb128 0x1c
    243 	.byte	0x11	 # DW_CFA_offset_extended_sf
    244 	.uleb128 0x41
    245 	.sleb128 -2
    246 	.byte	0x9f	 # DW_CFA_offset, column 0x1f
    247 	.uleb128 0x1
    248 	.byte	0x9e	 # DW_CFA_offset, column 0x1e
    249 	.uleb128 0x2
    250 	.byte	0x9d	 # DW_CFA_offset, column 0x1d
    251 	.uleb128 0x3
    252 	.byte	0x9c	 # DW_CFA_offset, column 0x1c
    253 	.uleb128 0x4
    254 	.align 3
    255 .LEFDE1:
    256 
    257 #endif
    258 
    259 #if (defined __ELF__ && defined __linux__) || _CALL_ELF == 2
    260 	.section	.note.GNU-stack,"",@progbits
    261 #endif
    262