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 #define LIBFFI_ASM
     28 #include <fficonfig.h>
     29 #include <ffi.h>
     30 
     31 	.file	"linux64_closure.S"
     32 
     33 #ifdef __powerpc64__
     34 	FFI_HIDDEN (ffi_closure_LINUX64)
     35 	FFI_HIDDEN (.ffi_closure_LINUX64)
     36 	.globl  ffi_closure_LINUX64, .ffi_closure_LINUX64
     37 	.section        ".opd","aw"
     38 	.align  3
     39 ffi_closure_LINUX64:
     40 	.quad   .ffi_closure_LINUX64,.TOC.@tocbase,0
     41 	.size   ffi_closure_LINUX64,24
     42 	.type   .ffi_closure_LINUX64,@function
     43 	.text
     44 .ffi_closure_LINUX64:
     45 .LFB1:
     46 	# save general regs into parm save area
     47 	std	%r3, 48(%r1)
     48 	std	%r4, 56(%r1)
     49 	std	%r5, 64(%r1)
     50 	std	%r6, 72(%r1)
     51 	mflr	%r0
     52 
     53 	std	%r7, 80(%r1)
     54 	std	%r8, 88(%r1)
     55 	std	%r9, 96(%r1)
     56 	std	%r10, 104(%r1)
     57 	std	%r0, 16(%r1)
     58 
     59 	# mandatory 48 bytes special reg save area + 64 bytes parm save area
     60 	# + 16 bytes retval area + 13*8 bytes fpr save area + round to 16
     61 	stdu	%r1, -240(%r1)
     62 .LCFI0:
     63 
     64 	# next save fpr 1 to fpr 13
     65 	stfd  %f1, 128+(0*8)(%r1)
     66 	stfd  %f2, 128+(1*8)(%r1)
     67 	stfd  %f3, 128+(2*8)(%r1)
     68 	stfd  %f4, 128+(3*8)(%r1)
     69 	stfd  %f5, 128+(4*8)(%r1)
     70 	stfd  %f6, 128+(5*8)(%r1)
     71 	stfd  %f7, 128+(6*8)(%r1)
     72 	stfd  %f8, 128+(7*8)(%r1)
     73 	stfd  %f9, 128+(8*8)(%r1)
     74 	stfd  %f10, 128+(9*8)(%r1)
     75 	stfd  %f11, 128+(10*8)(%r1)
     76 	stfd  %f12, 128+(11*8)(%r1)
     77 	stfd  %f13, 128+(12*8)(%r1)
     78 
     79 	# set up registers for the routine that actually does the work
     80 	# get the context pointer from the trampoline
     81 	mr %r3, %r11
     82 
     83 	# now load up the pointer to the result storage
     84 	addi %r4, %r1, 112
     85 
     86 	# now load up the pointer to the parameter save area
     87 	# in the previous frame
     88 	addi %r5, %r1, 240 + 48
     89 
     90 	# now load up the pointer to the saved fpr registers */
     91 	addi %r6, %r1, 128
     92 
     93 	# make the call
     94 	bl .ffi_closure_helper_LINUX64
     95 .Lret:
     96 
     97 	# now r3 contains the return type
     98 	# so use it to look up in a table
     99 	# so we know how to deal with each type
    100 
    101 	# look up the proper starting point in table
    102 	# by using return type as offset
    103 	mflr %r4		# move address of .Lret to r4
    104 	sldi %r3, %r3, 4	# now multiply return type by 16
    105 	addi %r4, %r4, .Lret_type0 - .Lret
    106 	ld %r0, 240+16(%r1)
    107 	add %r3, %r3, %r4	# add contents of table to table address
    108 	mtctr %r3
    109 	bctr			# jump to it
    110 
    111 # Each of the ret_typeX code fragments has to be exactly 16 bytes long
    112 # (4 instructions). For cache effectiveness we align to a 16 byte boundary
    113 # first.
    114 	.align 4
    115 
    116 .Lret_type0:
    117 # case FFI_TYPE_VOID
    118 	mtlr %r0
    119 	addi %r1, %r1, 240
    120 	blr
    121 	nop
    122 # case FFI_TYPE_INT
    123 	lwa %r3, 112+4(%r1)
    124 	mtlr %r0
    125 	addi %r1, %r1, 240
    126 	blr
    127 # case FFI_TYPE_FLOAT
    128 	lfs %f1, 112+0(%r1)
    129 	mtlr %r0
    130 	addi %r1, %r1, 240
    131 	blr
    132 # case FFI_TYPE_DOUBLE
    133 	lfd %f1, 112+0(%r1)
    134 	mtlr %r0
    135 	addi %r1, %r1, 240
    136 	blr
    137 # case FFI_TYPE_LONGDOUBLE
    138 	lfd %f1, 112+0(%r1)
    139 	mtlr %r0
    140 	lfd %f2, 112+8(%r1)
    141 	b .Lfinish
    142 # case FFI_TYPE_UINT8
    143 	lbz %r3, 112+7(%r1)
    144 	mtlr %r0
    145 	addi %r1, %r1, 240
    146 	blr
    147 # case FFI_TYPE_SINT8
    148 	lbz %r3, 112+7(%r1)
    149 	extsb %r3,%r3
    150 	mtlr %r0
    151 	b .Lfinish
    152 # case FFI_TYPE_UINT16
    153 	lhz %r3, 112+6(%r1)
    154 	mtlr %r0
    155 .Lfinish:
    156 	addi %r1, %r1, 240
    157 	blr
    158 # case FFI_TYPE_SINT16
    159 	lha %r3, 112+6(%r1)
    160 	mtlr %r0
    161 	addi %r1, %r1, 240
    162 	blr
    163 # case FFI_TYPE_UINT32
    164 	lwz %r3, 112+4(%r1)
    165 	mtlr %r0
    166 	addi %r1, %r1, 240
    167 	blr
    168 # case FFI_TYPE_SINT32
    169 	lwa %r3, 112+4(%r1)
    170 	mtlr %r0
    171 	addi %r1, %r1, 240
    172 	blr
    173 # case FFI_TYPE_UINT64
    174 	ld %r3, 112+0(%r1)
    175 	mtlr %r0
    176 	addi %r1, %r1, 240
    177 	blr
    178 # case FFI_TYPE_SINT64
    179 	ld %r3, 112+0(%r1)
    180 	mtlr %r0
    181 	addi %r1, %r1, 240
    182 	blr
    183 # case FFI_TYPE_STRUCT
    184 	mtlr %r0
    185 	addi %r1, %r1, 240
    186 	blr
    187 	nop
    188 # case FFI_TYPE_POINTER
    189 	ld %r3, 112+0(%r1)
    190 	mtlr %r0
    191 	addi %r1, %r1, 240
    192 	blr
    193 # esac
    194 .LFE1:
    195 	.long	0
    196 	.byte	0,12,0,1,128,0,0,0
    197 	.size	.ffi_closure_LINUX64,.-.ffi_closure_LINUX64
    198 
    199 	.section	.eh_frame,EH_FRAME_FLAGS,@progbits
    200 .Lframe1:
    201 	.4byte	.LECIE1-.LSCIE1	 # Length of Common Information Entry
    202 .LSCIE1:
    203 	.4byte	0x0	 # CIE Identifier Tag
    204 	.byte	0x1	 # CIE Version
    205 	.ascii "zR\0"	 # CIE Augmentation
    206 	.uleb128 0x1	 # CIE Code Alignment Factor
    207 	.sleb128 -8	 # CIE Data Alignment Factor
    208 	.byte	0x41	 # CIE RA Column
    209 	.uleb128 0x1	 # Augmentation size
    210 	.byte	0x14	 # FDE Encoding (pcrel udata8)
    211 	.byte	0xc	 # DW_CFA_def_cfa
    212 	.uleb128 0x1
    213 	.uleb128 0x0
    214 	.align 3
    215 .LECIE1:
    216 .LSFDE1:
    217 	.4byte	.LEFDE1-.LASFDE1	 # FDE Length
    218 .LASFDE1:
    219 	.4byte	.LASFDE1-.Lframe1	 # FDE CIE offset
    220 	.8byte	.LFB1-.	 # FDE initial location
    221 	.8byte	.LFE1-.LFB1	 # FDE address range
    222 	.uleb128 0x0	 # Augmentation size
    223 	.byte	0x2	 # DW_CFA_advance_loc1
    224 	.byte	.LCFI0-.LFB1
    225 	.byte	0xe	 # DW_CFA_def_cfa_offset
    226 	.uleb128 240
    227 	.byte	0x11	 # DW_CFA_offset_extended_sf
    228 	.uleb128 0x41
    229 	.sleb128 -2
    230 	.align 3
    231 .LEFDE1:
    232 #endif
    233 
    234 #if defined __ELF__ && defined __linux__
    235 	.section	.note.GNU-stack,"",@progbits
    236 #endif
    237