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    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,
     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 #include <powerpc/asm.h>
     31 
     32 	.file   "ppc_closure.S"
     33 
     34 #ifndef POWERPC64
     35 
     36 ENTRY(ffi_closure_SYSV)
     37 .LFB1:
     38 	stwu %r1,-144(%r1)
     39 .LCFI0:
     40 	mflr %r0
     41 .LCFI1:
     42 	stw %r0,148(%r1)
     43 
     44 # we want to build up an areas for the parameters passed
     45 # in registers (both floating point and integer)
     46 
     47 	# so first save gpr 3 to gpr 10 (aligned to 4)
     48 	stw   %r3, 16(%r1)
     49 	stw   %r4, 20(%r1)
     50 	stw   %r5, 24(%r1)
     51 	stw   %r6, 28(%r1)
     52 	stw   %r7, 32(%r1)
     53 	stw   %r8, 36(%r1)
     54 	stw   %r9, 40(%r1)
     55 	stw   %r10,44(%r1)
     56 
     57 #ifndef __NO_FPRS__
     58 	# next save fpr 1 to fpr 8 (aligned to 8)
     59 	stfd  %f1, 48(%r1)
     60 	stfd  %f2, 56(%r1)
     61 	stfd  %f3, 64(%r1)
     62 	stfd  %f4, 72(%r1)
     63 	stfd  %f5, 80(%r1)
     64 	stfd  %f6, 88(%r1)
     65 	stfd  %f7, 96(%r1)
     66 	stfd  %f8, 104(%r1)
     67 #endif
     68 
     69 	# set up registers for the routine that actually does the work
     70 	# get the context pointer from the trampoline
     71 	mr %r3,%r11
     72 
     73 	# now load up the pointer to the result storage
     74 	addi %r4,%r1,112
     75 
     76 	# now load up the pointer to the saved gpr registers
     77 	addi %r5,%r1,16
     78 
     79 	# now load up the pointer to the saved fpr registers */
     80 	addi %r6,%r1,48
     81 
     82 	# now load up the pointer to the outgoing parameter
     83 	# stack in the previous frame
     84 	# i.e. the previous frame pointer + 8
     85 	addi %r7,%r1,152
     86 
     87 	# make the call
     88 	bl ffi_closure_helper_SYSV@local
     89 .Lret:
     90 	# now r3 contains the return type
     91 	# so use it to look up in a table
     92 	# so we know how to deal with each type
     93 
     94 	# look up the proper starting point in table
     95 	# by using return type as offset
     96 
     97 	mflr %r4		# move address of .Lret to r4
     98 	slwi %r3,%r3,4		# now multiply return type by 16
     99 	addi %r4, %r4, .Lret_type0 - .Lret
    100 	lwz %r0,148(%r1)
    101 	add %r3,%r3,%r4		# add contents of table to table address
    102 	mtctr %r3
    103 	bctr			# jump to it
    104 .LFE1:
    105 
    106 # Each of the ret_typeX code fragments has to be exactly 16 bytes long
    107 # (4 instructions). For cache effectiveness we align to a 16 byte boundary
    108 # first.
    109 	.align 4
    110 # case FFI_TYPE_VOID
    111 .Lret_type0:
    112 	mtlr %r0
    113 	addi %r1,%r1,144
    114 	blr
    115 	nop
    116 
    117 # case FFI_TYPE_INT
    118 	lwz %r3,112+0(%r1)
    119 	mtlr %r0
    120 .Lfinish:
    121 	addi %r1,%r1,144
    122 	blr
    123 
    124 # case FFI_TYPE_FLOAT
    125 #ifndef __NO_FPRS__
    126 	lfs %f1,112+0(%r1)
    127 	mtlr %r0
    128 	addi %r1,%r1,144
    129 #else
    130 	nop
    131 	nop
    132 	nop
    133 #endif
    134 	blr
    135 
    136 # case FFI_TYPE_DOUBLE
    137 #ifndef __NO_FPRS__
    138 	lfd %f1,112+0(%r1)
    139 	mtlr %r0
    140 	addi %r1,%r1,144
    141 #else
    142 	nop
    143 	nop
    144 	nop
    145 #endif
    146 	blr
    147 
    148 # case FFI_TYPE_LONGDOUBLE
    149 #ifndef __NO_FPRS__
    150 	lfd %f1,112+0(%r1)
    151 	lfd %f2,112+8(%r1)
    152 	mtlr %r0
    153 	b .Lfinish
    154 #else
    155 	nop
    156 	nop
    157 	nop
    158 	blr
    159 #endif
    160 
    161 # case FFI_TYPE_UINT8
    162 #ifdef __LITTLE_ENDIAN__
    163 	lbz %r3,112+0(%r1)
    164 #else
    165 	lbz %r3,112+3(%r1)
    166 #endif
    167 	mtlr %r0
    168 	addi %r1,%r1,144
    169 	blr
    170 
    171 # case FFI_TYPE_SINT8
    172 #ifdef __LITTLE_ENDIAN__
    173 	lbz %r3,112+0(%r1)
    174 #else
    175 	lbz %r3,112+3(%r1)
    176 #endif
    177 	extsb %r3,%r3
    178 	mtlr %r0
    179 	b .Lfinish
    180 
    181 # case FFI_TYPE_UINT16
    182 #ifdef __LITTLE_ENDIAN__
    183 	lhz %r3,112+0(%r1)
    184 #else
    185 	lhz %r3,112+2(%r1)
    186 #endif
    187 	mtlr %r0
    188 	addi %r1,%r1,144
    189 	blr
    190 
    191 # case FFI_TYPE_SINT16
    192 #ifdef __LITTLE_ENDIAN__
    193 	lha %r3,112+0(%r1)
    194 #else
    195 	lha %r3,112+2(%r1)
    196 #endif
    197 	mtlr %r0
    198 	addi %r1,%r1,144
    199 	blr
    200 
    201 # case FFI_TYPE_UINT32
    202 	lwz %r3,112+0(%r1)
    203 	mtlr %r0
    204 	addi %r1,%r1,144
    205 	blr
    206 
    207 # case FFI_TYPE_SINT32
    208 	lwz %r3,112+0(%r1)
    209 	mtlr %r0
    210 	addi %r1,%r1,144
    211 	blr
    212 
    213 # case FFI_TYPE_UINT64
    214 	lwz %r3,112+0(%r1)
    215 	lwz %r4,112+4(%r1)
    216 	mtlr %r0
    217 	b .Lfinish
    218 
    219 # case FFI_TYPE_SINT64
    220 	lwz %r3,112+0(%r1)
    221 	lwz %r4,112+4(%r1)
    222 	mtlr %r0
    223 	b .Lfinish
    224 
    225 # case FFI_TYPE_STRUCT
    226 	mtlr %r0
    227 	addi %r1,%r1,144
    228 	blr
    229 	nop
    230 
    231 # case FFI_TYPE_POINTER
    232 	lwz %r3,112+0(%r1)
    233 	mtlr %r0
    234 	addi %r1,%r1,144
    235 	blr
    236 
    237 # case FFI_TYPE_UINT128
    238 	lwz %r3,112+0(%r1)
    239 	lwz %r4,112+4(%r1)
    240 	lwz %r5,112+8(%r1)
    241 	b .Luint128
    242 
    243 # The return types below are only used when the ABI type is FFI_SYSV.
    244 # case FFI_SYSV_TYPE_SMALL_STRUCT + 1. One byte struct.
    245 	lbz %r3,112+0(%r1)
    246 	mtlr %r0
    247 	addi %r1,%r1,144
    248 	blr
    249 
    250 # case FFI_SYSV_TYPE_SMALL_STRUCT + 2. Two byte struct.
    251 	lhz %r3,112+0(%r1)
    252 	mtlr %r0
    253 	addi %r1,%r1,144
    254 	blr
    255 
    256 # case FFI_SYSV_TYPE_SMALL_STRUCT + 3. Three byte struct.
    257 	lwz %r3,112+0(%r1)
    258 #ifdef __LITTLE_ENDIAN__
    259 	mtlr %r0
    260 	addi %r1,%r1,144
    261 	blr
    262 #else
    263 	srwi %r3,%r3,8
    264 	mtlr %r0
    265 	b .Lfinish
    266 #endif
    267 
    268 # case FFI_SYSV_TYPE_SMALL_STRUCT + 4. Four byte struct.
    269 	lwz %r3,112+0(%r1)
    270 	mtlr %r0
    271 	addi %r1,%r1,144
    272 	blr
    273 
    274 # case FFI_SYSV_TYPE_SMALL_STRUCT + 5. Five byte struct.
    275 	lwz %r3,112+0(%r1)
    276 	lwz %r4,112+4(%r1)
    277 #ifdef __LITTLE_ENDIAN__
    278 	mtlr %r0
    279 	b .Lfinish
    280 #else
    281 	li %r5,24
    282 	b .Lstruct567
    283 #endif
    284 
    285 # case FFI_SYSV_TYPE_SMALL_STRUCT + 6. Six byte struct.
    286 	lwz %r3,112+0(%r1)
    287 	lwz %r4,112+4(%r1)
    288 #ifdef __LITTLE_ENDIAN__
    289 	mtlr %r0
    290 	b .Lfinish
    291 #else
    292 	li %r5,16
    293 	b .Lstruct567
    294 #endif
    295 
    296 # case FFI_SYSV_TYPE_SMALL_STRUCT + 7. Seven byte struct.
    297 	lwz %r3,112+0(%r1)
    298 	lwz %r4,112+4(%r1)
    299 #ifdef __LITTLE_ENDIAN__
    300 	mtlr %r0
    301 	b .Lfinish
    302 #else
    303 	li %r5,8
    304 	b .Lstruct567
    305 #endif
    306 
    307 # case FFI_SYSV_TYPE_SMALL_STRUCT + 8. Eight byte struct.
    308 	lwz %r3,112+0(%r1)
    309 	lwz %r4,112+4(%r1)
    310 	mtlr %r0
    311 	b .Lfinish
    312 
    313 #ifndef __LITTLE_ENDIAN__
    314 .Lstruct567:
    315 	subfic %r6,%r5,32
    316 	srw %r4,%r4,%r5
    317 	slw %r6,%r3,%r6
    318 	srw %r3,%r3,%r5
    319 	or %r4,%r6,%r4
    320 	mtlr %r0
    321 	addi %r1,%r1,144
    322 	blr
    323 #endif
    324 
    325 .Luint128:
    326 	lwz %r6,112+12(%r1)
    327 	mtlr %r0
    328 	addi %r1,%r1,144
    329 	blr
    330 
    331 END(ffi_closure_SYSV)
    332 
    333 	.section	".eh_frame",EH_FRAME_FLAGS,@progbits
    334 .Lframe1:
    335 	.4byte	.LECIE1-.LSCIE1	 # Length of Common Information Entry
    336 .LSCIE1:
    337 	.4byte	0x0	 # CIE Identifier Tag
    338 	.byte	0x1	 # CIE Version
    339 #if defined _RELOCATABLE || defined __PIC__
    340 	.ascii "zR\0"	 # CIE Augmentation
    341 #else
    342 	.ascii "\0"	 # CIE Augmentation
    343 #endif
    344 	.uleb128 0x1	 # CIE Code Alignment Factor
    345 	.sleb128 -4	 # CIE Data Alignment Factor
    346 	.byte	0x41	 # CIE RA Column
    347 #if defined _RELOCATABLE || defined __PIC__
    348 	.uleb128 0x1	 # Augmentation size
    349 	.byte	0x1b	 # FDE Encoding (pcrel sdata4)
    350 #endif
    351 	.byte	0xc	 # DW_CFA_def_cfa
    352 	.uleb128 0x1
    353 	.uleb128 0x0
    354 	.align 2
    355 .LECIE1:
    356 .LSFDE1:
    357 	.4byte	.LEFDE1-.LASFDE1	 # FDE Length
    358 .LASFDE1:
    359 	.4byte	.LASFDE1-.Lframe1	 # FDE CIE offset
    360 #if defined _RELOCATABLE || defined __PIC__
    361 	.4byte	.LFB1-.	 # FDE initial location
    362 #else
    363 	.4byte	.LFB1	 # FDE initial location
    364 #endif
    365 	.4byte	.LFE1-.LFB1	 # FDE address range
    366 #if defined _RELOCATABLE || defined __PIC__
    367 	.uleb128 0x0	 # Augmentation size
    368 #endif
    369 	.byte	0x4	 # DW_CFA_advance_loc4
    370 	.4byte	.LCFI0-.LFB1
    371 	.byte	0xe	 # DW_CFA_def_cfa_offset
    372 	.uleb128 144
    373 	.byte	0x4	 # DW_CFA_advance_loc4
    374 	.4byte	.LCFI1-.LCFI0
    375 	.byte	0x11	 # DW_CFA_offset_extended_sf
    376 	.uleb128 0x41
    377 	.sleb128 -1
    378 	.align 2
    379 .LEFDE1:
    380 
    381 #if defined __ELF__ && defined __linux__
    382 	.section	.note.GNU-stack,"",@progbits
    383 #endif
    384 #endif
    385