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