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