Add powerpc soft float support
This commit is contained in:
@@ -34,3 +34,4 @@ kfreebsd-mmap
|
||||
minix
|
||||
interix-patch
|
||||
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>
|
||||
|
||||
* configure.ac (FFI_EXEC_TRAMPOLINE_TABLE): Fix kfreebsd support.
|
||||
|
||||
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
|
||||
remove-debug-code
|
||||
powerpc-ffi-softfloat
|
||||
|
||||
@@ -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, unsigned *const stack)
|
||||
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, unsigned *const stack)
|
||||
/* '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, unsigned *const stack)
|
||||
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, unsigned *const stack)
|
||||
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, unsigned *const stack)
|
||||
|
||||
#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, unsigned *const stack)
|
||||
|
||||
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, unsigned *const stack)
|
||||
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, unsigned *const stack)
|
||||
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, unsigned *const stack)
|
||||
/* 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;
|
||||
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++;
|
||||
/* 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), void *rvalue, void **avalue)
|
||||
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 *closure, void *rvalue,
|
||||
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 *closure, void *rvalue,
|
||||
arg_types = cif->arg_types;
|
||||
|
||||
/* Grab the addresses of the arguments from the stack frame. */
|
||||
while (i < avn)
|
||||
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)
|
||||
{
|
||||
switch (arg_types[i]->type)
|
||||
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 *closure, void *rvalue,
|
||||
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 *closure, void *rvalue,
|
||||
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 *closure, void *rvalue,
|
||||
|
||||
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,97 +1303,6 @@ ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue,
|
||||
}
|
||||
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);
|
||||
}
|
||||
@@ -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
|
||||
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 *,
|
||||
|
||||
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,20 +60,16 @@ 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))
|
||||
# elif defined(__NO_FPRS__)
|
||||
FFI_DEFAULT_ABI = FFI_LINUX_SOFT_FLOAT,
|
||||
# elif (__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,
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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):
|
||||
/*
|
||||
|
||||
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