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 	lfs %f1,112+0(%r1)
    126 	mtlr %r0
    127 	addi %r1,%r1,144
    128 	blr
    129 
    130 # case FFI_TYPE_DOUBLE
    131 	lfd %f1,112+0(%r1)
    132 	mtlr %r0
    133 	addi %r1,%r1,144
    134 	blr
    135 
    136 # case FFI_TYPE_LONGDOUBLE
    137 	lfd %f1,112+0(%r1)
    138 	lfd %f2,112+8(%r1)
    139 	mtlr %r0
    140 	b .Lfinish
    141 
    142 # case FFI_TYPE_UINT8
    143 	lbz %r3,112+3(%r1)
    144 	mtlr %r0
    145 	addi %r1,%r1,144
    146 	blr
    147 
    148 # case FFI_TYPE_SINT8
    149 	lbz %r3,112+3(%r1)
    150 	extsb %r3,%r3
    151 	mtlr %r0
    152 	b .Lfinish
    153 
    154 # case FFI_TYPE_UINT16
    155 	lhz %r3,112+2(%r1)
    156 	mtlr %r0
    157 	addi %r1,%r1,144
    158 	blr
    159 
    160 # case FFI_TYPE_SINT16
    161 	lha %r3,112+2(%r1)
    162 	mtlr %r0
    163 	addi %r1,%r1,144
    164 	blr
    165 
    166 # case FFI_TYPE_UINT32
    167 	lwz %r3,112+0(%r1)
    168 	mtlr %r0
    169 	addi %r1,%r1,144
    170 	blr
    171 
    172 # case FFI_TYPE_SINT32
    173 	lwz %r3,112+0(%r1)
    174 	mtlr %r0
    175 	addi %r1,%r1,144
    176 	blr
    177 
    178 # case FFI_TYPE_UINT64
    179 	lwz %r3,112+0(%r1)
    180 	lwz %r4,112+4(%r1)
    181 	mtlr %r0
    182 	b .Lfinish
    183 
    184 # case FFI_TYPE_SINT64
    185 	lwz %r3,112+0(%r1)
    186 	lwz %r4,112+4(%r1)
    187 	mtlr %r0
    188 	b .Lfinish
    189 
    190 # case FFI_TYPE_STRUCT
    191 	mtlr %r0
    192 	addi %r1,%r1,144
    193 	blr
    194 	nop
    195 
    196 # case FFI_TYPE_POINTER
    197 	lwz %r3,112+0(%r1)
    198 	mtlr %r0
    199 	addi %r1,%r1,144
    200 	blr
    201 
    202 # case FFI_TYPE_UINT128
    203 	lwz %r3,112+0(%r1)
    204 	lwz %r4,112+4(%r1)
    205 	lwz %r5,112+8(%r1)
    206 	bl .Luint128
    207 
    208 # The return types below are only used when the ABI type is FFI_SYSV.
    209 # case FFI_SYSV_TYPE_SMALL_STRUCT + 1. One byte struct.
    210 	lbz %r3,112+0(%r1)
    211 	mtlr %r0
    212 	addi %r1,%r1,144
    213 	blr
    214 
    215 # case FFI_SYSV_TYPE_SMALL_STRUCT + 2. Two byte struct.
    216 	lhz %r3,112+0(%r1)
    217 	mtlr %r0
    218 	addi %r1,%r1,144
    219 	blr
    220 
    221 # case FFI_SYSV_TYPE_SMALL_STRUCT + 3. Three byte struct.
    222 	lwz %r3,112+0(%r1)
    223 	srwi %r3,%r3,8
    224 	mtlr %r0
    225 	b .Lfinish
    226 
    227 # case FFI_SYSV_TYPE_SMALL_STRUCT + 4. Four byte struct.
    228 	lwz %r3,112+0(%r1)
    229 	mtlr %r0
    230 	addi %r1,%r1,144
    231 	blr
    232 
    233 # case FFI_SYSV_TYPE_SMALL_STRUCT + 5. Five byte struct.
    234 	lwz %r3,112+0(%r1)
    235 	lwz %r4,112+4(%r1)
    236 	li %r5,24
    237 	b .Lstruct567
    238 
    239 # case FFI_SYSV_TYPE_SMALL_STRUCT + 6. Six byte struct.
    240 	lwz %r3,112+0(%r1)
    241 	lwz %r4,112+4(%r1)
    242 	li %r5,16
    243 	b .Lstruct567
    244 
    245 # case FFI_SYSV_TYPE_SMALL_STRUCT + 7. Seven byte struct.
    246 	lwz %r3,112+0(%r1)
    247 	lwz %r4,112+4(%r1)
    248 	li %r5,8
    249 	b .Lstruct567
    250 
    251 # case FFI_SYSV_TYPE_SMALL_STRUCT + 8. Eight byte struct.
    252 	lwz %r3,112+0(%r1)
    253 	lwz %r4,112+4(%r1)
    254 	mtlr %r0
    255 	b .Lfinish
    256 
    257 .Lstruct567:
    258 	subfic %r6,%r5,32
    259 	srw %r4,%r4,%r5
    260 	slw %r6,%r3,%r6
    261 	srw %r3,%r3,%r5
    262 	or %r4,%r6,%r4
    263 	mtlr %r0
    264 	addi %r1,%r1,144
    265 	blr
    266 
    267 .Luint128:
    268 	lwz %r6,112+12(%r1)
    269 	mtlr %r0
    270 	addi %r1,%r1,144
    271 	blr
    272 
    273 END(ffi_closure_SYSV)
    274 
    275 	.section	".eh_frame",EH_FRAME_FLAGS,@progbits
    276 .Lframe1:
    277 	.4byte	.LECIE1-.LSCIE1	 # Length of Common Information Entry
    278 .LSCIE1:
    279 	.4byte	0x0	 # CIE Identifier Tag
    280 	.byte	0x1	 # CIE Version
    281 #if defined _RELOCATABLE || defined __PIC__
    282 	.ascii "zR\0"	 # CIE Augmentation
    283 #else
    284 	.ascii "\0"	 # CIE Augmentation
    285 #endif
    286 	.uleb128 0x1	 # CIE Code Alignment Factor
    287 	.sleb128 -4	 # CIE Data Alignment Factor
    288 	.byte	0x41	 # CIE RA Column
    289 #if defined _RELOCATABLE || defined __PIC__
    290 	.uleb128 0x1	 # Augmentation size
    291 	.byte	0x1b	 # FDE Encoding (pcrel sdata4)
    292 #endif
    293 	.byte	0xc	 # DW_CFA_def_cfa
    294 	.uleb128 0x1
    295 	.uleb128 0x0
    296 	.align 2
    297 .LECIE1:
    298 .LSFDE1:
    299 	.4byte	.LEFDE1-.LASFDE1	 # FDE Length
    300 .LASFDE1:
    301 	.4byte	.LASFDE1-.Lframe1	 # FDE CIE offset
    302 #if defined _RELOCATABLE || defined __PIC__
    303 	.4byte	.LFB1-.	 # FDE initial location
    304 #else
    305 	.4byte	.LFB1	 # FDE initial location
    306 #endif
    307 	.4byte	.LFE1-.LFB1	 # FDE address range
    308 #if defined _RELOCATABLE || defined __PIC__
    309 	.uleb128 0x0	 # Augmentation size
    310 #endif
    311 	.byte	0x4	 # DW_CFA_advance_loc4
    312 	.4byte	.LCFI0-.LFB1
    313 	.byte	0xe	 # DW_CFA_def_cfa_offset
    314 	.uleb128 144
    315 	.byte	0x4	 # DW_CFA_advance_loc4
    316 	.4byte	.LCFI1-.LCFI0
    317 	.byte	0x11	 # DW_CFA_offset_extended_sf
    318 	.uleb128 0x41
    319 	.sleb128 -1
    320 	.align 2
    321 .LEFDE1:
    322 
    323 #endif
    324 
    325 #if defined __ELF__ && defined __linux__
    326 	.section	.note.GNU-stack,"",@progbits
    327 #endif
    328