Add powerpc soft float support
This commit is contained in:
@@ -34,3 +34,4 @@ kfreebsd-mmap
|
|||||||
minix
|
minix
|
||||||
interix-patch
|
interix-patch
|
||||||
remove-debug-code
|
remove-debug-code
|
||||||
|
powerpc-ffi-softfloat
|
||||||
|
|||||||
0
.pc/powerpc-ffi-softfloat/.timestamp
Normal file
0
.pc/powerpc-ffi-softfloat/.timestamp
Normal file
4661
.pc/powerpc-ffi-softfloat/ChangeLog
Normal file
4661
.pc/powerpc-ffi-softfloat/ChangeLog
Normal file
File diff suppressed because it is too large
Load Diff
1444
.pc/powerpc-ffi-softfloat/src/powerpc/ffi.c
Normal file
1444
.pc/powerpc-ffi-softfloat/src/powerpc/ffi.c
Normal file
File diff suppressed because it is too large
Load Diff
139
.pc/powerpc-ffi-softfloat/src/powerpc/ffitarget.h
Normal file
139
.pc/powerpc-ffi-softfloat/src/powerpc/ffitarget.h
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
/* -----------------------------------------------------------------*-C-*-
|
||||||
|
ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc.
|
||||||
|
Copyright (C) 2007, 2008, 2010 Free Software Foundation, Inc
|
||||||
|
Target configuration macros for PowerPC.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of this software and associated documentation files (the
|
||||||
|
``Software''), to deal in the Software without restriction, including
|
||||||
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included
|
||||||
|
in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
----------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#ifndef LIBFFI_TARGET_H
|
||||||
|
#define LIBFFI_TARGET_H
|
||||||
|
|
||||||
|
/* ---- System specific configurations ----------------------------------- */
|
||||||
|
|
||||||
|
#if defined (POWERPC) && defined (__powerpc64__) /* linux64 */
|
||||||
|
#ifndef POWERPC64
|
||||||
|
#define POWERPC64
|
||||||
|
#endif
|
||||||
|
#elif defined (POWERPC_DARWIN) && defined (__ppc64__) /* Darwin64 */
|
||||||
|
#ifndef POWERPC64
|
||||||
|
#define POWERPC64
|
||||||
|
#endif
|
||||||
|
#ifndef POWERPC_DARWIN64
|
||||||
|
#define POWERPC_DARWIN64
|
||||||
|
#endif
|
||||||
|
#elif defined (POWERPC_AIX) && defined (__64BIT__) /* AIX64 */
|
||||||
|
#ifndef POWERPC64
|
||||||
|
#define POWERPC64
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef LIBFFI_ASM
|
||||||
|
typedef unsigned long ffi_arg;
|
||||||
|
typedef signed long ffi_sarg;
|
||||||
|
|
||||||
|
typedef enum ffi_abi {
|
||||||
|
FFI_FIRST_ABI = 0,
|
||||||
|
|
||||||
|
#ifdef POWERPC
|
||||||
|
FFI_SYSV,
|
||||||
|
FFI_GCC_SYSV,
|
||||||
|
FFI_LINUX64,
|
||||||
|
FFI_LINUX,
|
||||||
|
FFI_LINUX_SOFT_FLOAT,
|
||||||
|
# ifdef POWERPC64
|
||||||
|
FFI_DEFAULT_ABI = FFI_LINUX64,
|
||||||
|
# else
|
||||||
|
# if (!defined(__NO_FPRS__) && (__LDBL_MANT_DIG__ == 106))
|
||||||
|
FFI_DEFAULT_ABI = FFI_LINUX,
|
||||||
|
# else
|
||||||
|
# ifdef __NO_FPRS__
|
||||||
|
FFI_DEFAULT_ABI = FFI_LINUX_SOFT_FLOAT,
|
||||||
|
# else
|
||||||
|
FFI_DEFAULT_ABI = FFI_GCC_SYSV,
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef POWERPC_AIX
|
||||||
|
FFI_AIX,
|
||||||
|
FFI_DARWIN,
|
||||||
|
FFI_DEFAULT_ABI = FFI_AIX,
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef POWERPC_DARWIN
|
||||||
|
FFI_AIX,
|
||||||
|
FFI_DARWIN,
|
||||||
|
FFI_DEFAULT_ABI = FFI_DARWIN,
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef POWERPC_FREEBSD
|
||||||
|
FFI_SYSV,
|
||||||
|
FFI_GCC_SYSV,
|
||||||
|
FFI_LINUX64,
|
||||||
|
FFI_LINUX,
|
||||||
|
FFI_LINUX_SOFT_FLOAT,
|
||||||
|
FFI_DEFAULT_ABI = FFI_SYSV,
|
||||||
|
#endif
|
||||||
|
|
||||||
|
FFI_LAST_ABI
|
||||||
|
} ffi_abi;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ---- Definitions for closures ----------------------------------------- */
|
||||||
|
|
||||||
|
#define FFI_CLOSURES 1
|
||||||
|
#define FFI_NATIVE_RAW_API 0
|
||||||
|
|
||||||
|
/* For additional types like the below, take care about the order in
|
||||||
|
ppc_closures.S. They must follow after the FFI_TYPE_LAST. */
|
||||||
|
|
||||||
|
/* Needed for soft-float long-double-128 support. */
|
||||||
|
#define FFI_TYPE_UINT128 (FFI_TYPE_LAST + 1)
|
||||||
|
|
||||||
|
/* Needed for FFI_SYSV small structure returns.
|
||||||
|
We use two flag bits, (FLAG_SYSV_SMST_R3, FLAG_SYSV_SMST_R4) which are
|
||||||
|
defined in ffi.c, to determine the exact return type and its size. */
|
||||||
|
#define FFI_SYSV_TYPE_SMALL_STRUCT (FFI_TYPE_LAST + 2)
|
||||||
|
|
||||||
|
#if defined(POWERPC64) || defined(POWERPC_AIX)
|
||||||
|
# if defined(POWERPC_DARWIN64)
|
||||||
|
# define FFI_TRAMPOLINE_SIZE 48
|
||||||
|
# else
|
||||||
|
# define FFI_TRAMPOLINE_SIZE 24
|
||||||
|
# endif
|
||||||
|
#else /* POWERPC || POWERPC_AIX */
|
||||||
|
# define FFI_TRAMPOLINE_SIZE 40
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef LIBFFI_ASM
|
||||||
|
#if defined(POWERPC_DARWIN) || defined(POWERPC_AIX)
|
||||||
|
struct ffi_aix_trampoline_struct {
|
||||||
|
void * code_pointer; /* Pointer to ffi_closure_ASM */
|
||||||
|
void * toc; /* TOC */
|
||||||
|
void * static_chain; /* Pointer to closure */
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
327
.pc/powerpc-ffi-softfloat/src/powerpc/ppc_closure.S
Normal file
327
.pc/powerpc-ffi-softfloat/src/powerpc/ppc_closure.S
Normal file
@@ -0,0 +1,327 @@
|
|||||||
|
/* -----------------------------------------------------------------------
|
||||||
|
sysv.h - Copyright (c) 2003 Jakub Jelinek <jakub@redhat.com>
|
||||||
|
Copyright (c) 2008 Red Hat, Inc.
|
||||||
|
|
||||||
|
PowerPC Assembly glue.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of this software and associated documentation files (the
|
||||||
|
``Software''), to deal in the Software without restriction, including
|
||||||
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included
|
||||||
|
in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
DEALINGS IN THE SOFTWARE.
|
||||||
|
----------------------------------------------------------------------- */
|
||||||
|
#define LIBFFI_ASM
|
||||||
|
#include <fficonfig.h>
|
||||||
|
#include <ffi.h>
|
||||||
|
#include <powerpc/asm.h>
|
||||||
|
|
||||||
|
.file "ppc_closure.S"
|
||||||
|
|
||||||
|
#ifndef __powerpc64__
|
||||||
|
|
||||||
|
ENTRY(ffi_closure_SYSV)
|
||||||
|
.LFB1:
|
||||||
|
stwu %r1,-144(%r1)
|
||||||
|
.LCFI0:
|
||||||
|
mflr %r0
|
||||||
|
.LCFI1:
|
||||||
|
stw %r0,148(%r1)
|
||||||
|
|
||||||
|
# we want to build up an areas for the parameters passed
|
||||||
|
# in registers (both floating point and integer)
|
||||||
|
|
||||||
|
# so first save gpr 3 to gpr 10 (aligned to 4)
|
||||||
|
stw %r3, 16(%r1)
|
||||||
|
stw %r4, 20(%r1)
|
||||||
|
stw %r5, 24(%r1)
|
||||||
|
stw %r6, 28(%r1)
|
||||||
|
stw %r7, 32(%r1)
|
||||||
|
stw %r8, 36(%r1)
|
||||||
|
stw %r9, 40(%r1)
|
||||||
|
stw %r10,44(%r1)
|
||||||
|
|
||||||
|
#ifndef __NO_FPRS__
|
||||||
|
# next save fpr 1 to fpr 8 (aligned to 8)
|
||||||
|
stfd %f1, 48(%r1)
|
||||||
|
stfd %f2, 56(%r1)
|
||||||
|
stfd %f3, 64(%r1)
|
||||||
|
stfd %f4, 72(%r1)
|
||||||
|
stfd %f5, 80(%r1)
|
||||||
|
stfd %f6, 88(%r1)
|
||||||
|
stfd %f7, 96(%r1)
|
||||||
|
stfd %f8, 104(%r1)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
# set up registers for the routine that actually does the work
|
||||||
|
# get the context pointer from the trampoline
|
||||||
|
mr %r3,%r11
|
||||||
|
|
||||||
|
# now load up the pointer to the result storage
|
||||||
|
addi %r4,%r1,112
|
||||||
|
|
||||||
|
# now load up the pointer to the saved gpr registers
|
||||||
|
addi %r5,%r1,16
|
||||||
|
|
||||||
|
# now load up the pointer to the saved fpr registers */
|
||||||
|
addi %r6,%r1,48
|
||||||
|
|
||||||
|
# now load up the pointer to the outgoing parameter
|
||||||
|
# stack in the previous frame
|
||||||
|
# i.e. the previous frame pointer + 8
|
||||||
|
addi %r7,%r1,152
|
||||||
|
|
||||||
|
# make the call
|
||||||
|
bl ffi_closure_helper_SYSV@local
|
||||||
|
.Lret:
|
||||||
|
# now r3 contains the return type
|
||||||
|
# so use it to look up in a table
|
||||||
|
# so we know how to deal with each type
|
||||||
|
|
||||||
|
# look up the proper starting point in table
|
||||||
|
# by using return type as offset
|
||||||
|
|
||||||
|
mflr %r4 # move address of .Lret to r4
|
||||||
|
slwi %r3,%r3,4 # now multiply return type by 16
|
||||||
|
addi %r4, %r4, .Lret_type0 - .Lret
|
||||||
|
lwz %r0,148(%r1)
|
||||||
|
add %r3,%r3,%r4 # add contents of table to table address
|
||||||
|
mtctr %r3
|
||||||
|
bctr # jump to it
|
||||||
|
.LFE1:
|
||||||
|
|
||||||
|
# Each of the ret_typeX code fragments has to be exactly 16 bytes long
|
||||||
|
# (4 instructions). For cache effectiveness we align to a 16 byte boundary
|
||||||
|
# first.
|
||||||
|
.align 4
|
||||||
|
# case FFI_TYPE_VOID
|
||||||
|
.Lret_type0:
|
||||||
|
mtlr %r0
|
||||||
|
addi %r1,%r1,144
|
||||||
|
blr
|
||||||
|
nop
|
||||||
|
|
||||||
|
# case FFI_TYPE_INT
|
||||||
|
lwz %r3,112+0(%r1)
|
||||||
|
mtlr %r0
|
||||||
|
.Lfinish:
|
||||||
|
addi %r1,%r1,144
|
||||||
|
blr
|
||||||
|
|
||||||
|
# case FFI_TYPE_FLOAT
|
||||||
|
lfs %f1,112+0(%r1)
|
||||||
|
mtlr %r0
|
||||||
|
addi %r1,%r1,144
|
||||||
|
blr
|
||||||
|
|
||||||
|
# case FFI_TYPE_DOUBLE
|
||||||
|
lfd %f1,112+0(%r1)
|
||||||
|
mtlr %r0
|
||||||
|
addi %r1,%r1,144
|
||||||
|
blr
|
||||||
|
|
||||||
|
# case FFI_TYPE_LONGDOUBLE
|
||||||
|
lfd %f1,112+0(%r1)
|
||||||
|
lfd %f2,112+8(%r1)
|
||||||
|
mtlr %r0
|
||||||
|
b .Lfinish
|
||||||
|
|
||||||
|
# case FFI_TYPE_UINT8
|
||||||
|
lbz %r3,112+3(%r1)
|
||||||
|
mtlr %r0
|
||||||
|
addi %r1,%r1,144
|
||||||
|
blr
|
||||||
|
|
||||||
|
# case FFI_TYPE_SINT8
|
||||||
|
lbz %r3,112+3(%r1)
|
||||||
|
extsb %r3,%r3
|
||||||
|
mtlr %r0
|
||||||
|
b .Lfinish
|
||||||
|
|
||||||
|
# case FFI_TYPE_UINT16
|
||||||
|
lhz %r3,112+2(%r1)
|
||||||
|
mtlr %r0
|
||||||
|
addi %r1,%r1,144
|
||||||
|
blr
|
||||||
|
|
||||||
|
# case FFI_TYPE_SINT16
|
||||||
|
lha %r3,112+2(%r1)
|
||||||
|
mtlr %r0
|
||||||
|
addi %r1,%r1,144
|
||||||
|
blr
|
||||||
|
|
||||||
|
# case FFI_TYPE_UINT32
|
||||||
|
lwz %r3,112+0(%r1)
|
||||||
|
mtlr %r0
|
||||||
|
addi %r1,%r1,144
|
||||||
|
blr
|
||||||
|
|
||||||
|
# case FFI_TYPE_SINT32
|
||||||
|
lwz %r3,112+0(%r1)
|
||||||
|
mtlr %r0
|
||||||
|
addi %r1,%r1,144
|
||||||
|
blr
|
||||||
|
|
||||||
|
# case FFI_TYPE_UINT64
|
||||||
|
lwz %r3,112+0(%r1)
|
||||||
|
lwz %r4,112+4(%r1)
|
||||||
|
mtlr %r0
|
||||||
|
b .Lfinish
|
||||||
|
|
||||||
|
# case FFI_TYPE_SINT64
|
||||||
|
lwz %r3,112+0(%r1)
|
||||||
|
lwz %r4,112+4(%r1)
|
||||||
|
mtlr %r0
|
||||||
|
b .Lfinish
|
||||||
|
|
||||||
|
# case FFI_TYPE_STRUCT
|
||||||
|
mtlr %r0
|
||||||
|
addi %r1,%r1,144
|
||||||
|
blr
|
||||||
|
nop
|
||||||
|
|
||||||
|
# case FFI_TYPE_POINTER
|
||||||
|
lwz %r3,112+0(%r1)
|
||||||
|
mtlr %r0
|
||||||
|
addi %r1,%r1,144
|
||||||
|
blr
|
||||||
|
|
||||||
|
# case FFI_TYPE_UINT128
|
||||||
|
lwz %r3,112+0(%r1)
|
||||||
|
lwz %r4,112+4(%r1)
|
||||||
|
lwz %r5,112+8(%r1)
|
||||||
|
bl .Luint128
|
||||||
|
|
||||||
|
# The return types below are only used when the ABI type is FFI_SYSV.
|
||||||
|
# case FFI_SYSV_TYPE_SMALL_STRUCT + 1. One byte struct.
|
||||||
|
lbz %r3,112+0(%r1)
|
||||||
|
mtlr %r0
|
||||||
|
addi %r1,%r1,144
|
||||||
|
blr
|
||||||
|
|
||||||
|
# case FFI_SYSV_TYPE_SMALL_STRUCT + 2. Two byte struct.
|
||||||
|
lhz %r3,112+0(%r1)
|
||||||
|
mtlr %r0
|
||||||
|
addi %r1,%r1,144
|
||||||
|
blr
|
||||||
|
|
||||||
|
# case FFI_SYSV_TYPE_SMALL_STRUCT + 3. Three byte struct.
|
||||||
|
lwz %r3,112+0(%r1)
|
||||||
|
srwi %r3,%r3,8
|
||||||
|
mtlr %r0
|
||||||
|
b .Lfinish
|
||||||
|
|
||||||
|
# case FFI_SYSV_TYPE_SMALL_STRUCT + 4. Four byte struct.
|
||||||
|
lwz %r3,112+0(%r1)
|
||||||
|
mtlr %r0
|
||||||
|
addi %r1,%r1,144
|
||||||
|
blr
|
||||||
|
|
||||||
|
# case FFI_SYSV_TYPE_SMALL_STRUCT + 5. Five byte struct.
|
||||||
|
lwz %r3,112+0(%r1)
|
||||||
|
lwz %r4,112+4(%r1)
|
||||||
|
li %r5,24
|
||||||
|
b .Lstruct567
|
||||||
|
|
||||||
|
# case FFI_SYSV_TYPE_SMALL_STRUCT + 6. Six byte struct.
|
||||||
|
lwz %r3,112+0(%r1)
|
||||||
|
lwz %r4,112+4(%r1)
|
||||||
|
li %r5,16
|
||||||
|
b .Lstruct567
|
||||||
|
|
||||||
|
# case FFI_SYSV_TYPE_SMALL_STRUCT + 7. Seven byte struct.
|
||||||
|
lwz %r3,112+0(%r1)
|
||||||
|
lwz %r4,112+4(%r1)
|
||||||
|
li %r5,8
|
||||||
|
b .Lstruct567
|
||||||
|
|
||||||
|
# case FFI_SYSV_TYPE_SMALL_STRUCT + 8. Eight byte struct.
|
||||||
|
lwz %r3,112+0(%r1)
|
||||||
|
lwz %r4,112+4(%r1)
|
||||||
|
mtlr %r0
|
||||||
|
b .Lfinish
|
||||||
|
|
||||||
|
.Lstruct567:
|
||||||
|
subfic %r6,%r5,32
|
||||||
|
srw %r4,%r4,%r5
|
||||||
|
slw %r6,%r3,%r6
|
||||||
|
srw %r3,%r3,%r5
|
||||||
|
or %r4,%r6,%r4
|
||||||
|
mtlr %r0
|
||||||
|
addi %r1,%r1,144
|
||||||
|
blr
|
||||||
|
|
||||||
|
.Luint128:
|
||||||
|
lwz %r6,112+12(%r1)
|
||||||
|
mtlr %r0
|
||||||
|
addi %r1,%r1,144
|
||||||
|
blr
|
||||||
|
|
||||||
|
END(ffi_closure_SYSV)
|
||||||
|
|
||||||
|
.section ".eh_frame",EH_FRAME_FLAGS,@progbits
|
||||||
|
.Lframe1:
|
||||||
|
.4byte .LECIE1-.LSCIE1 # Length of Common Information Entry
|
||||||
|
.LSCIE1:
|
||||||
|
.4byte 0x0 # CIE Identifier Tag
|
||||||
|
.byte 0x1 # CIE Version
|
||||||
|
#if defined _RELOCATABLE || defined __PIC__
|
||||||
|
.ascii "zR\0" # CIE Augmentation
|
||||||
|
#else
|
||||||
|
.ascii "\0" # CIE Augmentation
|
||||||
|
#endif
|
||||||
|
.uleb128 0x1 # CIE Code Alignment Factor
|
||||||
|
.sleb128 -4 # CIE Data Alignment Factor
|
||||||
|
.byte 0x41 # CIE RA Column
|
||||||
|
#if defined _RELOCATABLE || defined __PIC__
|
||||||
|
.uleb128 0x1 # Augmentation size
|
||||||
|
.byte 0x1b # FDE Encoding (pcrel sdata4)
|
||||||
|
#endif
|
||||||
|
.byte 0xc # DW_CFA_def_cfa
|
||||||
|
.uleb128 0x1
|
||||||
|
.uleb128 0x0
|
||||||
|
.align 2
|
||||||
|
.LECIE1:
|
||||||
|
.LSFDE1:
|
||||||
|
.4byte .LEFDE1-.LASFDE1 # FDE Length
|
||||||
|
.LASFDE1:
|
||||||
|
.4byte .LASFDE1-.Lframe1 # FDE CIE offset
|
||||||
|
#if defined _RELOCATABLE || defined __PIC__
|
||||||
|
.4byte .LFB1-. # FDE initial location
|
||||||
|
#else
|
||||||
|
.4byte .LFB1 # FDE initial location
|
||||||
|
#endif
|
||||||
|
.4byte .LFE1-.LFB1 # FDE address range
|
||||||
|
#if defined _RELOCATABLE || defined __PIC__
|
||||||
|
.uleb128 0x0 # Augmentation size
|
||||||
|
#endif
|
||||||
|
.byte 0x4 # DW_CFA_advance_loc4
|
||||||
|
.4byte .LCFI0-.LFB1
|
||||||
|
.byte 0xe # DW_CFA_def_cfa_offset
|
||||||
|
.uleb128 144
|
||||||
|
.byte 0x4 # DW_CFA_advance_loc4
|
||||||
|
.4byte .LCFI1-.LCFI0
|
||||||
|
.byte 0x11 # DW_CFA_offset_extended_sf
|
||||||
|
.uleb128 0x41
|
||||||
|
.sleb128 -1
|
||||||
|
.align 2
|
||||||
|
.LEFDE1:
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined __ELF__ && defined __linux__
|
||||||
|
.section .note.GNU-stack,"",@progbits
|
||||||
|
#endif
|
||||||
214
.pc/powerpc-ffi-softfloat/src/powerpc/sysv.S
Normal file
214
.pc/powerpc-ffi-softfloat/src/powerpc/sysv.S
Normal file
@@ -0,0 +1,214 @@
|
|||||||
|
/* -----------------------------------------------------------------------
|
||||||
|
sysv.S - Copyright (c) 1998 Geoffrey Keating
|
||||||
|
Copyright (C) 2007 Free Software Foundation, Inc
|
||||||
|
|
||||||
|
PowerPC Assembly glue.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of this software and associated documentation files (the
|
||||||
|
``Software''), to deal in the Software without restriction, including
|
||||||
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included
|
||||||
|
in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
DEALINGS IN THE SOFTWARE.
|
||||||
|
----------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#define LIBFFI_ASM
|
||||||
|
#include <fficonfig.h>
|
||||||
|
#include <ffi.h>
|
||||||
|
#include <powerpc/asm.h>
|
||||||
|
|
||||||
|
#ifndef __powerpc64__
|
||||||
|
.globl ffi_prep_args_SYSV
|
||||||
|
ENTRY(ffi_call_SYSV)
|
||||||
|
.LFB1:
|
||||||
|
/* Save the old stack pointer as AP. */
|
||||||
|
mr %r8,%r1
|
||||||
|
|
||||||
|
.LCFI0:
|
||||||
|
/* Allocate the stack space we need. */
|
||||||
|
stwux %r1,%r1,%r4
|
||||||
|
/* Save registers we use. */
|
||||||
|
mflr %r9
|
||||||
|
stw %r28,-16(%r8)
|
||||||
|
.LCFI1:
|
||||||
|
stw %r29,-12(%r8)
|
||||||
|
.LCFI2:
|
||||||
|
stw %r30, -8(%r8)
|
||||||
|
.LCFI3:
|
||||||
|
stw %r31, -4(%r8)
|
||||||
|
.LCFI4:
|
||||||
|
stw %r9, 4(%r8)
|
||||||
|
.LCFI5:
|
||||||
|
|
||||||
|
/* Save arguments over call... */
|
||||||
|
mr %r31,%r5 /* flags, */
|
||||||
|
mr %r30,%r6 /* rvalue, */
|
||||||
|
mr %r29,%r7 /* function address, */
|
||||||
|
mr %r28,%r8 /* our AP. */
|
||||||
|
.LCFI6:
|
||||||
|
|
||||||
|
/* Call ffi_prep_args_SYSV. */
|
||||||
|
mr %r4,%r1
|
||||||
|
bl ffi_prep_args_SYSV@local
|
||||||
|
|
||||||
|
/* Now do the call. */
|
||||||
|
/* Set up cr1 with bits 4-7 of the flags. */
|
||||||
|
mtcrf 0x40,%r31
|
||||||
|
/* Get the address to call into CTR. */
|
||||||
|
mtctr %r29
|
||||||
|
/* Load all those argument registers. */
|
||||||
|
lwz %r3,-16-(8*4)(%r28)
|
||||||
|
lwz %r4,-16-(7*4)(%r28)
|
||||||
|
lwz %r5,-16-(6*4)(%r28)
|
||||||
|
lwz %r6,-16-(5*4)(%r28)
|
||||||
|
bf- 5,1f
|
||||||
|
nop
|
||||||
|
lwz %r7,-16-(4*4)(%r28)
|
||||||
|
lwz %r8,-16-(3*4)(%r28)
|
||||||
|
lwz %r9,-16-(2*4)(%r28)
|
||||||
|
lwz %r10,-16-(1*4)(%r28)
|
||||||
|
nop
|
||||||
|
1:
|
||||||
|
|
||||||
|
/* Load all the FP registers. */
|
||||||
|
bf- 6,2f
|
||||||
|
lfd %f1,-16-(8*4)-(8*8)(%r28)
|
||||||
|
lfd %f2,-16-(8*4)-(7*8)(%r28)
|
||||||
|
lfd %f3,-16-(8*4)-(6*8)(%r28)
|
||||||
|
lfd %f4,-16-(8*4)-(5*8)(%r28)
|
||||||
|
nop
|
||||||
|
lfd %f5,-16-(8*4)-(4*8)(%r28)
|
||||||
|
lfd %f6,-16-(8*4)-(3*8)(%r28)
|
||||||
|
lfd %f7,-16-(8*4)-(2*8)(%r28)
|
||||||
|
lfd %f8,-16-(8*4)-(1*8)(%r28)
|
||||||
|
2:
|
||||||
|
|
||||||
|
/* Make the call. */
|
||||||
|
bctrl
|
||||||
|
|
||||||
|
/* Now, deal with the return value. */
|
||||||
|
mtcrf 0x01,%r31 /* cr7 */
|
||||||
|
bt- 31,L(small_struct_return_value)
|
||||||
|
bt- 30,L(done_return_value)
|
||||||
|
bt- 29,L(fp_return_value)
|
||||||
|
stw %r3,0(%r30)
|
||||||
|
bf+ 28,L(done_return_value)
|
||||||
|
stw %r4,4(%r30)
|
||||||
|
mtcrf 0x02,%r31 /* cr6 */
|
||||||
|
bf 27,L(done_return_value)
|
||||||
|
stw %r5,8(%r30)
|
||||||
|
stw %r6,12(%r30)
|
||||||
|
/* Fall through... */
|
||||||
|
|
||||||
|
L(done_return_value):
|
||||||
|
/* Restore the registers we used and return. */
|
||||||
|
lwz %r9, 4(%r28)
|
||||||
|
lwz %r31, -4(%r28)
|
||||||
|
mtlr %r9
|
||||||
|
lwz %r30, -8(%r28)
|
||||||
|
lwz %r29,-12(%r28)
|
||||||
|
lwz %r28,-16(%r28)
|
||||||
|
lwz %r1,0(%r1)
|
||||||
|
blr
|
||||||
|
|
||||||
|
L(fp_return_value):
|
||||||
|
bf 28,L(float_return_value)
|
||||||
|
stfd %f1,0(%r30)
|
||||||
|
mtcrf 0x02,%r31 /* cr6 */
|
||||||
|
bf 27,L(done_return_value)
|
||||||
|
stfd %f2,8(%r30)
|
||||||
|
b L(done_return_value)
|
||||||
|
L(float_return_value):
|
||||||
|
stfs %f1,0(%r30)
|
||||||
|
b L(done_return_value)
|
||||||
|
|
||||||
|
L(small_struct_return_value):
|
||||||
|
/*
|
||||||
|
* The C code always allocates a properly-aligned 8-byte bounce
|
||||||
|
* buffer to make this assembly code very simple. Just write out
|
||||||
|
* r3 and r4 to the buffer to allow the C code to handle the rest.
|
||||||
|
*/
|
||||||
|
stw %r3, 0(%r30)
|
||||||
|
stw %r4, 4(%r30)
|
||||||
|
b L(done_return_value)
|
||||||
|
|
||||||
|
.LFE1:
|
||||||
|
END(ffi_call_SYSV)
|
||||||
|
|
||||||
|
.section ".eh_frame",EH_FRAME_FLAGS,@progbits
|
||||||
|
.Lframe1:
|
||||||
|
.4byte .LECIE1-.LSCIE1 /* Length of Common Information Entry */
|
||||||
|
.LSCIE1:
|
||||||
|
.4byte 0x0 /* CIE Identifier Tag */
|
||||||
|
.byte 0x1 /* CIE Version */
|
||||||
|
#if defined _RELOCATABLE || defined __PIC__
|
||||||
|
.ascii "zR\0" /* CIE Augmentation */
|
||||||
|
#else
|
||||||
|
.ascii "\0" /* CIE Augmentation */
|
||||||
|
#endif
|
||||||
|
.uleb128 0x1 /* CIE Code Alignment Factor */
|
||||||
|
.sleb128 -4 /* CIE Data Alignment Factor */
|
||||||
|
.byte 0x41 /* CIE RA Column */
|
||||||
|
#if defined _RELOCATABLE || defined __PIC__
|
||||||
|
.uleb128 0x1 /* Augmentation size */
|
||||||
|
.byte 0x1b /* FDE Encoding (pcrel sdata4) */
|
||||||
|
#endif
|
||||||
|
.byte 0xc /* DW_CFA_def_cfa */
|
||||||
|
.uleb128 0x1
|
||||||
|
.uleb128 0x0
|
||||||
|
.align 2
|
||||||
|
.LECIE1:
|
||||||
|
.LSFDE1:
|
||||||
|
.4byte .LEFDE1-.LASFDE1 /* FDE Length */
|
||||||
|
.LASFDE1:
|
||||||
|
.4byte .LASFDE1-.Lframe1 /* FDE CIE offset */
|
||||||
|
#if defined _RELOCATABLE || defined __PIC__
|
||||||
|
.4byte .LFB1-. /* FDE initial location */
|
||||||
|
#else
|
||||||
|
.4byte .LFB1 /* FDE initial location */
|
||||||
|
#endif
|
||||||
|
.4byte .LFE1-.LFB1 /* FDE address range */
|
||||||
|
#if defined _RELOCATABLE || defined __PIC__
|
||||||
|
.uleb128 0x0 /* Augmentation size */
|
||||||
|
#endif
|
||||||
|
.byte 0x4 /* DW_CFA_advance_loc4 */
|
||||||
|
.4byte .LCFI0-.LFB1
|
||||||
|
.byte 0xd /* DW_CFA_def_cfa_register */
|
||||||
|
.uleb128 0x08
|
||||||
|
.byte 0x4 /* DW_CFA_advance_loc4 */
|
||||||
|
.4byte .LCFI5-.LCFI0
|
||||||
|
.byte 0x11 /* DW_CFA_offset_extended_sf */
|
||||||
|
.uleb128 0x41
|
||||||
|
.sleb128 -1
|
||||||
|
.byte 0x9f /* DW_CFA_offset, column 0x1f */
|
||||||
|
.uleb128 0x1
|
||||||
|
.byte 0x9e /* DW_CFA_offset, column 0x1e */
|
||||||
|
.uleb128 0x2
|
||||||
|
.byte 0x9d /* DW_CFA_offset, column 0x1d */
|
||||||
|
.uleb128 0x3
|
||||||
|
.byte 0x9c /* DW_CFA_offset, column 0x1c */
|
||||||
|
.uleb128 0x4
|
||||||
|
.byte 0x4 /* DW_CFA_advance_loc4 */
|
||||||
|
.4byte .LCFI6-.LCFI5
|
||||||
|
.byte 0xd /* DW_CFA_def_cfa_register */
|
||||||
|
.uleb128 0x1c
|
||||||
|
.align 2
|
||||||
|
.LEFDE1:
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined __ELF__ && defined __linux__
|
||||||
|
.section .note.GNU-stack,"",@progbits
|
||||||
|
#endif
|
||||||
@@ -1,3 +1,9 @@
|
|||||||
|
2011-11-12 Kyle Moffett <Kyle.D.Moffett@boeing.com>
|
||||||
|
|
||||||
|
* src/powerpc/ffi.c, src/powerpc/ffitarget.h,
|
||||||
|
src/powerpc/ppc_closure.S, src/powerpc/sysv.S: Many changes for
|
||||||
|
softfloat powerpc variants.
|
||||||
|
|
||||||
2011-11-12 Petr Salinger <Petr.Salinger@seznam.cz>
|
2011-11-12 Petr Salinger <Petr.Salinger@seznam.cz>
|
||||||
|
|
||||||
* configure.ac (FFI_EXEC_TRAMPOLINE_TABLE): Fix kfreebsd support.
|
* configure.ac (FFI_EXEC_TRAMPOLINE_TABLE): Fix kfreebsd support.
|
||||||
@@ -17,7 +23,7 @@
|
|||||||
2011-11-12 Kimura Wataru <kimuraw@i.nifty.jp>
|
2011-11-12 Kimura Wataru <kimuraw@i.nifty.jp>
|
||||||
|
|
||||||
* m4/ax_enable_builddir: Change from string comparison to numeric
|
* m4/ax_enable_builddir: Change from string comparison to numeric
|
||||||
comparison for wc output.
|
comparison for wc output.
|
||||||
* configure.ac: Enable FFI_MMAP_EXEC_WRIT for darwin11 aka Mac OS
|
* configure.ac: Enable FFI_MMAP_EXEC_WRIT for darwin11 aka Mac OS
|
||||||
X 10.7.
|
X 10.7.
|
||||||
* configure: Rebuilt.
|
* configure: Rebuilt.
|
||||||
|
|||||||
970
patches/powerpc-ffi-softfloat
Normal file
970
patches/powerpc-ffi-softfloat
Normal file
@@ -0,0 +1,970 @@
|
|||||||
|
Index: libffi/ChangeLog
|
||||||
|
===================================================================
|
||||||
|
--- libffi.orig/ChangeLog
|
||||||
|
+++ libffi/ChangeLog
|
||||||
|
@@ -1,3 +1,9 @@
|
||||||
|
+2011-11-12 Kyle Moffett <Kyle.D.Moffett@boeing.com>
|
||||||
|
+
|
||||||
|
+ * src/powerpc/ffi.c, src/powerpc/ffitarget.h,
|
||||||
|
+ src/powerpc/ppc_closure.S, src/powerpc/sysv.S: Many changes for
|
||||||
|
+ softfloat powerpc variants.
|
||||||
|
+
|
||||||
|
2011-11-12 Petr Salinger <Petr.Salinger@seznam.cz>
|
||||||
|
|
||||||
|
* configure.ac (FFI_EXEC_TRAMPOLINE_TABLE): Fix kfreebsd support.
|
||||||
|
@@ -17,7 +23,7 @@
|
||||||
|
2011-11-12 Kimura Wataru <kimuraw@i.nifty.jp>
|
||||||
|
|
||||||
|
* m4/ax_enable_builddir: Change from string comparison to numeric
|
||||||
|
- comparison for wc output.
|
||||||
|
+ comparison for wc output.
|
||||||
|
* configure.ac: Enable FFI_MMAP_EXEC_WRIT for darwin11 aka Mac OS
|
||||||
|
X 10.7.
|
||||||
|
* configure: Rebuilt.
|
||||||
|
Index: libffi/src/powerpc/ffi.c
|
||||||
|
===================================================================
|
||||||
|
--- libffi.orig/src/powerpc/ffi.c
|
||||||
|
+++ libffi/src/powerpc/ffi.c
|
||||||
|
@@ -41,27 +41,28 @@ enum {
|
||||||
|
/* The assembly depends on these exact flags. */
|
||||||
|
FLAG_RETURNS_SMST = 1 << (31-31), /* Used for FFI_SYSV small structs. */
|
||||||
|
FLAG_RETURNS_NOTHING = 1 << (31-30), /* These go in cr7 */
|
||||||
|
+#ifndef __NO_FPRS__
|
||||||
|
FLAG_RETURNS_FP = 1 << (31-29),
|
||||||
|
+#endif
|
||||||
|
FLAG_RETURNS_64BITS = 1 << (31-28),
|
||||||
|
|
||||||
|
FLAG_RETURNS_128BITS = 1 << (31-27), /* cr6 */
|
||||||
|
|
||||||
|
FLAG_ARG_NEEDS_COPY = 1 << (31- 7),
|
||||||
|
+#ifndef __NO_FPRS__
|
||||||
|
FLAG_FP_ARGUMENTS = 1 << (31- 6), /* cr1.eq; specified by ABI */
|
||||||
|
+#endif
|
||||||
|
FLAG_4_GPR_ARGUMENTS = 1 << (31- 5),
|
||||||
|
FLAG_RETVAL_REFERENCE = 1 << (31- 4)
|
||||||
|
};
|
||||||
|
|
||||||
|
/* About the SYSV ABI. */
|
||||||
|
-unsigned int NUM_GPR_ARG_REGISTERS = 8;
|
||||||
|
+#define ASM_NEEDS_REGISTERS 4
|
||||||
|
+#define NUM_GPR_ARG_REGISTERS 8
|
||||||
|
#ifndef __NO_FPRS__
|
||||||
|
-unsigned int NUM_FPR_ARG_REGISTERS = 8;
|
||||||
|
-#else
|
||||||
|
-unsigned int NUM_FPR_ARG_REGISTERS = 0;
|
||||||
|
+# define NUM_FPR_ARG_REGISTERS 8
|
||||||
|
#endif
|
||||||
|
|
||||||
|
-enum { ASM_NEEDS_REGISTERS = 4 };
|
||||||
|
-
|
||||||
|
/* ffi_prep_args_SYSV is called by the assembly routine once stack space
|
||||||
|
has been allocated for the function's arguments.
|
||||||
|
|
||||||
|
@@ -110,10 +111,12 @@ ffi_prep_args_SYSV (extended_cif *ecif,
|
||||||
|
valp gpr_base;
|
||||||
|
int intarg_count;
|
||||||
|
|
||||||
|
+#ifndef __NO_FPRS__
|
||||||
|
/* 'fpr_base' points at the space for fpr1, and grows upwards as
|
||||||
|
we use FPR registers. */
|
||||||
|
valp fpr_base;
|
||||||
|
int fparg_count;
|
||||||
|
+#endif
|
||||||
|
|
||||||
|
/* 'copy_space' grows down as we put structures in it. It should
|
||||||
|
stay 16-byte aligned. */
|
||||||
|
@@ -122,9 +125,8 @@ ffi_prep_args_SYSV (extended_cif *ecif,
|
||||||
|
/* 'next_arg' grows up as we put parameters in it. */
|
||||||
|
valp next_arg;
|
||||||
|
|
||||||
|
- int i, ii MAYBE_UNUSED;
|
||||||
|
+ int i;
|
||||||
|
ffi_type **ptr;
|
||||||
|
- double double_tmp;
|
||||||
|
union {
|
||||||
|
void **v;
|
||||||
|
char **c;
|
||||||
|
@@ -140,15 +142,16 @@ ffi_prep_args_SYSV (extended_cif *ecif,
|
||||||
|
size_t struct_copy_size;
|
||||||
|
unsigned gprvalue;
|
||||||
|
|
||||||
|
- if (ecif->cif->abi == FFI_LINUX_SOFT_FLOAT)
|
||||||
|
- NUM_FPR_ARG_REGISTERS = 0;
|
||||||
|
-
|
||||||
|
stacktop.c = (char *) stack + bytes;
|
||||||
|
gpr_base.u = stacktop.u - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS;
|
||||||
|
intarg_count = 0;
|
||||||
|
+#ifndef __NO_FPRS__
|
||||||
|
fpr_base.d = gpr_base.d - NUM_FPR_ARG_REGISTERS;
|
||||||
|
fparg_count = 0;
|
||||||
|
copy_space.c = ((flags & FLAG_FP_ARGUMENTS) ? fpr_base.c : gpr_base.c);
|
||||||
|
+#else
|
||||||
|
+ copy_space.c = gpr_base.c;
|
||||||
|
+#endif
|
||||||
|
next_arg.u = stack + 2;
|
||||||
|
|
||||||
|
/* Check that everything starts aligned properly. */
|
||||||
|
@@ -171,12 +174,28 @@ ffi_prep_args_SYSV (extended_cif *ecif,
|
||||||
|
i > 0;
|
||||||
|
i--, ptr++, p_argv.v++)
|
||||||
|
{
|
||||||
|
- switch ((*ptr)->type)
|
||||||
|
- {
|
||||||
|
+ unsigned short typenum = (*ptr)->type;
|
||||||
|
+
|
||||||
|
+ /* We may need to handle some values depending on ABI */
|
||||||
|
+ if (ecif->cif->abi == FFI_LINUX_SOFT_FLOAT) {
|
||||||
|
+ if (typenum == FFI_TYPE_FLOAT)
|
||||||
|
+ typenum = FFI_TYPE_UINT32;
|
||||||
|
+ if (typenum == FFI_TYPE_DOUBLE)
|
||||||
|
+ typenum = FFI_TYPE_UINT64;
|
||||||
|
+ if (typenum == FFI_TYPE_LONGDOUBLE)
|
||||||
|
+ typenum = FFI_TYPE_UINT128;
|
||||||
|
+ } else if (ecif->cif->abi != FFI_LINUX) {
|
||||||
|
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||||
|
+ if (typenum == FFI_TYPE_LONGDOUBLE)
|
||||||
|
+ typenum = FFI_TYPE_STRUCT;
|
||||||
|
+#endif
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* Now test the translated value */
|
||||||
|
+ switch (typenum) {
|
||||||
|
+#ifndef __NO_FPRS__
|
||||||
|
case FFI_TYPE_FLOAT:
|
||||||
|
/* With FFI_LINUX_SOFT_FLOAT floats are handled like UINT32. */
|
||||||
|
- if (ecif->cif->abi == FFI_LINUX_SOFT_FLOAT)
|
||||||
|
- goto soft_float_prep;
|
||||||
|
double_tmp = **p_argv.f;
|
||||||
|
if (fparg_count >= NUM_FPR_ARG_REGISTERS)
|
||||||
|
{
|
||||||
|
@@ -215,43 +234,6 @@ ffi_prep_args_SYSV (extended_cif *ecif,
|
||||||
|
|
||||||
|
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||||
|
case FFI_TYPE_LONGDOUBLE:
|
||||||
|
- if ((ecif->cif->abi != FFI_LINUX)
|
||||||
|
- && (ecif->cif->abi != FFI_LINUX_SOFT_FLOAT))
|
||||||
|
- goto do_struct;
|
||||||
|
- /* The soft float ABI for long doubles works like this,
|
||||||
|
- a long double is passed in four consecutive gprs if available.
|
||||||
|
- A maximum of 2 long doubles can be passed in gprs.
|
||||||
|
- If we do not have 4 gprs left, the long double is passed on the
|
||||||
|
- stack, 4-byte aligned. */
|
||||||
|
- if (ecif->cif->abi == FFI_LINUX_SOFT_FLOAT)
|
||||||
|
- {
|
||||||
|
- unsigned int int_tmp = (*p_argv.ui)[0];
|
||||||
|
- if (intarg_count >= NUM_GPR_ARG_REGISTERS - 3)
|
||||||
|
- {
|
||||||
|
- if (intarg_count < NUM_GPR_ARG_REGISTERS)
|
||||||
|
- intarg_count += NUM_GPR_ARG_REGISTERS - intarg_count;
|
||||||
|
- *next_arg.u = int_tmp;
|
||||||
|
- next_arg.u++;
|
||||||
|
- for (ii = 1; ii < 4; ii++)
|
||||||
|
- {
|
||||||
|
- int_tmp = (*p_argv.ui)[ii];
|
||||||
|
- *next_arg.u = int_tmp;
|
||||||
|
- next_arg.u++;
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
- else
|
||||||
|
- {
|
||||||
|
- *gpr_base.u++ = int_tmp;
|
||||||
|
- for (ii = 1; ii < 4; ii++)
|
||||||
|
- {
|
||||||
|
- int_tmp = (*p_argv.ui)[ii];
|
||||||
|
- *gpr_base.u++ = int_tmp;
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
- intarg_count +=4;
|
||||||
|
- }
|
||||||
|
- else
|
||||||
|
- {
|
||||||
|
double_tmp = (*p_argv.d)[0];
|
||||||
|
|
||||||
|
if (fparg_count >= NUM_FPR_ARG_REGISTERS - 1)
|
||||||
|
@@ -277,13 +259,40 @@ ffi_prep_args_SYSV (extended_cif *ecif,
|
||||||
|
|
||||||
|
fparg_count += 2;
|
||||||
|
FFI_ASSERT (flags & FLAG_FP_ARGUMENTS);
|
||||||
|
- }
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
+#endif /* have FPRs */
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * The soft float ABI for long doubles works like this, a long double
|
||||||
|
+ * is passed in four consecutive GPRs if available. A maximum of 2
|
||||||
|
+ * long doubles can be passed in gprs. If we do not have 4 GPRs
|
||||||
|
+ * left, the long double is passed on the stack, 4-byte aligned.
|
||||||
|
+ */
|
||||||
|
+ case FFI_TYPE_UINT128: {
|
||||||
|
+ unsigned int int_tmp = (*p_argv.ui)[0];
|
||||||
|
+ unsigned int ii;
|
||||||
|
+ if (intarg_count >= NUM_GPR_ARG_REGISTERS - 3) {
|
||||||
|
+ if (intarg_count < NUM_GPR_ARG_REGISTERS)
|
||||||
|
+ intarg_count += NUM_GPR_ARG_REGISTERS - intarg_count;
|
||||||
|
+ *(next_arg.u++) = int_tmp;
|
||||||
|
+ for (ii = 1; ii < 4; ii++) {
|
||||||
|
+ int_tmp = (*p_argv.ui)[ii];
|
||||||
|
+ *(next_arg.u++) = int_tmp;
|
||||||
|
+ }
|
||||||
|
+ } else {
|
||||||
|
+ *(gpr_base.u++) = int_tmp;
|
||||||
|
+ for (ii = 1; ii < 4; ii++) {
|
||||||
|
+ int_tmp = (*p_argv.ui)[ii];
|
||||||
|
+ *(gpr_base.u++) = int_tmp;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ intarg_count += 4;
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
case FFI_TYPE_UINT64:
|
||||||
|
case FFI_TYPE_SINT64:
|
||||||
|
- soft_double_prep:
|
||||||
|
if (intarg_count == NUM_GPR_ARG_REGISTERS-1)
|
||||||
|
intarg_count++;
|
||||||
|
if (intarg_count >= NUM_GPR_ARG_REGISTERS)
|
||||||
|
@@ -316,9 +325,6 @@ ffi_prep_args_SYSV (extended_cif *ecif,
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FFI_TYPE_STRUCT:
|
||||||
|
-#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||||
|
- do_struct:
|
||||||
|
-#endif
|
||||||
|
struct_copy_size = ((*ptr)->size + 15) & ~0xF;
|
||||||
|
copy_space.c -= struct_copy_size;
|
||||||
|
memcpy (copy_space.c, *p_argv.c, (*ptr)->size);
|
||||||
|
@@ -346,7 +352,6 @@ ffi_prep_args_SYSV (extended_cif *ecif,
|
||||||
|
case FFI_TYPE_UINT32:
|
||||||
|
case FFI_TYPE_SINT32:
|
||||||
|
case FFI_TYPE_POINTER:
|
||||||
|
- soft_float_prep:
|
||||||
|
|
||||||
|
gprvalue = **p_argv.ui;
|
||||||
|
|
||||||
|
@@ -363,8 +368,10 @@ ffi_prep_args_SYSV (extended_cif *ecif,
|
||||||
|
/* Check that we didn't overrun the stack... */
|
||||||
|
FFI_ASSERT (copy_space.c >= next_arg.c);
|
||||||
|
FFI_ASSERT (gpr_base.u <= stacktop.u - ASM_NEEDS_REGISTERS);
|
||||||
|
+#ifndef __NO_FPRS__
|
||||||
|
FFI_ASSERT (fpr_base.u
|
||||||
|
<= stacktop.u - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS);
|
||||||
|
+#endif
|
||||||
|
FFI_ASSERT (flags & FLAG_4_GPR_ARGUMENTS || intarg_count <= 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -601,9 +608,6 @@ ffi_prep_cif_machdep (ffi_cif *cif)
|
||||||
|
unsigned type = cif->rtype->type;
|
||||||
|
unsigned size = cif->rtype->size;
|
||||||
|
|
||||||
|
- if (cif->abi == FFI_LINUX_SOFT_FLOAT)
|
||||||
|
- NUM_FPR_ARG_REGISTERS = 0;
|
||||||
|
-
|
||||||
|
if (cif->abi != FFI_LINUX64)
|
||||||
|
{
|
||||||
|
/* All the machine-independent calculation of cif->bytes will be wrong.
|
||||||
|
@@ -643,25 +647,38 @@ ffi_prep_cif_machdep (ffi_cif *cif)
|
||||||
|
- Single/double FP values in fpr1, long double in fpr1,fpr2.
|
||||||
|
- soft-float float/doubles are treated as UINT32/UINT64 respectivley.
|
||||||
|
- soft-float long doubles are returned in gpr3-gpr6. */
|
||||||
|
+ /* First translate for softfloat/nonlinux */
|
||||||
|
+ if (cif->abi == FFI_LINUX_SOFT_FLOAT) {
|
||||||
|
+ if (type == FFI_TYPE_FLOAT)
|
||||||
|
+ type = FFI_TYPE_UINT32;
|
||||||
|
+ if (type == FFI_TYPE_DOUBLE)
|
||||||
|
+ type = FFI_TYPE_UINT64;
|
||||||
|
+ if (type == FFI_TYPE_LONGDOUBLE)
|
||||||
|
+ type = FFI_TYPE_UINT128;
|
||||||
|
+ } else if (cif->abi != FFI_LINUX && cif->abi != FFI_LINUX64) {
|
||||||
|
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||||
|
+ if (type == FFI_TYPE_LONGDOUBLE)
|
||||||
|
+ type = FFI_TYPE_STRUCT;
|
||||||
|
+#endif
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
-#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||||
|
+#ifndef __NO_FPRS__
|
||||||
|
case FFI_TYPE_LONGDOUBLE:
|
||||||
|
- if (cif->abi != FFI_LINUX && cif->abi != FFI_LINUX64
|
||||||
|
- && cif->abi != FFI_LINUX_SOFT_FLOAT)
|
||||||
|
- goto byref;
|
||||||
|
flags |= FLAG_RETURNS_128BITS;
|
||||||
|
/* Fall through. */
|
||||||
|
-#endif
|
||||||
|
case FFI_TYPE_DOUBLE:
|
||||||
|
flags |= FLAG_RETURNS_64BITS;
|
||||||
|
/* Fall through. */
|
||||||
|
case FFI_TYPE_FLOAT:
|
||||||
|
- /* With FFI_LINUX_SOFT_FLOAT no fp registers are used. */
|
||||||
|
- if (cif->abi != FFI_LINUX_SOFT_FLOAT)
|
||||||
|
- flags |= FLAG_RETURNS_FP;
|
||||||
|
+ flags |= FLAG_RETURNS_FP;
|
||||||
|
break;
|
||||||
|
+#endif
|
||||||
|
|
||||||
|
+ case FFI_TYPE_UINT128:
|
||||||
|
+ flags |= FLAG_RETURNS_128BITS;
|
||||||
|
+ /* Fall through. */
|
||||||
|
case FFI_TYPE_UINT64:
|
||||||
|
case FFI_TYPE_SINT64:
|
||||||
|
flags |= FLAG_RETURNS_64BITS;
|
||||||
|
@@ -680,10 +697,6 @@ ffi_prep_cif_machdep (ffi_cif *cif)
|
||||||
|
*/
|
||||||
|
if (cif->abi == FFI_SYSV && size <= 8)
|
||||||
|
flags |= FLAG_RETURNS_SMST;
|
||||||
|
-
|
||||||
|
-#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||||
|
- byref:
|
||||||
|
-#endif
|
||||||
|
intarg_count++;
|
||||||
|
flags |= FLAG_RETVAL_REFERENCE;
|
||||||
|
/* Fall through. */
|
||||||
|
@@ -704,39 +717,36 @@ ffi_prep_cif_machdep (ffi_cif *cif)
|
||||||
|
Stuff on the stack needs to keep proper alignment. */
|
||||||
|
for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
|
||||||
|
{
|
||||||
|
- switch ((*ptr)->type)
|
||||||
|
- {
|
||||||
|
+ unsigned short typenum = (*ptr)->type;
|
||||||
|
+
|
||||||
|
+ /* We may need to handle some values depending on ABI */
|
||||||
|
+ if (cif->abi == FFI_LINUX_SOFT_FLOAT) {
|
||||||
|
+ if (typenum == FFI_TYPE_FLOAT)
|
||||||
|
+ typenum = FFI_TYPE_UINT32;
|
||||||
|
+ if (typenum == FFI_TYPE_DOUBLE)
|
||||||
|
+ typenum = FFI_TYPE_UINT64;
|
||||||
|
+ if (typenum == FFI_TYPE_LONGDOUBLE)
|
||||||
|
+ typenum = FFI_TYPE_UINT128;
|
||||||
|
+ } else if (cif->abi != FFI_LINUX && cif->abi != FFI_LINUX64) {
|
||||||
|
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||||
|
+ if (typenum == FFI_TYPE_LONGDOUBLE)
|
||||||
|
+ typenum = FFI_TYPE_STRUCT;
|
||||||
|
+#endif
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ switch (typenum) {
|
||||||
|
+#ifndef __NO_FPRS__
|
||||||
|
case FFI_TYPE_FLOAT:
|
||||||
|
- /* With FFI_LINUX_SOFT_FLOAT floats are handled like UINT32. */
|
||||||
|
- if (cif->abi == FFI_LINUX_SOFT_FLOAT)
|
||||||
|
- goto soft_float_cif;
|
||||||
|
fparg_count++;
|
||||||
|
/* floating singles are not 8-aligned on stack */
|
||||||
|
break;
|
||||||
|
|
||||||
|
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||||
|
case FFI_TYPE_LONGDOUBLE:
|
||||||
|
- if (cif->abi != FFI_LINUX && cif->abi != FFI_LINUX_SOFT_FLOAT)
|
||||||
|
- goto do_struct;
|
||||||
|
- if (cif->abi == FFI_LINUX_SOFT_FLOAT)
|
||||||
|
- {
|
||||||
|
- if (intarg_count >= NUM_GPR_ARG_REGISTERS - 3
|
||||||
|
- || intarg_count < NUM_GPR_ARG_REGISTERS)
|
||||||
|
- /* A long double in FFI_LINUX_SOFT_FLOAT can use only
|
||||||
|
- a set of four consecutive gprs. If we have not enough,
|
||||||
|
- we have to adjust the intarg_count value. */
|
||||||
|
- intarg_count += NUM_GPR_ARG_REGISTERS - intarg_count;
|
||||||
|
- intarg_count += 4;
|
||||||
|
- break;
|
||||||
|
- }
|
||||||
|
- else
|
||||||
|
- fparg_count++;
|
||||||
|
+ fparg_count++;
|
||||||
|
/* Fall thru */
|
||||||
|
#endif
|
||||||
|
case FFI_TYPE_DOUBLE:
|
||||||
|
- /* With FFI_LINUX_SOFT_FLOAT doubles are handled like UINT64. */
|
||||||
|
- if (cif->abi == FFI_LINUX_SOFT_FLOAT)
|
||||||
|
- goto soft_double_cif;
|
||||||
|
fparg_count++;
|
||||||
|
/* If this FP arg is going on the stack, it must be
|
||||||
|
8-byte-aligned. */
|
||||||
|
@@ -745,10 +755,21 @@ ffi_prep_cif_machdep (ffi_cif *cif)
|
||||||
|
&& intarg_count % 2 != 0)
|
||||||
|
intarg_count++;
|
||||||
|
break;
|
||||||
|
+#endif
|
||||||
|
+ case FFI_TYPE_UINT128:
|
||||||
|
+ /*
|
||||||
|
+ * A long double in FFI_LINUX_SOFT_FLOAT can use only a set
|
||||||
|
+ * of four consecutive gprs. If we do not have enough, we
|
||||||
|
+ * have to adjust the intarg_count value.
|
||||||
|
+ */
|
||||||
|
+ if (intarg_count >= NUM_GPR_ARG_REGISTERS - 3
|
||||||
|
+ && intarg_count < NUM_GPR_ARG_REGISTERS)
|
||||||
|
+ intarg_count = NUM_GPR_ARG_REGISTERS;
|
||||||
|
+ intarg_count += 4;
|
||||||
|
+ break;
|
||||||
|
|
||||||
|
case FFI_TYPE_UINT64:
|
||||||
|
case FFI_TYPE_SINT64:
|
||||||
|
- soft_double_cif:
|
||||||
|
/* 'long long' arguments are passed as two words, but
|
||||||
|
either both words must fit in registers or both go
|
||||||
|
on the stack. If they go on the stack, they must
|
||||||
|
@@ -765,9 +786,6 @@ ffi_prep_cif_machdep (ffi_cif *cif)
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FFI_TYPE_STRUCT:
|
||||||
|
-#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||||
|
- do_struct:
|
||||||
|
-#endif
|
||||||
|
/* We must allocate space for a copy of these to enforce
|
||||||
|
pass-by-value. Pad the space up to a multiple of 16
|
||||||
|
bytes (the maximum alignment required for anything under
|
||||||
|
@@ -775,12 +793,20 @@ ffi_prep_cif_machdep (ffi_cif *cif)
|
||||||
|
struct_copy_size += ((*ptr)->size + 15) & ~0xF;
|
||||||
|
/* Fall through (allocate space for the pointer). */
|
||||||
|
|
||||||
|
- default:
|
||||||
|
- soft_float_cif:
|
||||||
|
+ case FFI_TYPE_POINTER:
|
||||||
|
+ case FFI_TYPE_INT:
|
||||||
|
+ case FFI_TYPE_UINT32:
|
||||||
|
+ case FFI_TYPE_SINT32:
|
||||||
|
+ case FFI_TYPE_UINT16:
|
||||||
|
+ case FFI_TYPE_SINT16:
|
||||||
|
+ case FFI_TYPE_UINT8:
|
||||||
|
+ case FFI_TYPE_SINT8:
|
||||||
|
/* Everything else is passed as a 4-byte word in a GPR, either
|
||||||
|
the object itself or a pointer to it. */
|
||||||
|
intarg_count++;
|
||||||
|
break;
|
||||||
|
+ default:
|
||||||
|
+ FFI_ASSERT (0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
@@ -809,16 +835,29 @@ ffi_prep_cif_machdep (ffi_cif *cif)
|
||||||
|
intarg_count += ((*ptr)->size + 7) / 8;
|
||||||
|
break;
|
||||||
|
|
||||||
|
- default:
|
||||||
|
+ case FFI_TYPE_POINTER:
|
||||||
|
+ case FFI_TYPE_UINT64:
|
||||||
|
+ case FFI_TYPE_SINT64:
|
||||||
|
+ case FFI_TYPE_INT:
|
||||||
|
+ case FFI_TYPE_UINT32:
|
||||||
|
+ case FFI_TYPE_SINT32:
|
||||||
|
+ case FFI_TYPE_UINT16:
|
||||||
|
+ case FFI_TYPE_SINT16:
|
||||||
|
+ case FFI_TYPE_UINT8:
|
||||||
|
+ case FFI_TYPE_SINT8:
|
||||||
|
/* Everything else is passed as a 8-byte word in a GPR, either
|
||||||
|
the object itself or a pointer to it. */
|
||||||
|
intarg_count++;
|
||||||
|
break;
|
||||||
|
+ default:
|
||||||
|
+ FFI_ASSERT (0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+#ifndef __NO_FPRS__
|
||||||
|
if (fparg_count != 0)
|
||||||
|
flags |= FLAG_FP_ARGUMENTS;
|
||||||
|
+#endif
|
||||||
|
if (intarg_count > 4)
|
||||||
|
flags |= FLAG_4_GPR_ARGUMENTS;
|
||||||
|
if (struct_copy_size != 0)
|
||||||
|
@@ -826,21 +865,27 @@ ffi_prep_cif_machdep (ffi_cif *cif)
|
||||||
|
|
||||||
|
if (cif->abi != FFI_LINUX64)
|
||||||
|
{
|
||||||
|
+#ifndef __NO_FPRS__
|
||||||
|
/* Space for the FPR registers, if needed. */
|
||||||
|
if (fparg_count != 0)
|
||||||
|
bytes += NUM_FPR_ARG_REGISTERS * sizeof (double);
|
||||||
|
+#endif
|
||||||
|
|
||||||
|
/* Stack space. */
|
||||||
|
if (intarg_count > NUM_GPR_ARG_REGISTERS)
|
||||||
|
bytes += (intarg_count - NUM_GPR_ARG_REGISTERS) * sizeof (int);
|
||||||
|
+#ifndef __NO_FPRS__
|
||||||
|
if (fparg_count > NUM_FPR_ARG_REGISTERS)
|
||||||
|
bytes += (fparg_count - NUM_FPR_ARG_REGISTERS) * sizeof (double);
|
||||||
|
+#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
+#ifndef __NO_FPRS__
|
||||||
|
/* Space for the FPR registers, if needed. */
|
||||||
|
if (fparg_count != 0)
|
||||||
|
bytes += NUM_FPR_ARG_REGISTERS64 * sizeof (double);
|
||||||
|
+#endif
|
||||||
|
|
||||||
|
/* Stack space. */
|
||||||
|
if (intarg_count > NUM_GPR_ARG_REGISTERS64)
|
||||||
|
@@ -898,9 +943,11 @@ ffi_call(ffi_cif *cif, void (*fn)(void),
|
||||||
|
switch (cif->abi)
|
||||||
|
{
|
||||||
|
#ifndef POWERPC64
|
||||||
|
+# ifndef __NO_FPRS__
|
||||||
|
case FFI_SYSV:
|
||||||
|
case FFI_GCC_SYSV:
|
||||||
|
case FFI_LINUX:
|
||||||
|
+# endif
|
||||||
|
case FFI_LINUX_SOFT_FLOAT:
|
||||||
|
ffi_call_SYSV (&ecif, -cif->bytes, cif->flags, ecif.rvalue, fn);
|
||||||
|
break;
|
||||||
|
@@ -1013,32 +1060,38 @@ ffi_closure_helper_SYSV (ffi_closure *cl
|
||||||
|
void ** avalue;
|
||||||
|
ffi_type ** arg_types;
|
||||||
|
long i, avn;
|
||||||
|
- long nf; /* number of floating registers already used */
|
||||||
|
- long ng; /* number of general registers already used */
|
||||||
|
- ffi_cif * cif;
|
||||||
|
- double temp;
|
||||||
|
- unsigned size;
|
||||||
|
+#ifndef __NO_FPRS__
|
||||||
|
+ long nf = 0; /* number of floating registers already used */
|
||||||
|
+#endif
|
||||||
|
+ long ng = 0; /* number of general registers already used */
|
||||||
|
+
|
||||||
|
+ ffi_cif *cif = closure->cif;
|
||||||
|
+ unsigned size = cif->rtype->size;
|
||||||
|
+ unsigned short rtypenum = cif->rtype->type;
|
||||||
|
|
||||||
|
- cif = closure->cif;
|
||||||
|
avalue = alloca (cif->nargs * sizeof (void *));
|
||||||
|
- size = cif->rtype->size;
|
||||||
|
|
||||||
|
- nf = 0;
|
||||||
|
- ng = 0;
|
||||||
|
+ /* First translate for softfloat/nonlinux */
|
||||||
|
+ if (cif->abi == FFI_LINUX_SOFT_FLOAT) {
|
||||||
|
+ if (rtypenum == FFI_TYPE_FLOAT)
|
||||||
|
+ rtypenum = FFI_TYPE_UINT32;
|
||||||
|
+ if (rtypenum == FFI_TYPE_DOUBLE)
|
||||||
|
+ rtypenum = FFI_TYPE_UINT64;
|
||||||
|
+ if (rtypenum == FFI_TYPE_LONGDOUBLE)
|
||||||
|
+ rtypenum = FFI_TYPE_UINT128;
|
||||||
|
+ } else if (cif->abi != FFI_LINUX && cif->abi != FFI_LINUX64) {
|
||||||
|
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||||
|
+ if (rtypenum == FFI_TYPE_LONGDOUBLE)
|
||||||
|
+ rtypenum = FFI_TYPE_STRUCT;
|
||||||
|
+#endif
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
|
||||||
|
/* Copy the caller's structure return value address so that the closure
|
||||||
|
returns the data directly to the caller.
|
||||||
|
For FFI_SYSV the result is passed in r3/r4 if the struct size is less
|
||||||
|
or equal 8 bytes. */
|
||||||
|
-
|
||||||
|
- if ((cif->rtype->type == FFI_TYPE_STRUCT
|
||||||
|
- && !((cif->abi == FFI_SYSV) && (size <= 8)))
|
||||||
|
-#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||||
|
- || (cif->rtype->type == FFI_TYPE_LONGDOUBLE
|
||||||
|
- && cif->abi != FFI_LINUX && cif->abi != FFI_LINUX_SOFT_FLOAT)
|
||||||
|
-#endif
|
||||||
|
- )
|
||||||
|
- {
|
||||||
|
+ if (rtypenum == FFI_TYPE_STRUCT && ((cif->abi != FFI_SYSV) || (size > 8))) {
|
||||||
|
rvalue = (void *) *pgr;
|
||||||
|
ng++;
|
||||||
|
pgr++;
|
||||||
|
@@ -1049,10 +1102,109 @@ ffi_closure_helper_SYSV (ffi_closure *cl
|
||||||
|
arg_types = cif->arg_types;
|
||||||
|
|
||||||
|
/* Grab the addresses of the arguments from the stack frame. */
|
||||||
|
- while (i < avn)
|
||||||
|
- {
|
||||||
|
- switch (arg_types[i]->type)
|
||||||
|
- {
|
||||||
|
+ while (i < avn) {
|
||||||
|
+ unsigned short typenum = arg_types[i]->type;
|
||||||
|
+
|
||||||
|
+ /* We may need to handle some values depending on ABI */
|
||||||
|
+ if (cif->abi == FFI_LINUX_SOFT_FLOAT) {
|
||||||
|
+ if (typenum == FFI_TYPE_FLOAT)
|
||||||
|
+ typenum = FFI_TYPE_UINT32;
|
||||||
|
+ if (typenum == FFI_TYPE_DOUBLE)
|
||||||
|
+ typenum = FFI_TYPE_UINT64;
|
||||||
|
+ if (typenum == FFI_TYPE_LONGDOUBLE)
|
||||||
|
+ typenum = FFI_TYPE_UINT128;
|
||||||
|
+ } else if (cif->abi != FFI_LINUX && cif->abi != FFI_LINUX64) {
|
||||||
|
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||||
|
+ if (typenum == FFI_TYPE_LONGDOUBLE)
|
||||||
|
+ typenum = FFI_TYPE_STRUCT;
|
||||||
|
+#endif
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ switch (typenum) {
|
||||||
|
+#ifndef __NO_FPRS__
|
||||||
|
+ case FFI_TYPE_FLOAT:
|
||||||
|
+ /* unfortunately float values are stored as doubles
|
||||||
|
+ * in the ffi_closure_SYSV code (since we don't check
|
||||||
|
+ * the type in that routine).
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+ /* there are 8 64bit floating point registers */
|
||||||
|
+
|
||||||
|
+ if (nf < 8)
|
||||||
|
+ {
|
||||||
|
+ temp = pfr->d;
|
||||||
|
+ pfr->f = (float) temp;
|
||||||
|
+ avalue[i] = pfr;
|
||||||
|
+ nf++;
|
||||||
|
+ pfr++;
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ /* FIXME? here we are really changing the values
|
||||||
|
+ * stored in the original calling routines outgoing
|
||||||
|
+ * parameter stack. This is probably a really
|
||||||
|
+ * naughty thing to do but...
|
||||||
|
+ */
|
||||||
|
+ avalue[i] = pst;
|
||||||
|
+ pst += 1;
|
||||||
|
+ }
|
||||||
|
+ break;
|
||||||
|
+
|
||||||
|
+ case FFI_TYPE_DOUBLE:
|
||||||
|
+ /* On the outgoing stack all values are aligned to 8 */
|
||||||
|
+ /* there are 8 64bit floating point registers */
|
||||||
|
+
|
||||||
|
+ if (nf < 8)
|
||||||
|
+ {
|
||||||
|
+ avalue[i] = pfr;
|
||||||
|
+ nf++;
|
||||||
|
+ pfr++;
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ if (((long) pst) & 4)
|
||||||
|
+ pst++;
|
||||||
|
+ avalue[i] = pst;
|
||||||
|
+ pst += 2;
|
||||||
|
+ }
|
||||||
|
+ break;
|
||||||
|
+
|
||||||
|
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||||
|
+ case FFI_TYPE_LONGDOUBLE:
|
||||||
|
+ if (nf < 7)
|
||||||
|
+ {
|
||||||
|
+ avalue[i] = pfr;
|
||||||
|
+ pfr += 2;
|
||||||
|
+ nf += 2;
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ if (((long) pst) & 4)
|
||||||
|
+ pst++;
|
||||||
|
+ avalue[i] = pst;
|
||||||
|
+ pst += 4;
|
||||||
|
+ nf = 8;
|
||||||
|
+ }
|
||||||
|
+ break;
|
||||||
|
+#endif
|
||||||
|
+#endif /* have FPRS */
|
||||||
|
+
|
||||||
|
+ case FFI_TYPE_UINT128:
|
||||||
|
+ /*
|
||||||
|
+ * Test if for the whole long double, 4 gprs are available.
|
||||||
|
+ * otherwise the stuff ends up on the stack.
|
||||||
|
+ */
|
||||||
|
+ if (ng < 5) {
|
||||||
|
+ avalue[i] = pgr;
|
||||||
|
+ pgr += 4;
|
||||||
|
+ ng += 4;
|
||||||
|
+ } else {
|
||||||
|
+ avalue[i] = pst;
|
||||||
|
+ pst += 4;
|
||||||
|
+ ng = 8+4;
|
||||||
|
+ }
|
||||||
|
+ break;
|
||||||
|
+
|
||||||
|
case FFI_TYPE_SINT8:
|
||||||
|
case FFI_TYPE_UINT8:
|
||||||
|
/* there are 8 gpr registers used to pass values */
|
||||||
|
@@ -1088,7 +1240,6 @@ ffi_closure_helper_SYSV (ffi_closure *cl
|
||||||
|
case FFI_TYPE_SINT32:
|
||||||
|
case FFI_TYPE_UINT32:
|
||||||
|
case FFI_TYPE_POINTER:
|
||||||
|
- soft_float_closure:
|
||||||
|
/* there are 8 gpr registers used to pass values */
|
||||||
|
if (ng < 8)
|
||||||
|
{
|
||||||
|
@@ -1104,9 +1255,6 @@ ffi_closure_helper_SYSV (ffi_closure *cl
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FFI_TYPE_STRUCT:
|
||||||
|
-#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||||
|
- do_struct:
|
||||||
|
-#endif
|
||||||
|
/* Structs are passed by reference. The address will appear in a
|
||||||
|
gpr if it is one of the first 8 arguments. */
|
||||||
|
if (ng < 8)
|
||||||
|
@@ -1124,7 +1272,6 @@ ffi_closure_helper_SYSV (ffi_closure *cl
|
||||||
|
|
||||||
|
case FFI_TYPE_SINT64:
|
||||||
|
case FFI_TYPE_UINT64:
|
||||||
|
- soft_double_closure:
|
||||||
|
/* passing long long ints are complex, they must
|
||||||
|
* be passed in suitable register pairs such as
|
||||||
|
* (r3,r4) or (r5,r6) or (r6,r7), or (r7,r8) or (r9,r10)
|
||||||
|
@@ -1156,99 +1303,8 @@ ffi_closure_helper_SYSV (ffi_closure *cl
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
- case FFI_TYPE_FLOAT:
|
||||||
|
- /* With FFI_LINUX_SOFT_FLOAT floats are handled like UINT32. */
|
||||||
|
- if (cif->abi == FFI_LINUX_SOFT_FLOAT)
|
||||||
|
- goto soft_float_closure;
|
||||||
|
- /* unfortunately float values are stored as doubles
|
||||||
|
- * in the ffi_closure_SYSV code (since we don't check
|
||||||
|
- * the type in that routine).
|
||||||
|
- */
|
||||||
|
-
|
||||||
|
- /* there are 8 64bit floating point registers */
|
||||||
|
-
|
||||||
|
- if (nf < 8)
|
||||||
|
- {
|
||||||
|
- temp = pfr->d;
|
||||||
|
- pfr->f = (float) temp;
|
||||||
|
- avalue[i] = pfr;
|
||||||
|
- nf++;
|
||||||
|
- pfr++;
|
||||||
|
- }
|
||||||
|
- else
|
||||||
|
- {
|
||||||
|
- /* FIXME? here we are really changing the values
|
||||||
|
- * stored in the original calling routines outgoing
|
||||||
|
- * parameter stack. This is probably a really
|
||||||
|
- * naughty thing to do but...
|
||||||
|
- */
|
||||||
|
- avalue[i] = pst;
|
||||||
|
- pst += 1;
|
||||||
|
- }
|
||||||
|
- break;
|
||||||
|
-
|
||||||
|
- case FFI_TYPE_DOUBLE:
|
||||||
|
- /* With FFI_LINUX_SOFT_FLOAT doubles are handled like UINT64. */
|
||||||
|
- if (cif->abi == FFI_LINUX_SOFT_FLOAT)
|
||||||
|
- goto soft_double_closure;
|
||||||
|
- /* On the outgoing stack all values are aligned to 8 */
|
||||||
|
- /* there are 8 64bit floating point registers */
|
||||||
|
-
|
||||||
|
- if (nf < 8)
|
||||||
|
- {
|
||||||
|
- avalue[i] = pfr;
|
||||||
|
- nf++;
|
||||||
|
- pfr++;
|
||||||
|
- }
|
||||||
|
- else
|
||||||
|
- {
|
||||||
|
- if (((long) pst) & 4)
|
||||||
|
- pst++;
|
||||||
|
- avalue[i] = pst;
|
||||||
|
- pst += 2;
|
||||||
|
- }
|
||||||
|
- break;
|
||||||
|
-
|
||||||
|
-#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||||
|
- case FFI_TYPE_LONGDOUBLE:
|
||||||
|
- if (cif->abi != FFI_LINUX && cif->abi != FFI_LINUX_SOFT_FLOAT)
|
||||||
|
- goto do_struct;
|
||||||
|
- if (cif->abi == FFI_LINUX_SOFT_FLOAT)
|
||||||
|
- { /* Test if for the whole long double, 4 gprs are available.
|
||||||
|
- otherwise the stuff ends up on the stack. */
|
||||||
|
- if (ng < 5)
|
||||||
|
- {
|
||||||
|
- avalue[i] = pgr;
|
||||||
|
- pgr += 4;
|
||||||
|
- ng += 4;
|
||||||
|
- }
|
||||||
|
- else
|
||||||
|
- {
|
||||||
|
- avalue[i] = pst;
|
||||||
|
- pst += 4;
|
||||||
|
- ng = 8;
|
||||||
|
- }
|
||||||
|
- break;
|
||||||
|
- }
|
||||||
|
- if (nf < 7)
|
||||||
|
- {
|
||||||
|
- avalue[i] = pfr;
|
||||||
|
- pfr += 2;
|
||||||
|
- nf += 2;
|
||||||
|
- }
|
||||||
|
- else
|
||||||
|
- {
|
||||||
|
- if (((long) pst) & 4)
|
||||||
|
- pst++;
|
||||||
|
- avalue[i] = pst;
|
||||||
|
- pst += 4;
|
||||||
|
- nf = 8;
|
||||||
|
- }
|
||||||
|
- break;
|
||||||
|
-#endif
|
||||||
|
-
|
||||||
|
default:
|
||||||
|
- FFI_ASSERT (0);
|
||||||
|
+ FFI_ASSERT (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
i++;
|
||||||
|
@@ -1265,39 +1321,9 @@ ffi_closure_helper_SYSV (ffi_closure *cl
|
||||||
|
already used and we never have a struct with size zero. That is the reason
|
||||||
|
for the subtraction of 1. See the comment in ffitarget.h about ordering.
|
||||||
|
*/
|
||||||
|
- if (cif->abi == FFI_SYSV && cif->rtype->type == FFI_TYPE_STRUCT
|
||||||
|
- && size <= 8)
|
||||||
|
+ if (cif->abi == FFI_SYSV && rtypenum == FFI_TYPE_STRUCT && size <= 8)
|
||||||
|
return (FFI_SYSV_TYPE_SMALL_STRUCT - 1) + size;
|
||||||
|
-#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||||
|
- else if (cif->rtype->type == FFI_TYPE_LONGDOUBLE
|
||||||
|
- && cif->abi != FFI_LINUX && cif->abi != FFI_LINUX_SOFT_FLOAT)
|
||||||
|
- return FFI_TYPE_STRUCT;
|
||||||
|
-#endif
|
||||||
|
- /* With FFI_LINUX_SOFT_FLOAT floats and doubles are handled like UINT32
|
||||||
|
- respectivley UINT64. */
|
||||||
|
- if (cif->abi == FFI_LINUX_SOFT_FLOAT)
|
||||||
|
- {
|
||||||
|
- switch (cif->rtype->type)
|
||||||
|
- {
|
||||||
|
- case FFI_TYPE_FLOAT:
|
||||||
|
- return FFI_TYPE_UINT32;
|
||||||
|
- break;
|
||||||
|
- case FFI_TYPE_DOUBLE:
|
||||||
|
- return FFI_TYPE_UINT64;
|
||||||
|
- break;
|
||||||
|
-#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||||
|
- case FFI_TYPE_LONGDOUBLE:
|
||||||
|
- return FFI_TYPE_UINT128;
|
||||||
|
- break;
|
||||||
|
-#endif
|
||||||
|
- default:
|
||||||
|
- return cif->rtype->type;
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
- else
|
||||||
|
- {
|
||||||
|
- return cif->rtype->type;
|
||||||
|
- }
|
||||||
|
+ return rtypenum;
|
||||||
|
}
|
||||||
|
|
||||||
|
int FFI_HIDDEN ffi_closure_helper_LINUX64 (ffi_closure *, void *,
|
||||||
|
Index: libffi/src/powerpc/ffitarget.h
|
||||||
|
===================================================================
|
||||||
|
--- libffi.orig/src/powerpc/ffitarget.h
|
||||||
|
+++ libffi/src/powerpc/ffitarget.h
|
||||||
|
@@ -60,18 +60,14 @@ typedef enum ffi_abi {
|
||||||
|
FFI_LINUX64,
|
||||||
|
FFI_LINUX,
|
||||||
|
FFI_LINUX_SOFT_FLOAT,
|
||||||
|
-# ifdef POWERPC64
|
||||||
|
+# if defined(POWERPC64)
|
||||||
|
FFI_DEFAULT_ABI = FFI_LINUX64,
|
||||||
|
-# else
|
||||||
|
-# if (!defined(__NO_FPRS__) && (__LDBL_MANT_DIG__ == 106))
|
||||||
|
- FFI_DEFAULT_ABI = FFI_LINUX,
|
||||||
|
-# else
|
||||||
|
-# ifdef __NO_FPRS__
|
||||||
|
+# elif defined(__NO_FPRS__)
|
||||||
|
FFI_DEFAULT_ABI = FFI_LINUX_SOFT_FLOAT,
|
||||||
|
-# else
|
||||||
|
+# elif (__LDBL_MANT_DIG__ == 106)
|
||||||
|
+ FFI_DEFAULT_ABI = FFI_LINUX,
|
||||||
|
+# else
|
||||||
|
FFI_DEFAULT_ABI = FFI_GCC_SYSV,
|
||||||
|
-# endif
|
||||||
|
-# endif
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Index: libffi/src/powerpc/ppc_closure.S
|
||||||
|
===================================================================
|
||||||
|
--- libffi.orig/src/powerpc/ppc_closure.S
|
||||||
|
+++ libffi/src/powerpc/ppc_closure.S
|
||||||
|
@@ -122,22 +122,41 @@ ENTRY(ffi_closure_SYSV)
|
||||||
|
blr
|
||||||
|
|
||||||
|
# case FFI_TYPE_FLOAT
|
||||||
|
+#ifndef __NO_FPRS__
|
||||||
|
lfs %f1,112+0(%r1)
|
||||||
|
mtlr %r0
|
||||||
|
addi %r1,%r1,144
|
||||||
|
+#else
|
||||||
|
+ nop
|
||||||
|
+ nop
|
||||||
|
+ nop
|
||||||
|
+#endif
|
||||||
|
blr
|
||||||
|
|
||||||
|
# case FFI_TYPE_DOUBLE
|
||||||
|
+#ifndef __NO_FPRS__
|
||||||
|
lfd %f1,112+0(%r1)
|
||||||
|
mtlr %r0
|
||||||
|
addi %r1,%r1,144
|
||||||
|
+#else
|
||||||
|
+ nop
|
||||||
|
+ nop
|
||||||
|
+ nop
|
||||||
|
+#endif
|
||||||
|
blr
|
||||||
|
|
||||||
|
# case FFI_TYPE_LONGDOUBLE
|
||||||
|
+#ifndef __NO_FPRS__
|
||||||
|
lfd %f1,112+0(%r1)
|
||||||
|
lfd %f2,112+8(%r1)
|
||||||
|
mtlr %r0
|
||||||
|
b .Lfinish
|
||||||
|
+#else
|
||||||
|
+ nop
|
||||||
|
+ nop
|
||||||
|
+ nop
|
||||||
|
+ blr
|
||||||
|
+#endif
|
||||||
|
|
||||||
|
# case FFI_TYPE_UINT8
|
||||||
|
lbz %r3,112+3(%r1)
|
||||||
|
Index: libffi/src/powerpc/sysv.S
|
||||||
|
===================================================================
|
||||||
|
--- libffi.orig/src/powerpc/sysv.S
|
||||||
|
+++ libffi/src/powerpc/sysv.S
|
||||||
|
@@ -83,6 +83,7 @@ ENTRY(ffi_call_SYSV)
|
||||||
|
nop
|
||||||
|
1:
|
||||||
|
|
||||||
|
+#ifndef __NO_FPRS__
|
||||||
|
/* Load all the FP registers. */
|
||||||
|
bf- 6,2f
|
||||||
|
lfd %f1,-16-(8*4)-(8*8)(%r28)
|
||||||
|
@@ -94,6 +95,7 @@ ENTRY(ffi_call_SYSV)
|
||||||
|
lfd %f6,-16-(8*4)-(3*8)(%r28)
|
||||||
|
lfd %f7,-16-(8*4)-(2*8)(%r28)
|
||||||
|
lfd %f8,-16-(8*4)-(1*8)(%r28)
|
||||||
|
+#endif
|
||||||
|
2:
|
||||||
|
|
||||||
|
/* Make the call. */
|
||||||
|
@@ -103,7 +105,9 @@ ENTRY(ffi_call_SYSV)
|
||||||
|
mtcrf 0x01,%r31 /* cr7 */
|
||||||
|
bt- 31,L(small_struct_return_value)
|
||||||
|
bt- 30,L(done_return_value)
|
||||||
|
+#ifndef __NO_FPRS__
|
||||||
|
bt- 29,L(fp_return_value)
|
||||||
|
+#endif
|
||||||
|
stw %r3,0(%r30)
|
||||||
|
bf+ 28,L(done_return_value)
|
||||||
|
stw %r4,4(%r30)
|
||||||
|
@@ -124,6 +128,7 @@ L(done_return_value):
|
||||||
|
lwz %r1,0(%r1)
|
||||||
|
blr
|
||||||
|
|
||||||
|
+#ifndef __NO_FPRS__
|
||||||
|
L(fp_return_value):
|
||||||
|
bf 28,L(float_return_value)
|
||||||
|
stfd %f1,0(%r30)
|
||||||
|
@@ -134,6 +139,7 @@ L(fp_return_value):
|
||||||
|
L(float_return_value):
|
||||||
|
stfs %f1,0(%r30)
|
||||||
|
b L(done_return_value)
|
||||||
|
+#endif
|
||||||
|
|
||||||
|
L(small_struct_return_value):
|
||||||
|
/*
|
||||||
@@ -35,3 +35,4 @@ minix
|
|||||||
|
|
||||||
interix-patch
|
interix-patch
|
||||||
remove-debug-code
|
remove-debug-code
|
||||||
|
powerpc-ffi-softfloat
|
||||||
|
|||||||
@@ -41,27 +41,28 @@ enum {
|
|||||||
/* The assembly depends on these exact flags. */
|
/* The assembly depends on these exact flags. */
|
||||||
FLAG_RETURNS_SMST = 1 << (31-31), /* Used for FFI_SYSV small structs. */
|
FLAG_RETURNS_SMST = 1 << (31-31), /* Used for FFI_SYSV small structs. */
|
||||||
FLAG_RETURNS_NOTHING = 1 << (31-30), /* These go in cr7 */
|
FLAG_RETURNS_NOTHING = 1 << (31-30), /* These go in cr7 */
|
||||||
|
#ifndef __NO_FPRS__
|
||||||
FLAG_RETURNS_FP = 1 << (31-29),
|
FLAG_RETURNS_FP = 1 << (31-29),
|
||||||
|
#endif
|
||||||
FLAG_RETURNS_64BITS = 1 << (31-28),
|
FLAG_RETURNS_64BITS = 1 << (31-28),
|
||||||
|
|
||||||
FLAG_RETURNS_128BITS = 1 << (31-27), /* cr6 */
|
FLAG_RETURNS_128BITS = 1 << (31-27), /* cr6 */
|
||||||
|
|
||||||
FLAG_ARG_NEEDS_COPY = 1 << (31- 7),
|
FLAG_ARG_NEEDS_COPY = 1 << (31- 7),
|
||||||
|
#ifndef __NO_FPRS__
|
||||||
FLAG_FP_ARGUMENTS = 1 << (31- 6), /* cr1.eq; specified by ABI */
|
FLAG_FP_ARGUMENTS = 1 << (31- 6), /* cr1.eq; specified by ABI */
|
||||||
|
#endif
|
||||||
FLAG_4_GPR_ARGUMENTS = 1 << (31- 5),
|
FLAG_4_GPR_ARGUMENTS = 1 << (31- 5),
|
||||||
FLAG_RETVAL_REFERENCE = 1 << (31- 4)
|
FLAG_RETVAL_REFERENCE = 1 << (31- 4)
|
||||||
};
|
};
|
||||||
|
|
||||||
/* About the SYSV ABI. */
|
/* About the SYSV ABI. */
|
||||||
unsigned int NUM_GPR_ARG_REGISTERS = 8;
|
#define ASM_NEEDS_REGISTERS 4
|
||||||
|
#define NUM_GPR_ARG_REGISTERS 8
|
||||||
#ifndef __NO_FPRS__
|
#ifndef __NO_FPRS__
|
||||||
unsigned int NUM_FPR_ARG_REGISTERS = 8;
|
# define NUM_FPR_ARG_REGISTERS 8
|
||||||
#else
|
|
||||||
unsigned int NUM_FPR_ARG_REGISTERS = 0;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
enum { ASM_NEEDS_REGISTERS = 4 };
|
|
||||||
|
|
||||||
/* ffi_prep_args_SYSV is called by the assembly routine once stack space
|
/* ffi_prep_args_SYSV is called by the assembly routine once stack space
|
||||||
has been allocated for the function's arguments.
|
has been allocated for the function's arguments.
|
||||||
|
|
||||||
@@ -110,10 +111,12 @@ ffi_prep_args_SYSV (extended_cif *ecif, unsigned *const stack)
|
|||||||
valp gpr_base;
|
valp gpr_base;
|
||||||
int intarg_count;
|
int intarg_count;
|
||||||
|
|
||||||
|
#ifndef __NO_FPRS__
|
||||||
/* 'fpr_base' points at the space for fpr1, and grows upwards as
|
/* 'fpr_base' points at the space for fpr1, and grows upwards as
|
||||||
we use FPR registers. */
|
we use FPR registers. */
|
||||||
valp fpr_base;
|
valp fpr_base;
|
||||||
int fparg_count;
|
int fparg_count;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* 'copy_space' grows down as we put structures in it. It should
|
/* 'copy_space' grows down as we put structures in it. It should
|
||||||
stay 16-byte aligned. */
|
stay 16-byte aligned. */
|
||||||
@@ -122,9 +125,8 @@ ffi_prep_args_SYSV (extended_cif *ecif, unsigned *const stack)
|
|||||||
/* 'next_arg' grows up as we put parameters in it. */
|
/* 'next_arg' grows up as we put parameters in it. */
|
||||||
valp next_arg;
|
valp next_arg;
|
||||||
|
|
||||||
int i, ii MAYBE_UNUSED;
|
int i;
|
||||||
ffi_type **ptr;
|
ffi_type **ptr;
|
||||||
double double_tmp;
|
|
||||||
union {
|
union {
|
||||||
void **v;
|
void **v;
|
||||||
char **c;
|
char **c;
|
||||||
@@ -140,15 +142,16 @@ ffi_prep_args_SYSV (extended_cif *ecif, unsigned *const stack)
|
|||||||
size_t struct_copy_size;
|
size_t struct_copy_size;
|
||||||
unsigned gprvalue;
|
unsigned gprvalue;
|
||||||
|
|
||||||
if (ecif->cif->abi == FFI_LINUX_SOFT_FLOAT)
|
|
||||||
NUM_FPR_ARG_REGISTERS = 0;
|
|
||||||
|
|
||||||
stacktop.c = (char *) stack + bytes;
|
stacktop.c = (char *) stack + bytes;
|
||||||
gpr_base.u = stacktop.u - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS;
|
gpr_base.u = stacktop.u - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS;
|
||||||
intarg_count = 0;
|
intarg_count = 0;
|
||||||
|
#ifndef __NO_FPRS__
|
||||||
fpr_base.d = gpr_base.d - NUM_FPR_ARG_REGISTERS;
|
fpr_base.d = gpr_base.d - NUM_FPR_ARG_REGISTERS;
|
||||||
fparg_count = 0;
|
fparg_count = 0;
|
||||||
copy_space.c = ((flags & FLAG_FP_ARGUMENTS) ? fpr_base.c : gpr_base.c);
|
copy_space.c = ((flags & FLAG_FP_ARGUMENTS) ? fpr_base.c : gpr_base.c);
|
||||||
|
#else
|
||||||
|
copy_space.c = gpr_base.c;
|
||||||
|
#endif
|
||||||
next_arg.u = stack + 2;
|
next_arg.u = stack + 2;
|
||||||
|
|
||||||
/* Check that everything starts aligned properly. */
|
/* Check that everything starts aligned properly. */
|
||||||
@@ -171,12 +174,28 @@ ffi_prep_args_SYSV (extended_cif *ecif, unsigned *const stack)
|
|||||||
i > 0;
|
i > 0;
|
||||||
i--, ptr++, p_argv.v++)
|
i--, ptr++, p_argv.v++)
|
||||||
{
|
{
|
||||||
switch ((*ptr)->type)
|
unsigned short typenum = (*ptr)->type;
|
||||||
{
|
|
||||||
|
/* We may need to handle some values depending on ABI */
|
||||||
|
if (ecif->cif->abi == FFI_LINUX_SOFT_FLOAT) {
|
||||||
|
if (typenum == FFI_TYPE_FLOAT)
|
||||||
|
typenum = FFI_TYPE_UINT32;
|
||||||
|
if (typenum == FFI_TYPE_DOUBLE)
|
||||||
|
typenum = FFI_TYPE_UINT64;
|
||||||
|
if (typenum == FFI_TYPE_LONGDOUBLE)
|
||||||
|
typenum = FFI_TYPE_UINT128;
|
||||||
|
} else if (ecif->cif->abi != FFI_LINUX) {
|
||||||
|
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||||
|
if (typenum == FFI_TYPE_LONGDOUBLE)
|
||||||
|
typenum = FFI_TYPE_STRUCT;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now test the translated value */
|
||||||
|
switch (typenum) {
|
||||||
|
#ifndef __NO_FPRS__
|
||||||
case FFI_TYPE_FLOAT:
|
case FFI_TYPE_FLOAT:
|
||||||
/* With FFI_LINUX_SOFT_FLOAT floats are handled like UINT32. */
|
/* With FFI_LINUX_SOFT_FLOAT floats are handled like UINT32. */
|
||||||
if (ecif->cif->abi == FFI_LINUX_SOFT_FLOAT)
|
|
||||||
goto soft_float_prep;
|
|
||||||
double_tmp = **p_argv.f;
|
double_tmp = **p_argv.f;
|
||||||
if (fparg_count >= NUM_FPR_ARG_REGISTERS)
|
if (fparg_count >= NUM_FPR_ARG_REGISTERS)
|
||||||
{
|
{
|
||||||
@@ -215,43 +234,6 @@ ffi_prep_args_SYSV (extended_cif *ecif, unsigned *const stack)
|
|||||||
|
|
||||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||||
case FFI_TYPE_LONGDOUBLE:
|
case FFI_TYPE_LONGDOUBLE:
|
||||||
if ((ecif->cif->abi != FFI_LINUX)
|
|
||||||
&& (ecif->cif->abi != FFI_LINUX_SOFT_FLOAT))
|
|
||||||
goto do_struct;
|
|
||||||
/* The soft float ABI for long doubles works like this,
|
|
||||||
a long double is passed in four consecutive gprs if available.
|
|
||||||
A maximum of 2 long doubles can be passed in gprs.
|
|
||||||
If we do not have 4 gprs left, the long double is passed on the
|
|
||||||
stack, 4-byte aligned. */
|
|
||||||
if (ecif->cif->abi == FFI_LINUX_SOFT_FLOAT)
|
|
||||||
{
|
|
||||||
unsigned int int_tmp = (*p_argv.ui)[0];
|
|
||||||
if (intarg_count >= NUM_GPR_ARG_REGISTERS - 3)
|
|
||||||
{
|
|
||||||
if (intarg_count < NUM_GPR_ARG_REGISTERS)
|
|
||||||
intarg_count += NUM_GPR_ARG_REGISTERS - intarg_count;
|
|
||||||
*next_arg.u = int_tmp;
|
|
||||||
next_arg.u++;
|
|
||||||
for (ii = 1; ii < 4; ii++)
|
|
||||||
{
|
|
||||||
int_tmp = (*p_argv.ui)[ii];
|
|
||||||
*next_arg.u = int_tmp;
|
|
||||||
next_arg.u++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
*gpr_base.u++ = int_tmp;
|
|
||||||
for (ii = 1; ii < 4; ii++)
|
|
||||||
{
|
|
||||||
int_tmp = (*p_argv.ui)[ii];
|
|
||||||
*gpr_base.u++ = int_tmp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
intarg_count +=4;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
double_tmp = (*p_argv.d)[0];
|
double_tmp = (*p_argv.d)[0];
|
||||||
|
|
||||||
if (fparg_count >= NUM_FPR_ARG_REGISTERS - 1)
|
if (fparg_count >= NUM_FPR_ARG_REGISTERS - 1)
|
||||||
@@ -277,13 +259,40 @@ ffi_prep_args_SYSV (extended_cif *ecif, unsigned *const stack)
|
|||||||
|
|
||||||
fparg_count += 2;
|
fparg_count += 2;
|
||||||
FFI_ASSERT (flags & FLAG_FP_ARGUMENTS);
|
FFI_ASSERT (flags & FLAG_FP_ARGUMENTS);
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
#endif /* have FPRs */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The soft float ABI for long doubles works like this, a long double
|
||||||
|
* is passed in four consecutive GPRs if available. A maximum of 2
|
||||||
|
* long doubles can be passed in gprs. If we do not have 4 GPRs
|
||||||
|
* left, the long double is passed on the stack, 4-byte aligned.
|
||||||
|
*/
|
||||||
|
case FFI_TYPE_UINT128: {
|
||||||
|
unsigned int int_tmp = (*p_argv.ui)[0];
|
||||||
|
unsigned int ii;
|
||||||
|
if (intarg_count >= NUM_GPR_ARG_REGISTERS - 3) {
|
||||||
|
if (intarg_count < NUM_GPR_ARG_REGISTERS)
|
||||||
|
intarg_count += NUM_GPR_ARG_REGISTERS - intarg_count;
|
||||||
|
*(next_arg.u++) = int_tmp;
|
||||||
|
for (ii = 1; ii < 4; ii++) {
|
||||||
|
int_tmp = (*p_argv.ui)[ii];
|
||||||
|
*(next_arg.u++) = int_tmp;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
*(gpr_base.u++) = int_tmp;
|
||||||
|
for (ii = 1; ii < 4; ii++) {
|
||||||
|
int_tmp = (*p_argv.ui)[ii];
|
||||||
|
*(gpr_base.u++) = int_tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
intarg_count += 4;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case FFI_TYPE_UINT64:
|
case FFI_TYPE_UINT64:
|
||||||
case FFI_TYPE_SINT64:
|
case FFI_TYPE_SINT64:
|
||||||
soft_double_prep:
|
|
||||||
if (intarg_count == NUM_GPR_ARG_REGISTERS-1)
|
if (intarg_count == NUM_GPR_ARG_REGISTERS-1)
|
||||||
intarg_count++;
|
intarg_count++;
|
||||||
if (intarg_count >= NUM_GPR_ARG_REGISTERS)
|
if (intarg_count >= NUM_GPR_ARG_REGISTERS)
|
||||||
@@ -316,9 +325,6 @@ ffi_prep_args_SYSV (extended_cif *ecif, unsigned *const stack)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case FFI_TYPE_STRUCT:
|
case FFI_TYPE_STRUCT:
|
||||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
|
||||||
do_struct:
|
|
||||||
#endif
|
|
||||||
struct_copy_size = ((*ptr)->size + 15) & ~0xF;
|
struct_copy_size = ((*ptr)->size + 15) & ~0xF;
|
||||||
copy_space.c -= struct_copy_size;
|
copy_space.c -= struct_copy_size;
|
||||||
memcpy (copy_space.c, *p_argv.c, (*ptr)->size);
|
memcpy (copy_space.c, *p_argv.c, (*ptr)->size);
|
||||||
@@ -346,7 +352,6 @@ ffi_prep_args_SYSV (extended_cif *ecif, unsigned *const stack)
|
|||||||
case FFI_TYPE_UINT32:
|
case FFI_TYPE_UINT32:
|
||||||
case FFI_TYPE_SINT32:
|
case FFI_TYPE_SINT32:
|
||||||
case FFI_TYPE_POINTER:
|
case FFI_TYPE_POINTER:
|
||||||
soft_float_prep:
|
|
||||||
|
|
||||||
gprvalue = **p_argv.ui;
|
gprvalue = **p_argv.ui;
|
||||||
|
|
||||||
@@ -363,8 +368,10 @@ ffi_prep_args_SYSV (extended_cif *ecif, unsigned *const stack)
|
|||||||
/* Check that we didn't overrun the stack... */
|
/* Check that we didn't overrun the stack... */
|
||||||
FFI_ASSERT (copy_space.c >= next_arg.c);
|
FFI_ASSERT (copy_space.c >= next_arg.c);
|
||||||
FFI_ASSERT (gpr_base.u <= stacktop.u - ASM_NEEDS_REGISTERS);
|
FFI_ASSERT (gpr_base.u <= stacktop.u - ASM_NEEDS_REGISTERS);
|
||||||
|
#ifndef __NO_FPRS__
|
||||||
FFI_ASSERT (fpr_base.u
|
FFI_ASSERT (fpr_base.u
|
||||||
<= stacktop.u - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS);
|
<= stacktop.u - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS);
|
||||||
|
#endif
|
||||||
FFI_ASSERT (flags & FLAG_4_GPR_ARGUMENTS || intarg_count <= 4);
|
FFI_ASSERT (flags & FLAG_4_GPR_ARGUMENTS || intarg_count <= 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -601,9 +608,6 @@ ffi_prep_cif_machdep (ffi_cif *cif)
|
|||||||
unsigned type = cif->rtype->type;
|
unsigned type = cif->rtype->type;
|
||||||
unsigned size = cif->rtype->size;
|
unsigned size = cif->rtype->size;
|
||||||
|
|
||||||
if (cif->abi == FFI_LINUX_SOFT_FLOAT)
|
|
||||||
NUM_FPR_ARG_REGISTERS = 0;
|
|
||||||
|
|
||||||
if (cif->abi != FFI_LINUX64)
|
if (cif->abi != FFI_LINUX64)
|
||||||
{
|
{
|
||||||
/* All the machine-independent calculation of cif->bytes will be wrong.
|
/* All the machine-independent calculation of cif->bytes will be wrong.
|
||||||
@@ -643,25 +647,38 @@ ffi_prep_cif_machdep (ffi_cif *cif)
|
|||||||
- Single/double FP values in fpr1, long double in fpr1,fpr2.
|
- Single/double FP values in fpr1, long double in fpr1,fpr2.
|
||||||
- soft-float float/doubles are treated as UINT32/UINT64 respectivley.
|
- soft-float float/doubles are treated as UINT32/UINT64 respectivley.
|
||||||
- soft-float long doubles are returned in gpr3-gpr6. */
|
- soft-float long doubles are returned in gpr3-gpr6. */
|
||||||
|
/* First translate for softfloat/nonlinux */
|
||||||
|
if (cif->abi == FFI_LINUX_SOFT_FLOAT) {
|
||||||
|
if (type == FFI_TYPE_FLOAT)
|
||||||
|
type = FFI_TYPE_UINT32;
|
||||||
|
if (type == FFI_TYPE_DOUBLE)
|
||||||
|
type = FFI_TYPE_UINT64;
|
||||||
|
if (type == FFI_TYPE_LONGDOUBLE)
|
||||||
|
type = FFI_TYPE_UINT128;
|
||||||
|
} else if (cif->abi != FFI_LINUX && cif->abi != FFI_LINUX64) {
|
||||||
|
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||||
|
if (type == FFI_TYPE_LONGDOUBLE)
|
||||||
|
type = FFI_TYPE_STRUCT;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
#ifndef __NO_FPRS__
|
||||||
case FFI_TYPE_LONGDOUBLE:
|
case FFI_TYPE_LONGDOUBLE:
|
||||||
if (cif->abi != FFI_LINUX && cif->abi != FFI_LINUX64
|
|
||||||
&& cif->abi != FFI_LINUX_SOFT_FLOAT)
|
|
||||||
goto byref;
|
|
||||||
flags |= FLAG_RETURNS_128BITS;
|
flags |= FLAG_RETURNS_128BITS;
|
||||||
/* Fall through. */
|
/* Fall through. */
|
||||||
#endif
|
|
||||||
case FFI_TYPE_DOUBLE:
|
case FFI_TYPE_DOUBLE:
|
||||||
flags |= FLAG_RETURNS_64BITS;
|
flags |= FLAG_RETURNS_64BITS;
|
||||||
/* Fall through. */
|
/* Fall through. */
|
||||||
case FFI_TYPE_FLOAT:
|
case FFI_TYPE_FLOAT:
|
||||||
/* With FFI_LINUX_SOFT_FLOAT no fp registers are used. */
|
flags |= FLAG_RETURNS_FP;
|
||||||
if (cif->abi != FFI_LINUX_SOFT_FLOAT)
|
|
||||||
flags |= FLAG_RETURNS_FP;
|
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
case FFI_TYPE_UINT128:
|
||||||
|
flags |= FLAG_RETURNS_128BITS;
|
||||||
|
/* Fall through. */
|
||||||
case FFI_TYPE_UINT64:
|
case FFI_TYPE_UINT64:
|
||||||
case FFI_TYPE_SINT64:
|
case FFI_TYPE_SINT64:
|
||||||
flags |= FLAG_RETURNS_64BITS;
|
flags |= FLAG_RETURNS_64BITS;
|
||||||
@@ -680,10 +697,6 @@ ffi_prep_cif_machdep (ffi_cif *cif)
|
|||||||
*/
|
*/
|
||||||
if (cif->abi == FFI_SYSV && size <= 8)
|
if (cif->abi == FFI_SYSV && size <= 8)
|
||||||
flags |= FLAG_RETURNS_SMST;
|
flags |= FLAG_RETURNS_SMST;
|
||||||
|
|
||||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
|
||||||
byref:
|
|
||||||
#endif
|
|
||||||
intarg_count++;
|
intarg_count++;
|
||||||
flags |= FLAG_RETVAL_REFERENCE;
|
flags |= FLAG_RETVAL_REFERENCE;
|
||||||
/* Fall through. */
|
/* Fall through. */
|
||||||
@@ -704,39 +717,36 @@ ffi_prep_cif_machdep (ffi_cif *cif)
|
|||||||
Stuff on the stack needs to keep proper alignment. */
|
Stuff on the stack needs to keep proper alignment. */
|
||||||
for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
|
for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
|
||||||
{
|
{
|
||||||
switch ((*ptr)->type)
|
unsigned short typenum = (*ptr)->type;
|
||||||
{
|
|
||||||
|
/* We may need to handle some values depending on ABI */
|
||||||
|
if (cif->abi == FFI_LINUX_SOFT_FLOAT) {
|
||||||
|
if (typenum == FFI_TYPE_FLOAT)
|
||||||
|
typenum = FFI_TYPE_UINT32;
|
||||||
|
if (typenum == FFI_TYPE_DOUBLE)
|
||||||
|
typenum = FFI_TYPE_UINT64;
|
||||||
|
if (typenum == FFI_TYPE_LONGDOUBLE)
|
||||||
|
typenum = FFI_TYPE_UINT128;
|
||||||
|
} else if (cif->abi != FFI_LINUX && cif->abi != FFI_LINUX64) {
|
||||||
|
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||||
|
if (typenum == FFI_TYPE_LONGDOUBLE)
|
||||||
|
typenum = FFI_TYPE_STRUCT;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (typenum) {
|
||||||
|
#ifndef __NO_FPRS__
|
||||||
case FFI_TYPE_FLOAT:
|
case FFI_TYPE_FLOAT:
|
||||||
/* With FFI_LINUX_SOFT_FLOAT floats are handled like UINT32. */
|
|
||||||
if (cif->abi == FFI_LINUX_SOFT_FLOAT)
|
|
||||||
goto soft_float_cif;
|
|
||||||
fparg_count++;
|
fparg_count++;
|
||||||
/* floating singles are not 8-aligned on stack */
|
/* floating singles are not 8-aligned on stack */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||||
case FFI_TYPE_LONGDOUBLE:
|
case FFI_TYPE_LONGDOUBLE:
|
||||||
if (cif->abi != FFI_LINUX && cif->abi != FFI_LINUX_SOFT_FLOAT)
|
fparg_count++;
|
||||||
goto do_struct;
|
|
||||||
if (cif->abi == FFI_LINUX_SOFT_FLOAT)
|
|
||||||
{
|
|
||||||
if (intarg_count >= NUM_GPR_ARG_REGISTERS - 3
|
|
||||||
|| intarg_count < NUM_GPR_ARG_REGISTERS)
|
|
||||||
/* A long double in FFI_LINUX_SOFT_FLOAT can use only
|
|
||||||
a set of four consecutive gprs. If we have not enough,
|
|
||||||
we have to adjust the intarg_count value. */
|
|
||||||
intarg_count += NUM_GPR_ARG_REGISTERS - intarg_count;
|
|
||||||
intarg_count += 4;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
fparg_count++;
|
|
||||||
/* Fall thru */
|
/* Fall thru */
|
||||||
#endif
|
#endif
|
||||||
case FFI_TYPE_DOUBLE:
|
case FFI_TYPE_DOUBLE:
|
||||||
/* With FFI_LINUX_SOFT_FLOAT doubles are handled like UINT64. */
|
|
||||||
if (cif->abi == FFI_LINUX_SOFT_FLOAT)
|
|
||||||
goto soft_double_cif;
|
|
||||||
fparg_count++;
|
fparg_count++;
|
||||||
/* If this FP arg is going on the stack, it must be
|
/* If this FP arg is going on the stack, it must be
|
||||||
8-byte-aligned. */
|
8-byte-aligned. */
|
||||||
@@ -745,10 +755,21 @@ ffi_prep_cif_machdep (ffi_cif *cif)
|
|||||||
&& intarg_count % 2 != 0)
|
&& intarg_count % 2 != 0)
|
||||||
intarg_count++;
|
intarg_count++;
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
|
case FFI_TYPE_UINT128:
|
||||||
|
/*
|
||||||
|
* A long double in FFI_LINUX_SOFT_FLOAT can use only a set
|
||||||
|
* of four consecutive gprs. If we do not have enough, we
|
||||||
|
* have to adjust the intarg_count value.
|
||||||
|
*/
|
||||||
|
if (intarg_count >= NUM_GPR_ARG_REGISTERS - 3
|
||||||
|
&& intarg_count < NUM_GPR_ARG_REGISTERS)
|
||||||
|
intarg_count = NUM_GPR_ARG_REGISTERS;
|
||||||
|
intarg_count += 4;
|
||||||
|
break;
|
||||||
|
|
||||||
case FFI_TYPE_UINT64:
|
case FFI_TYPE_UINT64:
|
||||||
case FFI_TYPE_SINT64:
|
case FFI_TYPE_SINT64:
|
||||||
soft_double_cif:
|
|
||||||
/* 'long long' arguments are passed as two words, but
|
/* 'long long' arguments are passed as two words, but
|
||||||
either both words must fit in registers or both go
|
either both words must fit in registers or both go
|
||||||
on the stack. If they go on the stack, they must
|
on the stack. If they go on the stack, they must
|
||||||
@@ -765,9 +786,6 @@ ffi_prep_cif_machdep (ffi_cif *cif)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case FFI_TYPE_STRUCT:
|
case FFI_TYPE_STRUCT:
|
||||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
|
||||||
do_struct:
|
|
||||||
#endif
|
|
||||||
/* We must allocate space for a copy of these to enforce
|
/* We must allocate space for a copy of these to enforce
|
||||||
pass-by-value. Pad the space up to a multiple of 16
|
pass-by-value. Pad the space up to a multiple of 16
|
||||||
bytes (the maximum alignment required for anything under
|
bytes (the maximum alignment required for anything under
|
||||||
@@ -775,12 +793,20 @@ ffi_prep_cif_machdep (ffi_cif *cif)
|
|||||||
struct_copy_size += ((*ptr)->size + 15) & ~0xF;
|
struct_copy_size += ((*ptr)->size + 15) & ~0xF;
|
||||||
/* Fall through (allocate space for the pointer). */
|
/* Fall through (allocate space for the pointer). */
|
||||||
|
|
||||||
default:
|
case FFI_TYPE_POINTER:
|
||||||
soft_float_cif:
|
case FFI_TYPE_INT:
|
||||||
|
case FFI_TYPE_UINT32:
|
||||||
|
case FFI_TYPE_SINT32:
|
||||||
|
case FFI_TYPE_UINT16:
|
||||||
|
case FFI_TYPE_SINT16:
|
||||||
|
case FFI_TYPE_UINT8:
|
||||||
|
case FFI_TYPE_SINT8:
|
||||||
/* Everything else is passed as a 4-byte word in a GPR, either
|
/* Everything else is passed as a 4-byte word in a GPR, either
|
||||||
the object itself or a pointer to it. */
|
the object itself or a pointer to it. */
|
||||||
intarg_count++;
|
intarg_count++;
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
FFI_ASSERT (0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -809,16 +835,29 @@ ffi_prep_cif_machdep (ffi_cif *cif)
|
|||||||
intarg_count += ((*ptr)->size + 7) / 8;
|
intarg_count += ((*ptr)->size + 7) / 8;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
case FFI_TYPE_POINTER:
|
||||||
|
case FFI_TYPE_UINT64:
|
||||||
|
case FFI_TYPE_SINT64:
|
||||||
|
case FFI_TYPE_INT:
|
||||||
|
case FFI_TYPE_UINT32:
|
||||||
|
case FFI_TYPE_SINT32:
|
||||||
|
case FFI_TYPE_UINT16:
|
||||||
|
case FFI_TYPE_SINT16:
|
||||||
|
case FFI_TYPE_UINT8:
|
||||||
|
case FFI_TYPE_SINT8:
|
||||||
/* Everything else is passed as a 8-byte word in a GPR, either
|
/* Everything else is passed as a 8-byte word in a GPR, either
|
||||||
the object itself or a pointer to it. */
|
the object itself or a pointer to it. */
|
||||||
intarg_count++;
|
intarg_count++;
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
FFI_ASSERT (0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef __NO_FPRS__
|
||||||
if (fparg_count != 0)
|
if (fparg_count != 0)
|
||||||
flags |= FLAG_FP_ARGUMENTS;
|
flags |= FLAG_FP_ARGUMENTS;
|
||||||
|
#endif
|
||||||
if (intarg_count > 4)
|
if (intarg_count > 4)
|
||||||
flags |= FLAG_4_GPR_ARGUMENTS;
|
flags |= FLAG_4_GPR_ARGUMENTS;
|
||||||
if (struct_copy_size != 0)
|
if (struct_copy_size != 0)
|
||||||
@@ -826,21 +865,27 @@ ffi_prep_cif_machdep (ffi_cif *cif)
|
|||||||
|
|
||||||
if (cif->abi != FFI_LINUX64)
|
if (cif->abi != FFI_LINUX64)
|
||||||
{
|
{
|
||||||
|
#ifndef __NO_FPRS__
|
||||||
/* Space for the FPR registers, if needed. */
|
/* Space for the FPR registers, if needed. */
|
||||||
if (fparg_count != 0)
|
if (fparg_count != 0)
|
||||||
bytes += NUM_FPR_ARG_REGISTERS * sizeof (double);
|
bytes += NUM_FPR_ARG_REGISTERS * sizeof (double);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Stack space. */
|
/* Stack space. */
|
||||||
if (intarg_count > NUM_GPR_ARG_REGISTERS)
|
if (intarg_count > NUM_GPR_ARG_REGISTERS)
|
||||||
bytes += (intarg_count - NUM_GPR_ARG_REGISTERS) * sizeof (int);
|
bytes += (intarg_count - NUM_GPR_ARG_REGISTERS) * sizeof (int);
|
||||||
|
#ifndef __NO_FPRS__
|
||||||
if (fparg_count > NUM_FPR_ARG_REGISTERS)
|
if (fparg_count > NUM_FPR_ARG_REGISTERS)
|
||||||
bytes += (fparg_count - NUM_FPR_ARG_REGISTERS) * sizeof (double);
|
bytes += (fparg_count - NUM_FPR_ARG_REGISTERS) * sizeof (double);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
#ifndef __NO_FPRS__
|
||||||
/* Space for the FPR registers, if needed. */
|
/* Space for the FPR registers, if needed. */
|
||||||
if (fparg_count != 0)
|
if (fparg_count != 0)
|
||||||
bytes += NUM_FPR_ARG_REGISTERS64 * sizeof (double);
|
bytes += NUM_FPR_ARG_REGISTERS64 * sizeof (double);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Stack space. */
|
/* Stack space. */
|
||||||
if (intarg_count > NUM_GPR_ARG_REGISTERS64)
|
if (intarg_count > NUM_GPR_ARG_REGISTERS64)
|
||||||
@@ -898,9 +943,11 @@ ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
|
|||||||
switch (cif->abi)
|
switch (cif->abi)
|
||||||
{
|
{
|
||||||
#ifndef POWERPC64
|
#ifndef POWERPC64
|
||||||
|
# ifndef __NO_FPRS__
|
||||||
case FFI_SYSV:
|
case FFI_SYSV:
|
||||||
case FFI_GCC_SYSV:
|
case FFI_GCC_SYSV:
|
||||||
case FFI_LINUX:
|
case FFI_LINUX:
|
||||||
|
# endif
|
||||||
case FFI_LINUX_SOFT_FLOAT:
|
case FFI_LINUX_SOFT_FLOAT:
|
||||||
ffi_call_SYSV (&ecif, -cif->bytes, cif->flags, ecif.rvalue, fn);
|
ffi_call_SYSV (&ecif, -cif->bytes, cif->flags, ecif.rvalue, fn);
|
||||||
break;
|
break;
|
||||||
@@ -1013,32 +1060,38 @@ ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue,
|
|||||||
void ** avalue;
|
void ** avalue;
|
||||||
ffi_type ** arg_types;
|
ffi_type ** arg_types;
|
||||||
long i, avn;
|
long i, avn;
|
||||||
long nf; /* number of floating registers already used */
|
#ifndef __NO_FPRS__
|
||||||
long ng; /* number of general registers already used */
|
long nf = 0; /* number of floating registers already used */
|
||||||
ffi_cif * cif;
|
#endif
|
||||||
double temp;
|
long ng = 0; /* number of general registers already used */
|
||||||
unsigned size;
|
|
||||||
|
ffi_cif *cif = closure->cif;
|
||||||
|
unsigned size = cif->rtype->size;
|
||||||
|
unsigned short rtypenum = cif->rtype->type;
|
||||||
|
|
||||||
cif = closure->cif;
|
|
||||||
avalue = alloca (cif->nargs * sizeof (void *));
|
avalue = alloca (cif->nargs * sizeof (void *));
|
||||||
size = cif->rtype->size;
|
|
||||||
|
|
||||||
nf = 0;
|
/* First translate for softfloat/nonlinux */
|
||||||
ng = 0;
|
if (cif->abi == FFI_LINUX_SOFT_FLOAT) {
|
||||||
|
if (rtypenum == FFI_TYPE_FLOAT)
|
||||||
|
rtypenum = FFI_TYPE_UINT32;
|
||||||
|
if (rtypenum == FFI_TYPE_DOUBLE)
|
||||||
|
rtypenum = FFI_TYPE_UINT64;
|
||||||
|
if (rtypenum == FFI_TYPE_LONGDOUBLE)
|
||||||
|
rtypenum = FFI_TYPE_UINT128;
|
||||||
|
} else if (cif->abi != FFI_LINUX && cif->abi != FFI_LINUX64) {
|
||||||
|
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||||
|
if (rtypenum == FFI_TYPE_LONGDOUBLE)
|
||||||
|
rtypenum = FFI_TYPE_STRUCT;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Copy the caller's structure return value address so that the closure
|
/* Copy the caller's structure return value address so that the closure
|
||||||
returns the data directly to the caller.
|
returns the data directly to the caller.
|
||||||
For FFI_SYSV the result is passed in r3/r4 if the struct size is less
|
For FFI_SYSV the result is passed in r3/r4 if the struct size is less
|
||||||
or equal 8 bytes. */
|
or equal 8 bytes. */
|
||||||
|
if (rtypenum == FFI_TYPE_STRUCT && ((cif->abi != FFI_SYSV) || (size > 8))) {
|
||||||
if ((cif->rtype->type == FFI_TYPE_STRUCT
|
|
||||||
&& !((cif->abi == FFI_SYSV) && (size <= 8)))
|
|
||||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
|
||||||
|| (cif->rtype->type == FFI_TYPE_LONGDOUBLE
|
|
||||||
&& cif->abi != FFI_LINUX && cif->abi != FFI_LINUX_SOFT_FLOAT)
|
|
||||||
#endif
|
|
||||||
)
|
|
||||||
{
|
|
||||||
rvalue = (void *) *pgr;
|
rvalue = (void *) *pgr;
|
||||||
ng++;
|
ng++;
|
||||||
pgr++;
|
pgr++;
|
||||||
@@ -1049,10 +1102,109 @@ ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue,
|
|||||||
arg_types = cif->arg_types;
|
arg_types = cif->arg_types;
|
||||||
|
|
||||||
/* Grab the addresses of the arguments from the stack frame. */
|
/* Grab the addresses of the arguments from the stack frame. */
|
||||||
while (i < avn)
|
while (i < avn) {
|
||||||
{
|
unsigned short typenum = arg_types[i]->type;
|
||||||
switch (arg_types[i]->type)
|
|
||||||
{
|
/* We may need to handle some values depending on ABI */
|
||||||
|
if (cif->abi == FFI_LINUX_SOFT_FLOAT) {
|
||||||
|
if (typenum == FFI_TYPE_FLOAT)
|
||||||
|
typenum = FFI_TYPE_UINT32;
|
||||||
|
if (typenum == FFI_TYPE_DOUBLE)
|
||||||
|
typenum = FFI_TYPE_UINT64;
|
||||||
|
if (typenum == FFI_TYPE_LONGDOUBLE)
|
||||||
|
typenum = FFI_TYPE_UINT128;
|
||||||
|
} else if (cif->abi != FFI_LINUX && cif->abi != FFI_LINUX64) {
|
||||||
|
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||||
|
if (typenum == FFI_TYPE_LONGDOUBLE)
|
||||||
|
typenum = FFI_TYPE_STRUCT;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (typenum) {
|
||||||
|
#ifndef __NO_FPRS__
|
||||||
|
case FFI_TYPE_FLOAT:
|
||||||
|
/* unfortunately float values are stored as doubles
|
||||||
|
* in the ffi_closure_SYSV code (since we don't check
|
||||||
|
* the type in that routine).
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* there are 8 64bit floating point registers */
|
||||||
|
|
||||||
|
if (nf < 8)
|
||||||
|
{
|
||||||
|
temp = pfr->d;
|
||||||
|
pfr->f = (float) temp;
|
||||||
|
avalue[i] = pfr;
|
||||||
|
nf++;
|
||||||
|
pfr++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* FIXME? here we are really changing the values
|
||||||
|
* stored in the original calling routines outgoing
|
||||||
|
* parameter stack. This is probably a really
|
||||||
|
* naughty thing to do but...
|
||||||
|
*/
|
||||||
|
avalue[i] = pst;
|
||||||
|
pst += 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FFI_TYPE_DOUBLE:
|
||||||
|
/* On the outgoing stack all values are aligned to 8 */
|
||||||
|
/* there are 8 64bit floating point registers */
|
||||||
|
|
||||||
|
if (nf < 8)
|
||||||
|
{
|
||||||
|
avalue[i] = pfr;
|
||||||
|
nf++;
|
||||||
|
pfr++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (((long) pst) & 4)
|
||||||
|
pst++;
|
||||||
|
avalue[i] = pst;
|
||||||
|
pst += 2;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||||
|
case FFI_TYPE_LONGDOUBLE:
|
||||||
|
if (nf < 7)
|
||||||
|
{
|
||||||
|
avalue[i] = pfr;
|
||||||
|
pfr += 2;
|
||||||
|
nf += 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (((long) pst) & 4)
|
||||||
|
pst++;
|
||||||
|
avalue[i] = pst;
|
||||||
|
pst += 4;
|
||||||
|
nf = 8;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#endif /* have FPRS */
|
||||||
|
|
||||||
|
case FFI_TYPE_UINT128:
|
||||||
|
/*
|
||||||
|
* Test if for the whole long double, 4 gprs are available.
|
||||||
|
* otherwise the stuff ends up on the stack.
|
||||||
|
*/
|
||||||
|
if (ng < 5) {
|
||||||
|
avalue[i] = pgr;
|
||||||
|
pgr += 4;
|
||||||
|
ng += 4;
|
||||||
|
} else {
|
||||||
|
avalue[i] = pst;
|
||||||
|
pst += 4;
|
||||||
|
ng = 8+4;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case FFI_TYPE_SINT8:
|
case FFI_TYPE_SINT8:
|
||||||
case FFI_TYPE_UINT8:
|
case FFI_TYPE_UINT8:
|
||||||
/* there are 8 gpr registers used to pass values */
|
/* there are 8 gpr registers used to pass values */
|
||||||
@@ -1088,7 +1240,6 @@ ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue,
|
|||||||
case FFI_TYPE_SINT32:
|
case FFI_TYPE_SINT32:
|
||||||
case FFI_TYPE_UINT32:
|
case FFI_TYPE_UINT32:
|
||||||
case FFI_TYPE_POINTER:
|
case FFI_TYPE_POINTER:
|
||||||
soft_float_closure:
|
|
||||||
/* there are 8 gpr registers used to pass values */
|
/* there are 8 gpr registers used to pass values */
|
||||||
if (ng < 8)
|
if (ng < 8)
|
||||||
{
|
{
|
||||||
@@ -1104,9 +1255,6 @@ ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case FFI_TYPE_STRUCT:
|
case FFI_TYPE_STRUCT:
|
||||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
|
||||||
do_struct:
|
|
||||||
#endif
|
|
||||||
/* Structs are passed by reference. The address will appear in a
|
/* Structs are passed by reference. The address will appear in a
|
||||||
gpr if it is one of the first 8 arguments. */
|
gpr if it is one of the first 8 arguments. */
|
||||||
if (ng < 8)
|
if (ng < 8)
|
||||||
@@ -1124,7 +1272,6 @@ ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue,
|
|||||||
|
|
||||||
case FFI_TYPE_SINT64:
|
case FFI_TYPE_SINT64:
|
||||||
case FFI_TYPE_UINT64:
|
case FFI_TYPE_UINT64:
|
||||||
soft_double_closure:
|
|
||||||
/* passing long long ints are complex, they must
|
/* passing long long ints are complex, they must
|
||||||
* be passed in suitable register pairs such as
|
* be passed in suitable register pairs such as
|
||||||
* (r3,r4) or (r5,r6) or (r6,r7), or (r7,r8) or (r9,r10)
|
* (r3,r4) or (r5,r6) or (r6,r7), or (r7,r8) or (r9,r10)
|
||||||
@@ -1156,99 +1303,8 @@ ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FFI_TYPE_FLOAT:
|
|
||||||
/* With FFI_LINUX_SOFT_FLOAT floats are handled like UINT32. */
|
|
||||||
if (cif->abi == FFI_LINUX_SOFT_FLOAT)
|
|
||||||
goto soft_float_closure;
|
|
||||||
/* unfortunately float values are stored as doubles
|
|
||||||
* in the ffi_closure_SYSV code (since we don't check
|
|
||||||
* the type in that routine).
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* there are 8 64bit floating point registers */
|
|
||||||
|
|
||||||
if (nf < 8)
|
|
||||||
{
|
|
||||||
temp = pfr->d;
|
|
||||||
pfr->f = (float) temp;
|
|
||||||
avalue[i] = pfr;
|
|
||||||
nf++;
|
|
||||||
pfr++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* FIXME? here we are really changing the values
|
|
||||||
* stored in the original calling routines outgoing
|
|
||||||
* parameter stack. This is probably a really
|
|
||||||
* naughty thing to do but...
|
|
||||||
*/
|
|
||||||
avalue[i] = pst;
|
|
||||||
pst += 1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FFI_TYPE_DOUBLE:
|
|
||||||
/* With FFI_LINUX_SOFT_FLOAT doubles are handled like UINT64. */
|
|
||||||
if (cif->abi == FFI_LINUX_SOFT_FLOAT)
|
|
||||||
goto soft_double_closure;
|
|
||||||
/* On the outgoing stack all values are aligned to 8 */
|
|
||||||
/* there are 8 64bit floating point registers */
|
|
||||||
|
|
||||||
if (nf < 8)
|
|
||||||
{
|
|
||||||
avalue[i] = pfr;
|
|
||||||
nf++;
|
|
||||||
pfr++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (((long) pst) & 4)
|
|
||||||
pst++;
|
|
||||||
avalue[i] = pst;
|
|
||||||
pst += 2;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
|
||||||
case FFI_TYPE_LONGDOUBLE:
|
|
||||||
if (cif->abi != FFI_LINUX && cif->abi != FFI_LINUX_SOFT_FLOAT)
|
|
||||||
goto do_struct;
|
|
||||||
if (cif->abi == FFI_LINUX_SOFT_FLOAT)
|
|
||||||
{ /* Test if for the whole long double, 4 gprs are available.
|
|
||||||
otherwise the stuff ends up on the stack. */
|
|
||||||
if (ng < 5)
|
|
||||||
{
|
|
||||||
avalue[i] = pgr;
|
|
||||||
pgr += 4;
|
|
||||||
ng += 4;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
avalue[i] = pst;
|
|
||||||
pst += 4;
|
|
||||||
ng = 8;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (nf < 7)
|
|
||||||
{
|
|
||||||
avalue[i] = pfr;
|
|
||||||
pfr += 2;
|
|
||||||
nf += 2;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (((long) pst) & 4)
|
|
||||||
pst++;
|
|
||||||
avalue[i] = pst;
|
|
||||||
pst += 4;
|
|
||||||
nf = 8;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
FFI_ASSERT (0);
|
FFI_ASSERT (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
i++;
|
i++;
|
||||||
@@ -1265,39 +1321,9 @@ ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue,
|
|||||||
already used and we never have a struct with size zero. That is the reason
|
already used and we never have a struct with size zero. That is the reason
|
||||||
for the subtraction of 1. See the comment in ffitarget.h about ordering.
|
for the subtraction of 1. See the comment in ffitarget.h about ordering.
|
||||||
*/
|
*/
|
||||||
if (cif->abi == FFI_SYSV && cif->rtype->type == FFI_TYPE_STRUCT
|
if (cif->abi == FFI_SYSV && rtypenum == FFI_TYPE_STRUCT && size <= 8)
|
||||||
&& size <= 8)
|
|
||||||
return (FFI_SYSV_TYPE_SMALL_STRUCT - 1) + size;
|
return (FFI_SYSV_TYPE_SMALL_STRUCT - 1) + size;
|
||||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
return rtypenum;
|
||||||
else if (cif->rtype->type == FFI_TYPE_LONGDOUBLE
|
|
||||||
&& cif->abi != FFI_LINUX && cif->abi != FFI_LINUX_SOFT_FLOAT)
|
|
||||||
return FFI_TYPE_STRUCT;
|
|
||||||
#endif
|
|
||||||
/* With FFI_LINUX_SOFT_FLOAT floats and doubles are handled like UINT32
|
|
||||||
respectivley UINT64. */
|
|
||||||
if (cif->abi == FFI_LINUX_SOFT_FLOAT)
|
|
||||||
{
|
|
||||||
switch (cif->rtype->type)
|
|
||||||
{
|
|
||||||
case FFI_TYPE_FLOAT:
|
|
||||||
return FFI_TYPE_UINT32;
|
|
||||||
break;
|
|
||||||
case FFI_TYPE_DOUBLE:
|
|
||||||
return FFI_TYPE_UINT64;
|
|
||||||
break;
|
|
||||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
|
||||||
case FFI_TYPE_LONGDOUBLE:
|
|
||||||
return FFI_TYPE_UINT128;
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
default:
|
|
||||||
return cif->rtype->type;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return cif->rtype->type;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int FFI_HIDDEN ffi_closure_helper_LINUX64 (ffi_closure *, void *,
|
int FFI_HIDDEN ffi_closure_helper_LINUX64 (ffi_closure *, void *,
|
||||||
|
|||||||
1444
src/powerpc/ffi.c.orig
Normal file
1444
src/powerpc/ffi.c.orig
Normal file
File diff suppressed because it is too large
Load Diff
12
src/powerpc/ffi.c.rej
Normal file
12
src/powerpc/ffi.c.rej
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
--- src/powerpc/ffi.c
|
||||||
|
+++ src/powerpc/ffi.c
|
||||||
|
@@ -717,9 +734,6 @@
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
-#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||||
|
- byref:
|
||||||
|
-#endif
|
||||||
|
intarg_count++;
|
||||||
|
flags |= FLAG_RETVAL_REFERENCE;
|
||||||
|
/* Fall through. */
|
||||||
@@ -60,18 +60,14 @@ typedef enum ffi_abi {
|
|||||||
FFI_LINUX64,
|
FFI_LINUX64,
|
||||||
FFI_LINUX,
|
FFI_LINUX,
|
||||||
FFI_LINUX_SOFT_FLOAT,
|
FFI_LINUX_SOFT_FLOAT,
|
||||||
# ifdef POWERPC64
|
# if defined(POWERPC64)
|
||||||
FFI_DEFAULT_ABI = FFI_LINUX64,
|
FFI_DEFAULT_ABI = FFI_LINUX64,
|
||||||
# else
|
# elif defined(__NO_FPRS__)
|
||||||
# if (!defined(__NO_FPRS__) && (__LDBL_MANT_DIG__ == 106))
|
|
||||||
FFI_DEFAULT_ABI = FFI_LINUX,
|
|
||||||
# else
|
|
||||||
# ifdef __NO_FPRS__
|
|
||||||
FFI_DEFAULT_ABI = FFI_LINUX_SOFT_FLOAT,
|
FFI_DEFAULT_ABI = FFI_LINUX_SOFT_FLOAT,
|
||||||
# else
|
# elif (__LDBL_MANT_DIG__ == 106)
|
||||||
|
FFI_DEFAULT_ABI = FFI_LINUX,
|
||||||
|
# else
|
||||||
FFI_DEFAULT_ABI = FFI_GCC_SYSV,
|
FFI_DEFAULT_ABI = FFI_GCC_SYSV,
|
||||||
# endif
|
|
||||||
# endif
|
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -122,22 +122,41 @@ ENTRY(ffi_closure_SYSV)
|
|||||||
blr
|
blr
|
||||||
|
|
||||||
# case FFI_TYPE_FLOAT
|
# case FFI_TYPE_FLOAT
|
||||||
|
#ifndef __NO_FPRS__
|
||||||
lfs %f1,112+0(%r1)
|
lfs %f1,112+0(%r1)
|
||||||
mtlr %r0
|
mtlr %r0
|
||||||
addi %r1,%r1,144
|
addi %r1,%r1,144
|
||||||
|
#else
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
#endif
|
||||||
blr
|
blr
|
||||||
|
|
||||||
# case FFI_TYPE_DOUBLE
|
# case FFI_TYPE_DOUBLE
|
||||||
|
#ifndef __NO_FPRS__
|
||||||
lfd %f1,112+0(%r1)
|
lfd %f1,112+0(%r1)
|
||||||
mtlr %r0
|
mtlr %r0
|
||||||
addi %r1,%r1,144
|
addi %r1,%r1,144
|
||||||
|
#else
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
#endif
|
||||||
blr
|
blr
|
||||||
|
|
||||||
# case FFI_TYPE_LONGDOUBLE
|
# case FFI_TYPE_LONGDOUBLE
|
||||||
|
#ifndef __NO_FPRS__
|
||||||
lfd %f1,112+0(%r1)
|
lfd %f1,112+0(%r1)
|
||||||
lfd %f2,112+8(%r1)
|
lfd %f2,112+8(%r1)
|
||||||
mtlr %r0
|
mtlr %r0
|
||||||
b .Lfinish
|
b .Lfinish
|
||||||
|
#else
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
blr
|
||||||
|
#endif
|
||||||
|
|
||||||
# case FFI_TYPE_UINT8
|
# case FFI_TYPE_UINT8
|
||||||
lbz %r3,112+3(%r1)
|
lbz %r3,112+3(%r1)
|
||||||
|
|||||||
@@ -83,6 +83,7 @@ ENTRY(ffi_call_SYSV)
|
|||||||
nop
|
nop
|
||||||
1:
|
1:
|
||||||
|
|
||||||
|
#ifndef __NO_FPRS__
|
||||||
/* Load all the FP registers. */
|
/* Load all the FP registers. */
|
||||||
bf- 6,2f
|
bf- 6,2f
|
||||||
lfd %f1,-16-(8*4)-(8*8)(%r28)
|
lfd %f1,-16-(8*4)-(8*8)(%r28)
|
||||||
@@ -94,6 +95,7 @@ ENTRY(ffi_call_SYSV)
|
|||||||
lfd %f6,-16-(8*4)-(3*8)(%r28)
|
lfd %f6,-16-(8*4)-(3*8)(%r28)
|
||||||
lfd %f7,-16-(8*4)-(2*8)(%r28)
|
lfd %f7,-16-(8*4)-(2*8)(%r28)
|
||||||
lfd %f8,-16-(8*4)-(1*8)(%r28)
|
lfd %f8,-16-(8*4)-(1*8)(%r28)
|
||||||
|
#endif
|
||||||
2:
|
2:
|
||||||
|
|
||||||
/* Make the call. */
|
/* Make the call. */
|
||||||
@@ -103,7 +105,9 @@ ENTRY(ffi_call_SYSV)
|
|||||||
mtcrf 0x01,%r31 /* cr7 */
|
mtcrf 0x01,%r31 /* cr7 */
|
||||||
bt- 31,L(small_struct_return_value)
|
bt- 31,L(small_struct_return_value)
|
||||||
bt- 30,L(done_return_value)
|
bt- 30,L(done_return_value)
|
||||||
|
#ifndef __NO_FPRS__
|
||||||
bt- 29,L(fp_return_value)
|
bt- 29,L(fp_return_value)
|
||||||
|
#endif
|
||||||
stw %r3,0(%r30)
|
stw %r3,0(%r30)
|
||||||
bf+ 28,L(done_return_value)
|
bf+ 28,L(done_return_value)
|
||||||
stw %r4,4(%r30)
|
stw %r4,4(%r30)
|
||||||
@@ -124,6 +128,7 @@ L(done_return_value):
|
|||||||
lwz %r1,0(%r1)
|
lwz %r1,0(%r1)
|
||||||
blr
|
blr
|
||||||
|
|
||||||
|
#ifndef __NO_FPRS__
|
||||||
L(fp_return_value):
|
L(fp_return_value):
|
||||||
bf 28,L(float_return_value)
|
bf 28,L(float_return_value)
|
||||||
stfd %f1,0(%r30)
|
stfd %f1,0(%r30)
|
||||||
@@ -134,6 +139,7 @@ L(fp_return_value):
|
|||||||
L(float_return_value):
|
L(float_return_value):
|
||||||
stfs %f1,0(%r30)
|
stfs %f1,0(%r30)
|
||||||
b L(done_return_value)
|
b L(done_return_value)
|
||||||
|
#endif
|
||||||
|
|
||||||
L(small_struct_return_value):
|
L(small_struct_return_value):
|
||||||
/*
|
/*
|
||||||
|
|||||||
214
src/powerpc/sysv.S.orig
Normal file
214
src/powerpc/sysv.S.orig
Normal file
@@ -0,0 +1,214 @@
|
|||||||
|
/* -----------------------------------------------------------------------
|
||||||
|
sysv.S - Copyright (c) 1998 Geoffrey Keating
|
||||||
|
Copyright (C) 2007 Free Software Foundation, Inc
|
||||||
|
|
||||||
|
PowerPC Assembly glue.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of this software and associated documentation files (the
|
||||||
|
``Software''), to deal in the Software without restriction, including
|
||||||
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included
|
||||||
|
in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
DEALINGS IN THE SOFTWARE.
|
||||||
|
----------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#define LIBFFI_ASM
|
||||||
|
#include <fficonfig.h>
|
||||||
|
#include <ffi.h>
|
||||||
|
#include <powerpc/asm.h>
|
||||||
|
|
||||||
|
#ifndef __powerpc64__
|
||||||
|
.globl ffi_prep_args_SYSV
|
||||||
|
ENTRY(ffi_call_SYSV)
|
||||||
|
.LFB1:
|
||||||
|
/* Save the old stack pointer as AP. */
|
||||||
|
mr %r8,%r1
|
||||||
|
|
||||||
|
.LCFI0:
|
||||||
|
/* Allocate the stack space we need. */
|
||||||
|
stwux %r1,%r1,%r4
|
||||||
|
/* Save registers we use. */
|
||||||
|
mflr %r9
|
||||||
|
stw %r28,-16(%r8)
|
||||||
|
.LCFI1:
|
||||||
|
stw %r29,-12(%r8)
|
||||||
|
.LCFI2:
|
||||||
|
stw %r30, -8(%r8)
|
||||||
|
.LCFI3:
|
||||||
|
stw %r31, -4(%r8)
|
||||||
|
.LCFI4:
|
||||||
|
stw %r9, 4(%r8)
|
||||||
|
.LCFI5:
|
||||||
|
|
||||||
|
/* Save arguments over call... */
|
||||||
|
mr %r31,%r5 /* flags, */
|
||||||
|
mr %r30,%r6 /* rvalue, */
|
||||||
|
mr %r29,%r7 /* function address, */
|
||||||
|
mr %r28,%r8 /* our AP. */
|
||||||
|
.LCFI6:
|
||||||
|
|
||||||
|
/* Call ffi_prep_args_SYSV. */
|
||||||
|
mr %r4,%r1
|
||||||
|
bl ffi_prep_args_SYSV@local
|
||||||
|
|
||||||
|
/* Now do the call. */
|
||||||
|
/* Set up cr1 with bits 4-7 of the flags. */
|
||||||
|
mtcrf 0x40,%r31
|
||||||
|
/* Get the address to call into CTR. */
|
||||||
|
mtctr %r29
|
||||||
|
/* Load all those argument registers. */
|
||||||
|
lwz %r3,-16-(8*4)(%r28)
|
||||||
|
lwz %r4,-16-(7*4)(%r28)
|
||||||
|
lwz %r5,-16-(6*4)(%r28)
|
||||||
|
lwz %r6,-16-(5*4)(%r28)
|
||||||
|
bf- 5,1f
|
||||||
|
nop
|
||||||
|
lwz %r7,-16-(4*4)(%r28)
|
||||||
|
lwz %r8,-16-(3*4)(%r28)
|
||||||
|
lwz %r9,-16-(2*4)(%r28)
|
||||||
|
lwz %r10,-16-(1*4)(%r28)
|
||||||
|
nop
|
||||||
|
1:
|
||||||
|
|
||||||
|
/* Load all the FP registers. */
|
||||||
|
bf- 6,2f
|
||||||
|
lfd %f1,-16-(8*4)-(8*8)(%r28)
|
||||||
|
lfd %f2,-16-(8*4)-(7*8)(%r28)
|
||||||
|
lfd %f3,-16-(8*4)-(6*8)(%r28)
|
||||||
|
lfd %f4,-16-(8*4)-(5*8)(%r28)
|
||||||
|
nop
|
||||||
|
lfd %f5,-16-(8*4)-(4*8)(%r28)
|
||||||
|
lfd %f6,-16-(8*4)-(3*8)(%r28)
|
||||||
|
lfd %f7,-16-(8*4)-(2*8)(%r28)
|
||||||
|
lfd %f8,-16-(8*4)-(1*8)(%r28)
|
||||||
|
2:
|
||||||
|
|
||||||
|
/* Make the call. */
|
||||||
|
bctrl
|
||||||
|
|
||||||
|
/* Now, deal with the return value. */
|
||||||
|
mtcrf 0x01,%r31 /* cr7 */
|
||||||
|
bt- 31,L(small_struct_return_value)
|
||||||
|
bt- 30,L(done_return_value)
|
||||||
|
bt- 29,L(fp_return_value)
|
||||||
|
stw %r3,0(%r30)
|
||||||
|
bf+ 28,L(done_return_value)
|
||||||
|
stw %r4,4(%r30)
|
||||||
|
mtcrf 0x02,%r31 /* cr6 */
|
||||||
|
bf 27,L(done_return_value)
|
||||||
|
stw %r5,8(%r30)
|
||||||
|
stw %r6,12(%r30)
|
||||||
|
/* Fall through... */
|
||||||
|
|
||||||
|
L(done_return_value):
|
||||||
|
/* Restore the registers we used and return. */
|
||||||
|
lwz %r9, 4(%r28)
|
||||||
|
lwz %r31, -4(%r28)
|
||||||
|
mtlr %r9
|
||||||
|
lwz %r30, -8(%r28)
|
||||||
|
lwz %r29,-12(%r28)
|
||||||
|
lwz %r28,-16(%r28)
|
||||||
|
lwz %r1,0(%r1)
|
||||||
|
blr
|
||||||
|
|
||||||
|
L(fp_return_value):
|
||||||
|
bf 28,L(float_return_value)
|
||||||
|
stfd %f1,0(%r30)
|
||||||
|
mtcrf 0x02,%r31 /* cr6 */
|
||||||
|
bf 27,L(done_return_value)
|
||||||
|
stfd %f2,8(%r30)
|
||||||
|
b L(done_return_value)
|
||||||
|
L(float_return_value):
|
||||||
|
stfs %f1,0(%r30)
|
||||||
|
b L(done_return_value)
|
||||||
|
|
||||||
|
L(small_struct_return_value):
|
||||||
|
/*
|
||||||
|
* The C code always allocates a properly-aligned 8-byte bounce
|
||||||
|
* buffer to make this assembly code very simple. Just write out
|
||||||
|
* r3 and r4 to the buffer to allow the C code to handle the rest.
|
||||||
|
*/
|
||||||
|
stw %r3, 0(%r30)
|
||||||
|
stw %r4, 4(%r30)
|
||||||
|
b L(done_return_value)
|
||||||
|
|
||||||
|
.LFE1:
|
||||||
|
END(ffi_call_SYSV)
|
||||||
|
|
||||||
|
.section ".eh_frame",EH_FRAME_FLAGS,@progbits
|
||||||
|
.Lframe1:
|
||||||
|
.4byte .LECIE1-.LSCIE1 /* Length of Common Information Entry */
|
||||||
|
.LSCIE1:
|
||||||
|
.4byte 0x0 /* CIE Identifier Tag */
|
||||||
|
.byte 0x1 /* CIE Version */
|
||||||
|
#if defined _RELOCATABLE || defined __PIC__
|
||||||
|
.ascii "zR\0" /* CIE Augmentation */
|
||||||
|
#else
|
||||||
|
.ascii "\0" /* CIE Augmentation */
|
||||||
|
#endif
|
||||||
|
.uleb128 0x1 /* CIE Code Alignment Factor */
|
||||||
|
.sleb128 -4 /* CIE Data Alignment Factor */
|
||||||
|
.byte 0x41 /* CIE RA Column */
|
||||||
|
#if defined _RELOCATABLE || defined __PIC__
|
||||||
|
.uleb128 0x1 /* Augmentation size */
|
||||||
|
.byte 0x1b /* FDE Encoding (pcrel sdata4) */
|
||||||
|
#endif
|
||||||
|
.byte 0xc /* DW_CFA_def_cfa */
|
||||||
|
.uleb128 0x1
|
||||||
|
.uleb128 0x0
|
||||||
|
.align 2
|
||||||
|
.LECIE1:
|
||||||
|
.LSFDE1:
|
||||||
|
.4byte .LEFDE1-.LASFDE1 /* FDE Length */
|
||||||
|
.LASFDE1:
|
||||||
|
.4byte .LASFDE1-.Lframe1 /* FDE CIE offset */
|
||||||
|
#if defined _RELOCATABLE || defined __PIC__
|
||||||
|
.4byte .LFB1-. /* FDE initial location */
|
||||||
|
#else
|
||||||
|
.4byte .LFB1 /* FDE initial location */
|
||||||
|
#endif
|
||||||
|
.4byte .LFE1-.LFB1 /* FDE address range */
|
||||||
|
#if defined _RELOCATABLE || defined __PIC__
|
||||||
|
.uleb128 0x0 /* Augmentation size */
|
||||||
|
#endif
|
||||||
|
.byte 0x4 /* DW_CFA_advance_loc4 */
|
||||||
|
.4byte .LCFI0-.LFB1
|
||||||
|
.byte 0xd /* DW_CFA_def_cfa_register */
|
||||||
|
.uleb128 0x08
|
||||||
|
.byte 0x4 /* DW_CFA_advance_loc4 */
|
||||||
|
.4byte .LCFI5-.LCFI0
|
||||||
|
.byte 0x11 /* DW_CFA_offset_extended_sf */
|
||||||
|
.uleb128 0x41
|
||||||
|
.sleb128 -1
|
||||||
|
.byte 0x9f /* DW_CFA_offset, column 0x1f */
|
||||||
|
.uleb128 0x1
|
||||||
|
.byte 0x9e /* DW_CFA_offset, column 0x1e */
|
||||||
|
.uleb128 0x2
|
||||||
|
.byte 0x9d /* DW_CFA_offset, column 0x1d */
|
||||||
|
.uleb128 0x3
|
||||||
|
.byte 0x9c /* DW_CFA_offset, column 0x1c */
|
||||||
|
.uleb128 0x4
|
||||||
|
.byte 0x4 /* DW_CFA_advance_loc4 */
|
||||||
|
.4byte .LCFI6-.LCFI5
|
||||||
|
.byte 0xd /* DW_CFA_def_cfa_register */
|
||||||
|
.uleb128 0x1c
|
||||||
|
.align 2
|
||||||
|
.LEFDE1:
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined __ELF__ && defined __linux__
|
||||||
|
.section .note.GNU-stack,"",@progbits
|
||||||
|
#endif
|
||||||
Reference in New Issue
Block a user