1/* ----------------------------------------------------------------------- 2 sysv.h - Copyright (c) 2003 Jakub Jelinek <jakub@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 36ENTRY(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 273END(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