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 	.globl  ffi_closure_LINUX64
     36 # if _CALL_ELF == 2
     37 	.text
     38 ffi_closure_LINUX64:
     39 	addis	%r2, %r12, .TOC.-ffi_closure_LINUX64@ha
     40 	addi	%r2, %r2, .TOC.-ffi_closure_LINUX64@l
     41 	.localentry ffi_closure_LINUX64, . - ffi_closure_LINUX64
     42 # else
     43 	.section        ".opd","aw"
     44 	.align  3
     45 ffi_closure_LINUX64:
     46 #  ifdef _CALL_LINUX
     47 	.quad   .L.ffi_closure_LINUX64,.TOC.@tocbase,0
     48 	.type   ffi_closure_LINUX64,@function
     49 	.text
     50 .L.ffi_closure_LINUX64:
     51 #  else
     52 	FFI_HIDDEN (.ffi_closure_LINUX64)
     53 	.globl  .ffi_closure_LINUX64
     54 	.quad   .ffi_closure_LINUX64,.TOC.@tocbase,0
     55 	.size   ffi_closure_LINUX64,24
     56 	.type   .ffi_closure_LINUX64,@function
     57 	.text
     58 .ffi_closure_LINUX64:
     59 #  endif
     60 # endif
     61 
     62 # if _CALL_ELF == 2
     63 #  32 byte special reg save area + 64 byte parm save area
     64 #  + 64 byte retval area + 13*8 fpr save area + round to 16
     65 #  define STACKFRAME 272
     66 #  define PARMSAVE 32
     67 #  define RETVAL PARMSAVE+64
     68 # else
     69 #  48 bytes special reg save area + 64 bytes parm save area
     70 #  + 16 bytes retval area + 13*8 bytes fpr save area + round to 16
     71 #  define STACKFRAME 240
     72 #  define PARMSAVE 48
     73 #  define RETVAL PARMSAVE+64
     74 # endif
     75 
     76 .LFB1:
     77 # if _CALL_ELF == 2
     78 	ld	%r12, FFI_TRAMPOLINE_SIZE(%r11)		# closure->cif
     79 	mflr	%r0
     80 	lwz	%r12, 28(%r12)				# cif->flags
     81 	mtcrf	0x40, %r12
     82 	addi	%r12, %r1, PARMSAVE
     83 	bt	7, .Lparmsave
     84 	# Our caller has not allocated a parameter save area.
     85 	# We need to allocate one here and use it to pass gprs to
     86 	# ffi_closure_helper_LINUX64.
     87 	addi	%r12, %r1, -STACKFRAME+PARMSAVE
     88 .Lparmsave:
     89 	std	%r0, 16(%r1)
     90 	# Save general regs into parm save area
     91 	std	%r3, 0(%r12)
     92 	std	%r4, 8(%r12)
     93 	std	%r5, 16(%r12)
     94 	std	%r6, 24(%r12)
     95 	std	%r7, 32(%r12)
     96 	std	%r8, 40(%r12)
     97 	std	%r9, 48(%r12)
     98 	std	%r10, 56(%r12)
     99 
    100 	# load up the pointer to the parm save area
    101 	mr	%r5, %r12
    102 # else
    103 	# copy r2 to r11 and load TOC into r2
    104 	mr	%r11, %r2
    105 	ld	%r2, 16(%r11)
    106 
    107 	mflr	%r0
    108 	# Save general regs into parm save area
    109 	# This is the parameter save area set up by our caller.
    110 	std	%r3, PARMSAVE+0(%r1)
    111 	std	%r4, PARMSAVE+8(%r1)
    112 	std	%r5, PARMSAVE+16(%r1)
    113 	std	%r6, PARMSAVE+24(%r1)
    114 	std	%r7, PARMSAVE+32(%r1)
    115 	std	%r8, PARMSAVE+40(%r1)
    116 	std	%r9, PARMSAVE+48(%r1)
    117 	std	%r10, PARMSAVE+56(%r1)
    118 
    119 	std	%r0, 16(%r1)
    120 
    121 	# load up the pointer to the parm save area
    122 	addi	%r5, %r1, PARMSAVE
    123 # endif
    124 
    125 	# next save fpr 1 to fpr 13
    126 	stfd	%f1, -104+(0*8)(%r1)
    127 	stfd	%f2, -104+(1*8)(%r1)
    128 	stfd	%f3, -104+(2*8)(%r1)
    129 	stfd	%f4, -104+(3*8)(%r1)
    130 	stfd	%f5, -104+(4*8)(%r1)
    131 	stfd	%f6, -104+(5*8)(%r1)
    132 	stfd	%f7, -104+(6*8)(%r1)
    133 	stfd	%f8, -104+(7*8)(%r1)
    134 	stfd	%f9, -104+(8*8)(%r1)
    135 	stfd	%f10, -104+(9*8)(%r1)
    136 	stfd	%f11, -104+(10*8)(%r1)
    137 	stfd	%f12, -104+(11*8)(%r1)
    138 	stfd	%f13, -104+(12*8)(%r1)
    139 
    140 	# load up the pointer to the saved fpr registers */
    141 	addi	%r6, %r1, -104
    142 
    143 	# load up the pointer to the result storage
    144 	addi	%r4, %r1, -STACKFRAME+RETVAL
    145 
    146 	stdu	%r1, -STACKFRAME(%r1)
    147 .LCFI0:
    148 
    149 	# get the context pointer from the trampoline
    150 	mr	%r3, %r11
    151 
    152 	# make the call
    153 # if defined _CALL_LINUX || _CALL_ELF == 2
    154 	bl ffi_closure_helper_LINUX64
    155 # else
    156 	bl .ffi_closure_helper_LINUX64
    157 # endif
    158 .Lret:
    159 
    160 	# now r3 contains the return type
    161 	# so use it to look up in a table
    162 	# so we know how to deal with each type
    163 
    164 	# look up the proper starting point in table
    165 	# by using return type as offset
    166 	ld %r0, STACKFRAME+16(%r1)
    167 	cmpldi %r3, FFI_V2_TYPE_SMALL_STRUCT
    168 	bge .Lsmall
    169 	mflr %r4		# move address of .Lret to r4
    170 	sldi %r3, %r3, 4	# now multiply return type by 16
    171 	addi %r4, %r4, .Lret_type0 - .Lret
    172 	add %r3, %r3, %r4	# add contents of table to table address
    173 	mtctr %r3
    174 	bctr			# jump to it
    175 
    176 # Each of the ret_typeX code fragments has to be exactly 16 bytes long
    177 # (4 instructions). For cache effectiveness we align to a 16 byte boundary
    178 # first.
    179 	.align 4
    180 
    181 .Lret_type0:
    182 # case FFI_TYPE_VOID
    183 	mtlr %r0
    184 	addi %r1, %r1, STACKFRAME
    185 	blr
    186 	nop
    187 # case FFI_TYPE_INT
    188 # ifdef __LITTLE_ENDIAN__
    189 	lwa %r3, RETVAL+0(%r1)
    190 # else
    191 	lwa %r3, RETVAL+4(%r1)
    192 # endif
    193 	mtlr %r0
    194 	addi %r1, %r1, STACKFRAME
    195 	blr
    196 # case FFI_TYPE_FLOAT
    197 	lfs %f1, RETVAL+0(%r1)
    198 	mtlr %r0
    199 	addi %r1, %r1, STACKFRAME
    200 	blr
    201 # case FFI_TYPE_DOUBLE
    202 	lfd %f1, RETVAL+0(%r1)
    203 	mtlr %r0
    204 	addi %r1, %r1, STACKFRAME
    205 	blr
    206 # case FFI_TYPE_LONGDOUBLE
    207 	lfd %f1, RETVAL+0(%r1)
    208 	mtlr %r0
    209 	lfd %f2, RETVAL+8(%r1)
    210 	b .Lfinish
    211 # case FFI_TYPE_UINT8
    212 # ifdef __LITTLE_ENDIAN__
    213 	lbz %r3, RETVAL+0(%r1)
    214 # else
    215 	lbz %r3, RETVAL+7(%r1)
    216 # endif
    217 	mtlr %r0
    218 	addi %r1, %r1, STACKFRAME
    219 	blr
    220 # case FFI_TYPE_SINT8
    221 # ifdef __LITTLE_ENDIAN__
    222 	lbz %r3, RETVAL+0(%r1)
    223 # else
    224 	lbz %r3, RETVAL+7(%r1)
    225 # endif
    226 	extsb %r3,%r3
    227 	mtlr %r0
    228 	b .Lfinish
    229 # case FFI_TYPE_UINT16
    230 # ifdef __LITTLE_ENDIAN__
    231 	lhz %r3, RETVAL+0(%r1)
    232 # else
    233 	lhz %r3, RETVAL+6(%r1)
    234 # endif
    235 	mtlr %r0
    236 .Lfinish:
    237 	addi %r1, %r1, STACKFRAME
    238 	blr
    239 # case FFI_TYPE_SINT16
    240 # ifdef __LITTLE_ENDIAN__
    241 	lha %r3, RETVAL+0(%r1)
    242 # else
    243 	lha %r3, RETVAL+6(%r1)
    244 # endif
    245 	mtlr %r0
    246 	addi %r1, %r1, STACKFRAME
    247 	blr
    248 # case FFI_TYPE_UINT32
    249 # ifdef __LITTLE_ENDIAN__
    250 	lwz %r3, RETVAL+0(%r1)
    251 # else
    252 	lwz %r3, RETVAL+4(%r1)
    253 # endif
    254 	mtlr %r0
    255 	addi %r1, %r1, STACKFRAME
    256 	blr
    257 # case FFI_TYPE_SINT32
    258 # ifdef __LITTLE_ENDIAN__
    259 	lwa %r3, RETVAL+0(%r1)
    260 # else
    261 	lwa %r3, RETVAL+4(%r1)
    262 # endif
    263 	mtlr %r0
    264 	addi %r1, %r1, STACKFRAME
    265 	blr
    266 # case FFI_TYPE_UINT64
    267 	ld %r3, RETVAL+0(%r1)
    268 	mtlr %r0
    269 	addi %r1, %r1, STACKFRAME
    270 	blr
    271 # case FFI_TYPE_SINT64
    272 	ld %r3, RETVAL+0(%r1)
    273 	mtlr %r0
    274 	addi %r1, %r1, STACKFRAME
    275 	blr
    276 # case FFI_TYPE_STRUCT
    277 	mtlr %r0
    278 	addi %r1, %r1, STACKFRAME
    279 	blr
    280 	nop
    281 # case FFI_TYPE_POINTER
    282 	ld %r3, RETVAL+0(%r1)
    283 	mtlr %r0
    284 	addi %r1, %r1, STACKFRAME
    285 	blr
    286 # case FFI_V2_TYPE_FLOAT_HOMOG
    287 	lfs %f1, RETVAL+0(%r1)
    288 	lfs %f2, RETVAL+4(%r1)
    289 	lfs %f3, RETVAL+8(%r1)
    290 	b .Lmorefloat
    291 # case FFI_V2_TYPE_DOUBLE_HOMOG
    292 	lfd %f1, RETVAL+0(%r1)
    293 	lfd %f2, RETVAL+8(%r1)
    294 	lfd %f3, RETVAL+16(%r1)
    295 	lfd %f4, RETVAL+24(%r1)
    296 	mtlr %r0
    297 	lfd %f5, RETVAL+32(%r1)
    298 	lfd %f6, RETVAL+40(%r1)
    299 	lfd %f7, RETVAL+48(%r1)
    300 	lfd %f8, RETVAL+56(%r1)
    301 	addi %r1, %r1, STACKFRAME
    302 	blr
    303 .Lmorefloat:
    304 	lfs %f4, RETVAL+12(%r1)
    305 	mtlr %r0
    306 	lfs %f5, RETVAL+16(%r1)
    307 	lfs %f6, RETVAL+20(%r1)
    308 	lfs %f7, RETVAL+24(%r1)
    309 	lfs %f8, RETVAL+28(%r1)
    310 	addi %r1, %r1, STACKFRAME
    311 	blr
    312 .Lsmall:
    313 # ifdef __LITTLE_ENDIAN__
    314 	ld %r3,RETVAL+0(%r1)
    315 	mtlr %r0
    316 	ld %r4,RETVAL+8(%r1)
    317 	addi %r1, %r1, STACKFRAME
    318 	blr
    319 # else
    320 	# A struct smaller than a dword is returned in the low bits of r3
    321 	# ie. right justified.  Larger structs are passed left justified
    322 	# in r3 and r4.  The return value area on the stack will have
    323 	# the structs as they are usually stored in memory.
    324 	cmpldi %r3, FFI_V2_TYPE_SMALL_STRUCT + 7 # size 8 bytes?
    325 	neg %r5, %r3
    326 	ld %r3,RETVAL+0(%r1)
    327 	blt .Lsmalldown
    328 	mtlr %r0
    329 	ld %r4,RETVAL+8(%r1)
    330 	addi %r1, %r1, STACKFRAME
    331 	blr
    332 .Lsmalldown:
    333 	addi %r5, %r5, FFI_V2_TYPE_SMALL_STRUCT + 7
    334 	mtlr %r0
    335 	sldi %r5, %r5, 3
    336 	addi %r1, %r1, STACKFRAME
    337 	srd %r3, %r3, %r5
    338 	blr
    339 # endif
    340 
    341 .LFE1:
    342 	.long	0
    343 	.byte	0,12,0,1,128,0,0,0
    344 # if _CALL_ELF == 2
    345 	.size	ffi_closure_LINUX64,.-ffi_closure_LINUX64
    346 # else
    347 #  ifdef _CALL_LINUX
    348 	.size	ffi_closure_LINUX64,.-.L.ffi_closure_LINUX64
    349 #  else
    350 	.size	.ffi_closure_LINUX64,.-.ffi_closure_LINUX64
    351 #  endif
    352 # endif
    353 
    354 	.section	.eh_frame,EH_FRAME_FLAGS,@progbits
    355 .Lframe1:
    356 	.4byte	.LECIE1-.LSCIE1	 # Length of Common Information Entry
    357 .LSCIE1:
    358 	.4byte	0x0	 # CIE Identifier Tag
    359 	.byte	0x1	 # CIE Version
    360 	.ascii "zR\0"	 # CIE Augmentation
    361 	.uleb128 0x1	 # CIE Code Alignment Factor
    362 	.sleb128 -8	 # CIE Data Alignment Factor
    363 	.byte	0x41	 # CIE RA Column
    364 	.uleb128 0x1	 # Augmentation size
    365 	.byte	0x14	 # FDE Encoding (pcrel udata8)
    366 	.byte	0xc	 # DW_CFA_def_cfa
    367 	.uleb128 0x1
    368 	.uleb128 0x0
    369 	.align 3
    370 .LECIE1:
    371 .LSFDE1:
    372 	.4byte	.LEFDE1-.LASFDE1	 # FDE Length
    373 .LASFDE1:
    374 	.4byte	.LASFDE1-.Lframe1	 # FDE CIE offset
    375 	.8byte	.LFB1-.	 # FDE initial location
    376 	.8byte	.LFE1-.LFB1	 # FDE address range
    377 	.uleb128 0x0	 # Augmentation size
    378 	.byte	0x2	 # DW_CFA_advance_loc1
    379 	.byte	.LCFI0-.LFB1
    380 	.byte	0xe	 # DW_CFA_def_cfa_offset
    381 	.uleb128 STACKFRAME
    382 	.byte	0x11	 # DW_CFA_offset_extended_sf
    383 	.uleb128 0x41
    384 	.sleb128 -2
    385 	.align 3
    386 .LEFDE1:
    387 
    388 # if defined __ELF__ && defined __linux__
    389 	.section	.note.GNU-stack,"",@progbits
    390 # endif
    391 #endif
    392