diff options
author | Matthias Benkard <code@mail.matthias.benkard.de> | 2008-03-03 21:39:37 +0100 |
---|---|---|
committer | Matthias Benkard <code@mail.matthias.benkard.de> | 2008-03-03 21:39:37 +0100 |
commit | cd11ae061b002913740483529e31b3f6d3da753d (patch) | |
tree | a6d84df9a4a8ed53476aa079a7202fdec69f4d98 /libffi/src/powerpc | |
parent | b2342735e543f8fec2f6914d5e628391dd0ffc46 (diff) |
Update libffi to 3.0.4.
darcs-hash:d0cdf89441c98da668f268b1af91e536dc3ed76e
Diffstat (limited to 'libffi/src/powerpc')
-rw-r--r-- | libffi/src/powerpc/aix.S | 225 | ||||
-rw-r--r-- | libffi/src/powerpc/aix_closure.S | 247 | ||||
-rw-r--r-- | libffi/src/powerpc/asm.h | 128 | ||||
-rw-r--r-- | libffi/src/powerpc/darwin.S | 225 | ||||
-rw-r--r-- | libffi/src/powerpc/darwin_closure.S | 306 | ||||
-rw-r--r-- | libffi/src/powerpc/ffi.c | 1133 | ||||
-rw-r--r-- | libffi/src/powerpc/ffi_darwin.c | 704 | ||||
-rw-r--r-- | libffi/src/powerpc/ffitarget.h | 91 | ||||
-rw-r--r-- | libffi/src/powerpc/linux64.S | 176 | ||||
-rw-r--r-- | libffi/src/powerpc/linux64_closure.S | 205 | ||||
-rw-r--r-- | libffi/src/powerpc/ppc_closure.S | 250 | ||||
-rw-r--r-- | libffi/src/powerpc/sysv.S | 191 |
12 files changed, 0 insertions, 3881 deletions
diff --git a/libffi/src/powerpc/aix.S b/libffi/src/powerpc/aix.S deleted file mode 100644 index 590717f..0000000 --- a/libffi/src/powerpc/aix.S +++ /dev/null @@ -1,225 +0,0 @@ -/* ----------------------------------------------------------------------- - aix.S - Copyright (c) 2002 Free Software Foundation, Inc. - based on darwin.S by John Hornkvist - - 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 AUTHOR 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. - ----------------------------------------------------------------------- */ - - .set r0,0 - .set r1,1 - .set r2,2 - .set r3,3 - .set r4,4 - .set r5,5 - .set r6,6 - .set r7,7 - .set r8,8 - .set r9,9 - .set r10,10 - .set r11,11 - .set r12,12 - .set r13,13 - .set r14,14 - .set r15,15 - .set r16,16 - .set r17,17 - .set r18,18 - .set r19,19 - .set r20,20 - .set r21,21 - .set r22,22 - .set r23,23 - .set r24,24 - .set r25,25 - .set r26,26 - .set r27,27 - .set r28,28 - .set r29,29 - .set r30,30 - .set r31,31 - .set f0,0 - .set f1,1 - .set f2,2 - .set f3,3 - .set f4,4 - .set f5,5 - .set f6,6 - .set f7,7 - .set f8,8 - .set f9,9 - .set f10,10 - .set f11,11 - .set f12,12 - .set f13,13 - .set f14,14 - .set f15,15 - .set f16,16 - .set f17,17 - .set f18,18 - .set f19,19 - .set f20,20 - .set f21,21 - -#define LIBFFI_ASM -#include <fficonfig.h> -#include <ffi.h> -#define JUMPTARGET(name) name -#define L(x) x - .file "aix.S" - .toc - .csect .text[PR] - .align 2 -.globl ffi_prep_args - -.csect .text[PR] - .align 2 - .globl ffi_call_AIX - .globl .ffi_call_AIX -.csect ffi_call_AIX[DS] -ffi_call_AIX: - .long .ffi_call_AIX, TOC[tc0], 0 - .csect .text[PR] -.ffi_call_AIX: - mr r12,r8 // We only need r12 until the call, so it doesn't have to be saved... - /* Save the old stack pointer as AP. */ - mr r8,r1 - - /* Allocate the stack space we need. */ - stwux r1,r1,r4 - - /* Save registers we use. */ - mflr r9 - - stw r28,-16(r8) - stw r29,-12(r8) - stw r30, -8(r8) - stw r31, -4(r8) - - stw r9, 8(r8) - stw r2, 20(r1) - - /* Save arguments over call... */ - mr r31,r5 /* flags, */ - mr r30,r6 /* rvalue, */ - mr r29,r7 /* function address, */ - mr r28,r8 /* our AP. */ - - /* Call ffi_prep_args. */ - mr r4,r1 - li r9,0 - - lwz r2,4(r12) - lwz r12,0(r12) - mtctr r12 // r12 holds address of _ffi_prep_args - bctrl - lwz r2,20(r1) - - /* Now do the call. */ - lwz r12,0(r29) - /* Set up cr1 with bits 4-7 of the flags. */ - mtcrf 0x40,r31 - stw r2,20(r1) - mtctr r12 - lwz r2,4(r29) - /* Load all those argument registers. */ - // We have set up a nice stack frame, just load it into registers. - lwz r3, 20+(1*4)(r1) - lwz r4, 20+(2*4)(r1) - lwz r5, 20+(3*4)(r1) - lwz r6, 20+(4*4)(r1) - nop - lwz r7, 20+(5*4)(r1) - lwz r8, 20+(6*4)(r1) - lwz r9, 20+(7*4)(r1) - lwz r10,20+(8*4)(r1) - -L1: - /* Load all the FP registers. */ - bf 6,L2 // 2f + 0x18 - lfd f1,-16-(13*8)(r28) - lfd f2,-16-(12*8)(r28) - lfd f3,-16-(11*8)(r28) - lfd f4,-16-(10*8)(r28) - nop - lfd f5,-16-(9*8)(r28) - lfd f6,-16-(8*8)(r28) - lfd f7,-16-(7*8)(r28) - lfd f8,-16-(6*8)(r28) - nop - lfd f9,-16-(5*8)(r28) - lfd f10,-16-(4*8)(r28) - lfd f11,-16-(3*8)(r28) - lfd f12,-16-(2*8)(r28) - nop - lfd f13,-16-(1*8)(r28) - -L2: - /* Make the call. */ - bctrl - lwz r2,20(r1) - - /* Now, deal with the return value. */ - mtcrf 0x01,r31 - - 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) - - /* Fall through... */ - -L(done_return_value): - /* Restore the registers we used and return. */ - lwz r9, 8(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) - b L(done_return_value) -L(float_return_value): - stfs f1,0(r30) - b L(done_return_value) - .long 0 - .byte 0,0,0,1,128,4,0,0 -//END(ffi_call_AIX) - -.csect .text[PR] - .align 2 - .globl ffi_call_DARWIN - .globl .ffi_call_DARWIN -.csect ffi_call_DARWIN[DS] -ffi_call_DARWIN: - .long .ffi_call_DARWIN, TOC[tc0], 0 - .csect .text[PR] -.ffi_call_DARWIN: - blr - .long 0 - .byte 0,0,0,0,0,0,0,0 -//END(ffi_call_DARWIN) diff --git a/libffi/src/powerpc/aix_closure.S b/libffi/src/powerpc/aix_closure.S deleted file mode 100644 index 8a26121..0000000 --- a/libffi/src/powerpc/aix_closure.S +++ /dev/null @@ -1,247 +0,0 @@ -/* ----------------------------------------------------------------------- - aix_closure.S - Copyright (c) 2002 2003 Free Software Foundation, Inc. - based on darwin_closure.S - - 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 AUTHOR 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. - ----------------------------------------------------------------------- */ - - .set r0,0 - .set r1,1 - .set r2,2 - .set r3,3 - .set r4,4 - .set r5,5 - .set r6,6 - .set r7,7 - .set r8,8 - .set r9,9 - .set r10,10 - .set r11,11 - .set r12,12 - .set r13,13 - .set r14,14 - .set r15,15 - .set r16,16 - .set r17,17 - .set r18,18 - .set r19,19 - .set r20,20 - .set r21,21 - .set r22,22 - .set r23,23 - .set r24,24 - .set r25,25 - .set r26,26 - .set r27,27 - .set r28,28 - .set r29,29 - .set r30,30 - .set r31,31 - .set f0,0 - .set f1,1 - .set f2,2 - .set f3,3 - .set f4,4 - .set f5,5 - .set f6,6 - .set f7,7 - .set f8,8 - .set f9,9 - .set f10,10 - .set f11,11 - .set f12,12 - .set f13,13 - .set f14,14 - .set f15,15 - .set f16,16 - .set f17,17 - .set f18,18 - .set f19,19 - .set f20,20 - .set f21,21 - -#define LIBFFI_ASM -#define JUMPTARGET(name) name -#define L(x) x - .file "aix_closure.S" - .toc -LC..60: - .tc L..60[TC],L..60 - .csect .text[PR] - .align 2 - -.csect .text[PR] - .align 2 - .globl ffi_closure_ASM - .globl .ffi_closure_ASM -.csect ffi_closure_ASM[DS] - -ffi_closure_ASM: - .long .ffi_closure_ASM, TOC[tc0], 0 - .csect .text[PR] -.ffi_closure_ASM: - - mflr r0 /* extract return address */ - stw r0, 8(r1) /* save the return address */ - - /* 24 Bytes (Linkage Area) */ - /* 32 Bytes (params) */ - /* 104 Bytes (13*8 from FPR) */ - /* 8 Bytes (result) */ - /* 168 Bytes */ - - stwu r1,-176(r1) /* skip over caller save area - keep stack aligned to 16 */ - -/* we want to build up an area for the parameters passed */ -/* in registers (both floating point and integer) */ - - /* we store gpr 3 to gpr 10 (aligned to 4) - in the parents outgoing area */ - stw r3, 200(r1) - stw r4, 204(r1) - stw r5, 208(r1) - stw r6, 212(r1) - stw r7, 216(r1) - stw r8, 220(r1) - stw r9, 224(r1) - stw r10, 228(r1) - - /* next save fpr 1 to fpr 13 (aligned to 8) */ - stfd f1, 56(r1) - stfd f2, 64(r1) - stfd f3, 72(r1) - stfd f4, 80(r1) - stfd f5, 88(r1) - stfd f6, 96(r1) - stfd f7, 104(r1) - stfd f8, 112(r1) - stfd f9, 120(r1) - stfd f10, 128(r1) - stfd f11, 136(r1) - stfd f12, 144(r1) - stfd f13, 152(r1) - - /* 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,160 - - /* now load up the pointer to the saved gpr registers */ - addi r5,r1,200 - - /* now load up the pointer to the saved fpr registers */ - addi r6,r1,56 - - /* make the call */ - bl .ffi_closure_helper_DARWIN - nop - - /* 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 */ - addi r5,r1,160 /* get pointer to results area */ - lwz r4,LC..60(2) /* get address of jump table */ - slwi r3,r3,2 /* now multiply return type by 4 */ - lwzx r3,r4,r3 /* get the contents of that table value */ - add r3,r3,r4 /* add contents of table to table address */ - mtctr r3 - bctr /* jump to it */ - -L..60: - .long L..44-L..60 /* FFI_TYPE_VOID */ - .long L..50-L..60 /* FFI_TYPE_INT */ - .long L..47-L..60 /* FFI_TYPE_FLOAT */ - .long L..46-L..60 /* FFI_TYPE_DOUBLE */ - .long L..46-L..60 /* FFI_TYPE_LONGDOUBLE */ - .long L..56-L..60 /* FFI_TYPE_UINT8 */ - .long L..55-L..60 /* FFI_TYPE_SINT8 */ - .long L..58-L..60 /* FFI_TYPE_UINT16 */ - .long L..57-L..60 /* FFI_TYPE_SINT16 */ - .long L..50-L..60 /* FFI_TYPE_UINT32 */ - .long L..50-L..60 /* FFI_TYPE_SINT32 */ - .long L..48-L..60 /* FFI_TYPE_UINT64 */ - .long L..48-L..60 /* FFI_TYPE_SINT64 */ - .long L..44-L..60 /* FFI_TYPE_STRUCT */ - .long L..50-L..60 /* FFI_TYPE_POINTER */ - - -/* case double */ -L..46: - lfd f1,0(r5) - b L..44 - -/* case float */ -L..47: - lfs f1,0(r5) - b L..44 - -/* case long long */ -L..48: - lwz r3,0(r5) - lwz r4,4(r5) - b L..44 - -/* case default / int32 / pointer */ -L..50: - lwz r3,0(r5) - b L..44 - -/* case signed int8 */ -L..55: - addi r5,r5,3 - lbz r3,0(r5) - slwi r3,r3,24 - srawi r3,r3,24 - b L..44 - -/* case unsigned int8 */ -L..56: - addi r5,r5,3 - lbz r3,0(r5) - b L..44 - -/* case signed int16 */ -L..57: - addi r5,r5,2 - lhz r3,0(r5) - extsh r3,r3 - b L..44 - -/* case unsigned int16 */ -L..58: - addi r5,r5,2 - lhz r3,0(r5) - -/* case void / done */ -L..44: - addi r1,r1,176 /* restore stack pointer */ - lwz r0,8(r1) /* get return address */ - mtlr r0 /* reset link register */ - blr - -/* END(ffi_closure_ASM) */ diff --git a/libffi/src/powerpc/asm.h b/libffi/src/powerpc/asm.h deleted file mode 100644 index 2ccdc02..0000000 --- a/libffi/src/powerpc/asm.h +++ /dev/null @@ -1,128 +0,0 @@ -/* ----------------------------------------------------------------------- - asm.h - Copyright (c) 1998 Geoffrey Keating - - PowerPC Assembly glue. - - $Id: asm.h,v 1.1.1.1 1998/11/29 16:48:16 green Exp $ - - 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 AUTHOR 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 ASM_GLOBAL_DIRECTIVE .globl - - -#define C_SYMBOL_NAME(name) name -/* Macro for a label. */ -#ifdef __STDC__ -#define C_LABEL(name) name##: -#else -#define C_LABEL(name) name/**/: -#endif - -/* This seems to always be the case on PPC. */ -#define ALIGNARG(log2) log2 -/* For ELF we need the `.type' directive to make shared libs work right. */ -#define ASM_TYPE_DIRECTIVE(name,typearg) .type name,typearg; -#define ASM_SIZE_DIRECTIVE(name) .size name,.-name - -/* If compiled for profiling, call `_mcount' at the start of each function. */ -#ifdef PROF -/* The mcount code relies on a the return address being on the stack - to locate our caller and so it can restore it; so store one just - for its benefit. */ -#ifdef PIC -#define CALL_MCOUNT \ - .pushsection; \ - .section ".data"; \ - .align ALIGNARG(2); \ -0:.long 0; \ - .previous; \ - mflr %r0; \ - stw %r0,4(%r1); \ - bl _GLOBAL_OFFSET_TABLE_@local-4; \ - mflr %r11; \ - lwz %r0,0b@got(%r11); \ - bl JUMPTARGET(_mcount); -#else /* PIC */ -#define CALL_MCOUNT \ - .section ".data"; \ - .align ALIGNARG(2); \ -0:.long 0; \ - .previous; \ - mflr %r0; \ - lis %r11,0b@ha; \ - stw %r0,4(%r1); \ - addi %r0,%r11,0b@l; \ - bl JUMPTARGET(_mcount); -#endif /* PIC */ -#else /* PROF */ -#define CALL_MCOUNT /* Do nothing. */ -#endif /* PROF */ - -#define ENTRY(name) \ - ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(name); \ - ASM_TYPE_DIRECTIVE (C_SYMBOL_NAME(name),@function) \ - .align ALIGNARG(2); \ - C_LABEL(name) \ - CALL_MCOUNT - -#define EALIGN_W_0 /* No words to insert. */ -#define EALIGN_W_1 nop -#define EALIGN_W_2 nop;nop -#define EALIGN_W_3 nop;nop;nop -#define EALIGN_W_4 EALIGN_W_3;nop -#define EALIGN_W_5 EALIGN_W_4;nop -#define EALIGN_W_6 EALIGN_W_5;nop -#define EALIGN_W_7 EALIGN_W_6;nop - -/* EALIGN is like ENTRY, but does alignment to 'words'*4 bytes - past a 2^align boundary. */ -#ifdef PROF -#define EALIGN(name, alignt, words) \ - ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(name); \ - ASM_TYPE_DIRECTIVE (C_SYMBOL_NAME(name),@function) \ - .align ALIGNARG(2); \ - C_LABEL(name) \ - CALL_MCOUNT \ - b 0f; \ - .align ALIGNARG(alignt); \ - EALIGN_W_##words; \ - 0: -#else /* PROF */ -#define EALIGN(name, alignt, words) \ - ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(name); \ - ASM_TYPE_DIRECTIVE (C_SYMBOL_NAME(name),@function) \ - .align ALIGNARG(alignt); \ - EALIGN_W_##words; \ - C_LABEL(name) -#endif - -#define END(name) \ - ASM_SIZE_DIRECTIVE(name) - -#ifdef PIC -#define JUMPTARGET(name) name##@plt -#else -#define JUMPTARGET(name) name -#endif - -/* Local labels stripped out by the linker. */ -#define L(x) .L##x - diff --git a/libffi/src/powerpc/darwin.S b/libffi/src/powerpc/darwin.S deleted file mode 100644 index 2233d8a..0000000 --- a/libffi/src/powerpc/darwin.S +++ /dev/null @@ -1,225 +0,0 @@ -#ifdef __ppc__ -/* ----------------------------------------------------------------------- - darwin.S - Copyright (c) 2000 John Hornkvist - - 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 AUTHOR 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> -#define JUMPTARGET(name) name -#define L(x) x -.text - .align 2 -.globl _ffi_prep_args - -.text - .align 2 -.globl _ffi_call_DARWIN -.text - .align 2 -_ffi_call_DARWIN: -LFB0: - mr r12,r8 /* We only need r12 until the call, - so it doesn't have to be saved... */ -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) - stw r29,-12(r8) - stw r30, -8(r8) - stw r31, -4(r8) - - stw r9, 8(r8) - stw r2, 20(r1) -LCFI1: - - /* Save arguments over call... */ - mr r31,r5 /* flags, */ - mr r30,r6 /* rvalue, */ - mr r29,r7 /* function address, */ - mr r28,r8 /* our AP. */ -LCFI2: - /* Call ffi_prep_args. */ - mr r4,r1 - li r9,0 - - mtctr r12 // r12 holds address of _ffi_prep_args - bctrl - lwz r2,20(r1) - - /* 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. - We have set up a nice stack frame, just load it into registers. */ - lwz r3, 20+(1*4)(r1) - lwz r4, 20+(2*4)(r1) - lwz r5, 20+(3*4)(r1) - lwz r6, 20+(4*4)(r1) - nop - lwz r7, 20+(5*4)(r1) - lwz r8, 20+(6*4)(r1) - lwz r9, 20+(7*4)(r1) - lwz r10,20+(8*4)(r1) - -L1: - /* Load all the FP registers. */ - bf 6,L2 // 2f + 0x18 - lfd f1,-16-(13*8)(r28) - lfd f2,-16-(12*8)(r28) - lfd f3,-16-(11*8)(r28) - lfd f4,-16-(10*8)(r28) - nop - lfd f5,-16-(9*8)(r28) - lfd f6,-16-(8*8)(r28) - lfd f7,-16-(7*8)(r28) - lfd f8,-16-(6*8)(r28) - nop - lfd f9,-16-(5*8)(r28) - lfd f10,-16-(4*8)(r28) - lfd f11,-16-(3*8)(r28) - lfd f12,-16-(2*8)(r28) - nop - lfd f13,-16-(1*8)(r28) - -L2: - mr r12,r29 /* Put the target address in r12 as specified. */ - mtctr r12 - nop - nop - /* Make the call. */ - bctrl - - /* Now, deal with the return value. */ - mtcrf 0x01,r31 - - 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) - - /* Fall through... */ - -L(done_return_value): - /* Restore the registers we used and return. */ - lwz r9, 8(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) - b L(done_return_value) -L(float_return_value): - stfs f1,0(r30) - b L(done_return_value) -LFE1: -/* END(_ffi_call_DARWIN) */ - -/* Provide a null definition of _ffi_call_AIX. */ -.text - .align 2 -.globl _ffi_call_AIX -.text - .align 2 -_ffi_call_AIX: - blr -/* END(_ffi_call_AIX) */ - -.data -.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms -EH_frame1: - .set L$set$0,LECIE1-LSCIE1 - .long L$set$0 ; Length of Common Information Entry -LSCIE1: - .long 0x0 ; CIE Identifier Tag - .byte 0x1 ; CIE Version - .ascii "zR\0" ; CIE Augmentation - .byte 0x1 ; uleb128 0x1; CIE Code Alignment Factor - .byte 0x7c ; sleb128 -4; CIE Data Alignment Factor - .byte 0x41 ; CIE RA Column - .byte 0x1 ; uleb128 0x1; Augmentation size - .byte 0x90 ; FDE Encoding (indirect pcrel) - .byte 0xc ; DW_CFA_def_cfa - .byte 0x1 ; uleb128 0x1 - .byte 0x0 ; uleb128 0x0 - .align 2 -LECIE1: -.globl _ffi_call_DARWIN.eh -_ffi_call_DARWIN.eh: -LSFDE1: - .set L$set$1,LEFDE1-LASFDE1 - .long L$set$1 ; FDE Length -LASFDE1: - .long LASFDE1-EH_frame1 ; FDE CIE offset - .long LLFB0$non_lazy_ptr-. ; FDE initial location - .set L$set$3,LFE1-LFB0 - .long L$set$3 ; FDE address range - .byte 0x0 ; uleb128 0x0; Augmentation size - .byte 0x4 ; DW_CFA_advance_loc4 - .set L$set$4,LCFI0-LFB1 - .long L$set$4 - .byte 0xd ; DW_CFA_def_cfa_register - .byte 0x08 ; uleb128 0x08 - .byte 0x4 ; DW_CFA_advance_loc4 - .set L$set$5,LCFI1-LCFI0 - .long L$set$5 - .byte 0x11 ; DW_CFA_offset_extended_sf - .byte 0x41 ; uleb128 0x41 - .byte 0x7e ; sleb128 -2 - .byte 0x9f ; DW_CFA_offset, column 0x1f - .byte 0x1 ; uleb128 0x1 - .byte 0x9e ; DW_CFA_offset, column 0x1e - .byte 0x2 ; uleb128 0x2 - .byte 0x9d ; DW_CFA_offset, column 0x1d - .byte 0x3 ; uleb128 0x3 - .byte 0x9c ; DW_CFA_offset, column 0x1c - .byte 0x4 ; uleb128 0x4 - .byte 0x4 ; DW_CFA_advance_loc4 - .set L$set$6,LCFI2-LCFI1 - .long L$set$6 - .byte 0xd ; DW_CFA_def_cfa_register - .byte 0x1c ; uleb128 0x1c - .align 2 -LEFDE1: -.data - .align 2 -LLFB0$non_lazy_ptr: - .long LFB0 -#endif diff --git a/libffi/src/powerpc/darwin_closure.S b/libffi/src/powerpc/darwin_closure.S deleted file mode 100644 index 317172c..0000000 --- a/libffi/src/powerpc/darwin_closure.S +++ /dev/null @@ -1,306 +0,0 @@ -#ifdef __ppc__ -/* ----------------------------------------------------------------------- - darwin_closure.S - Copyright (c) 2002 2003 Free Software Foundation, - Inc. based on ppc_closure.S - - 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 AUTHOR 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 -#define L(x) x - - .file "darwin_closure.S" -.text - .align 2 -.globl _ffi_closure_ASM - -.text - .align 2 -_ffi_closure_ASM: -LFB1: - mflr r0 /* extract return address */ - stw r0, 8(r1) /* save the return address */ -LCFI0: - /* 24 Bytes (Linkage Area) - 32 Bytes (outgoing parameter area, always reserved) - 104 Bytes (13*8 from FPR) - 8 Bytes (result) - 168 Bytes */ - - stwu r1,-176(r1) /* skip over caller save area - keep stack aligned to 16. */ -LCFI1: - /* We want to build up an area for the parameters passed - in registers. (both floating point and integer) */ - - /* We store gpr 3 to gpr 10 (aligned to 4) - in the parents outgoing area. */ - stw r3, 200(r1) - stw r4, 204(r1) - stw r5, 208(r1) - stw r6, 212(r1) - stw r7, 216(r1) - stw r8, 220(r1) - stw r9, 224(r1) - stw r10, 228(r1) - - /* We save fpr 1 to fpr 13. (aligned to 8) */ - stfd f1, 56(r1) - stfd f2, 64(r1) - stfd f3, 72(r1) - stfd f4, 80(r1) - stfd f5, 88(r1) - stfd f6, 96(r1) - stfd f7, 104(r1) - stfd f8, 112(r1) - stfd f9, 120(r1) - stfd f10, 128(r1) - stfd f11, 136(r1) - stfd f12, 144(r1) - stfd f13, 152(r1) - - /* 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,160 - - /* Now load up the pointer to the saved gpr registers. */ - addi r5,r1,200 - - /* Now load up the pointer to the saved fpr registers. */ - addi r6,r1,56 - - /* Make the call. */ - bl Lffi_closure_helper_DARWIN$stub - - /* 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. */ - addi r5,r1,160 /* Get pointer to results area. */ - bl Lget_ret_type0_addr /* Get pointer to Lret_type0 into LR. */ - mflr r4 /* Move to r4. */ - slwi r3,r3,4 /* Now multiply return type by 16. */ - 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 - - nop - nop - nop -Lget_ret_type0_addr: - blrl - -/* case FFI_TYPE_VOID */ -Lret_type0: - b Lfinish - nop - nop - nop - -/* case FFI_TYPE_INT */ -Lret_type1: - lwz r3,0(r5) - b Lfinish - nop - nop - -/* case FFI_TYPE_FLOAT */ -Lret_type2: - lfs f1,0(r5) - b Lfinish - nop - nop - -/* case FFI_TYPE_DOUBLE */ -Lret_type3: - lfd f1,0(r5) - b Lfinish - nop - nop - -/* case FFI_TYPE_LONGDOUBLE */ -Lret_type4: - lfd f1,0(r5) - b Lfinish - nop - nop - -/* case FFI_TYPE_UINT8 */ -Lret_type5: - lbz r3,3(r5) - b Lfinish - nop - nop - -/* case FFI_TYPE_SINT8 */ -Lret_type6: - lbz r3,3(r5) - extsb r3,r3 - b Lfinish - nop - -/* case FFI_TYPE_UINT16 */ -Lret_type7: - lhz r3,2(r5) - b Lfinish - nop - nop - -/* case FFI_TYPE_SINT16 */ -Lret_type8: - lha r3,2(r5) - b Lfinish - nop - nop - -/* case FFI_TYPE_UINT32 */ -Lret_type9: - lwz r3,0(r5) - b Lfinish - nop - nop - -/* case FFI_TYPE_SINT32 */ -Lret_type10: - lwz r3,0(r5) - b Lfinish - nop - nop - -/* case FFI_TYPE_UINT64 */ -Lret_type11: - lwz r3,0(r5) - lwz r4,4(r5) - b Lfinish - nop - -/* case FFI_TYPE_SINT64 */ -Lret_type12: - lwz r3,0(r5) - lwz r4,4(r5) - b Lfinish - nop - -/* case FFI_TYPE_STRUCT */ -Lret_type13: - b Lfinish - nop - nop - nop - -/* case FFI_TYPE_POINTER */ -Lret_type14: - lwz r3,0(r5) - b Lfinish - nop - nop - -/* case done */ -Lfinish: - addi r1,r1,176 /* Restore stack pointer. */ - lwz r0,8(r1) /* Get return address. */ - mtlr r0 /* Reset link register. */ - blr - -/* END(ffi_closure_ASM) */ - -.data -.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms -EH_frame1: - .set L$set$0,LECIE1-LSCIE1 - .long L$set$0 ; Length of Common Information Entry -LSCIE1: - .long 0x0 ; CIE Identifier Tag - .byte 0x1 ; CIE Version - .ascii "zR\0" ; CIE Augmentation - .byte 0x1 ; uleb128 0x1; CIE Code Alignment Factor - .byte 0x7c ; sleb128 -4; CIE Data Alignment Factor - .byte 0x41 ; CIE RA Column - .byte 0x1 ; uleb128 0x1; Augmentation size - .byte 0x90 ; FDE Encoding (indirect pcrel) - .byte 0xc ; DW_CFA_def_cfa - .byte 0x1 ; uleb128 0x1 - .byte 0x0 ; uleb128 0x0 - .align 2 -LECIE1: -.globl _ffi_closure_ASM.eh -_ffi_closure_ASM.eh: -LSFDE1: - .set L$set$1,LEFDE1-LASFDE1 - .long L$set$1 ; FDE Length - -LASFDE1: - .long LASFDE1-EH_frame1 ; FDE CIE offset - .long LLFB1$non_lazy_ptr-. ; FDE initial location - .set L$set$3,LFE1-LFB1 - .long L$set$3 ; FDE address range - .byte 0x0 ; uleb128 0x0; Augmentation size - .byte 0x4 ; DW_CFA_advance_loc4 - .set L$set$3,LCFI1-LCFI0 - .long L$set$3 - .byte 0xe ; DW_CFA_def_cfa_offset - .byte 176,1 ; uleb128 176 - .byte 0x4 ; DW_CFA_advance_loc4 - .set L$set$4,LCFI0-LFB1 - .long L$set$4 - .byte 0x11 ; DW_CFA_offset_extended_sf - .byte 0x41 ; uleb128 0x41 - .byte 0x7e ; sleb128 -2 - .align 2 -LEFDE1: -.data - .align 2 -LDFCM0: -.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32 - .align 2 -Lffi_closure_helper_DARWIN$stub: - .indirect_symbol _ffi_closure_helper_DARWIN - mflr r0 - bcl 20,31,LO$ffi_closure_helper_DARWIN -LO$ffi_closure_helper_DARWIN: - mflr r11 - addis r11,r11,ha16(L_ffi_closure_helper_DARWIN$lazy_ptr - LO$ffi_closure_helper_DARWIN) - mtlr r0 - lwzu r12,lo16(L_ffi_closure_helper_DARWIN$lazy_ptr - LO$ffi_closure_helper_DARWIN)(r11) - mtctr r12 - bctr -.data -.lazy_symbol_pointer -L_ffi_closure_helper_DARWIN$lazy_ptr: - .indirect_symbol _ffi_closure_helper_DARWIN - .long dyld_stub_binding_helper -.data - .align 2 -LLFB1$non_lazy_ptr: - .long LFB1 -#endif diff --git a/libffi/src/powerpc/ffi.c b/libffi/src/powerpc/ffi.c deleted file mode 100644 index 29f7dba..0000000 --- a/libffi/src/powerpc/ffi.c +++ /dev/null @@ -1,1133 +0,0 @@ -/* ----------------------------------------------------------------------- - ffi.c - Copyright (c) 1998 Geoffrey Keating - - PowerPC Foreign Function Interface - - $Id: ffi.c,v 1.1.1.1 1998/11/29 16:48:16 green Exp $ - - 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 AUTHOR 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. - ----------------------------------------------------------------------- */ - -#include <ffi.h> -#include <ffi_common.h> - -#include <stdlib.h> -#include <stdio.h> - -#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 1) -# define hidden __attribute__ ((visibility ("hidden"))) -#else -# define hidden -#endif - - -extern void ffi_closure_SYSV(void); -extern void hidden ffi_closure_LINUX64(void); - -enum { - /* The assembly depends on these exact flags. */ - FLAG_RETURNS_NOTHING = 1 << (31-30), /* These go in cr7 */ - FLAG_RETURNS_FP = 1 << (31-29), - FLAG_RETURNS_64BITS = 1 << (31-28), - - FLAG_ARG_NEEDS_COPY = 1 << (31- 7), - FLAG_FP_ARGUMENTS = 1 << (31- 6), /* cr1.eq; specified by ABI */ - FLAG_4_GPR_ARGUMENTS = 1 << (31- 5), - FLAG_RETVAL_REFERENCE = 1 << (31- 4) -}; - -/* About the SYSV ABI. */ -enum { - NUM_GPR_ARG_REGISTERS = 8, - NUM_FPR_ARG_REGISTERS = 8 -}; -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. - - The stack layout we want looks like this: - - | Return address from ffi_call_SYSV 4bytes | higher addresses - |--------------------------------------------| - | Previous backchain pointer 4 | stack pointer here - |--------------------------------------------|<+ <<< on entry to - | Saved r28-r31 4*4 | | ffi_call_SYSV - |--------------------------------------------| | - | GPR registers r3-r10 8*4 | | ffi_call_SYSV - |--------------------------------------------| | - | FPR registers f1-f8 (optional) 8*8 | | - |--------------------------------------------| | stack | - | Space for copied structures | | grows | - |--------------------------------------------| | down V - | Parameters that didn't fit in registers | | - |--------------------------------------------| | lower addresses - | Space for callee's LR 4 | | - |--------------------------------------------| | stack pointer here - | Current backchain pointer 4 |-/ during - |--------------------------------------------| <<< ffi_call_SYSV - - */ - -/*@-exportheader@*/ -void ffi_prep_args_SYSV(extended_cif *ecif, unsigned *const stack) -/*@=exportheader@*/ -{ - const unsigned bytes = ecif->cif->bytes; - const unsigned flags = ecif->cif->flags; - - /* 'stacktop' points at the previous backchain pointer. */ - unsigned *const stacktop = stack + (bytes / sizeof(unsigned)); - - /* 'gpr_base' points at the space for gpr3, and grows upwards as - we use GPR registers. */ - unsigned *gpr_base = stacktop - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS; - int intarg_count = 0; - - /* 'fpr_base' points at the space for fpr1, and grows upwards as - we use FPR registers. */ - double *fpr_base = (double *)gpr_base - NUM_FPR_ARG_REGISTERS; - int fparg_count = 0; - - /* 'copy_space' grows down as we put structures in it. It should - stay 16-byte aligned. */ - char *copy_space = ((flags & FLAG_FP_ARGUMENTS) - ? (char *)fpr_base - : (char *)gpr_base); - - /* 'next_arg' grows up as we put parameters in it. */ - unsigned *next_arg = stack + 2; - - int i; - ffi_type **ptr; - double double_tmp; - void **p_argv; - size_t struct_copy_size; - unsigned gprvalue; - - /* Check that everything starts aligned properly. */ - FFI_ASSERT(((unsigned)(char *)stack & 0xF) == 0); - FFI_ASSERT(((unsigned)(char *)copy_space & 0xF) == 0); - FFI_ASSERT(((unsigned)(char *)stacktop & 0xF) == 0); - FFI_ASSERT((bytes & 0xF) == 0); - FFI_ASSERT(copy_space >= (char *)next_arg); - - /* Deal with return values that are actually pass-by-reference. */ - if (flags & FLAG_RETVAL_REFERENCE) - { - *gpr_base++ = (unsigned long)(char *)ecif->rvalue; - intarg_count++; - } - - /* Now for the arguments. */ - p_argv = ecif->avalue; - for (ptr = ecif->cif->arg_types, i = ecif->cif->nargs; - i > 0; - i--, ptr++, p_argv++) - { - switch ((*ptr)->type) - { - case FFI_TYPE_FLOAT: - double_tmp = *(float *)*p_argv; - if (fparg_count >= NUM_FPR_ARG_REGISTERS) - { - *(float *)next_arg = (float)double_tmp; - next_arg += 1; - } - else - *fpr_base++ = double_tmp; - fparg_count++; - FFI_ASSERT(flags & FLAG_FP_ARGUMENTS); - break; - - case FFI_TYPE_DOUBLE: - double_tmp = *(double *)*p_argv; - - if (fparg_count >= NUM_FPR_ARG_REGISTERS) - { - if (intarg_count%2 != 0) - { - intarg_count++; - next_arg++; - } - *(double *)next_arg = double_tmp; - next_arg += 2; - } - else - *fpr_base++ = double_tmp; - fparg_count++; - FFI_ASSERT(flags & FLAG_FP_ARGUMENTS); - break; - - case FFI_TYPE_UINT64: - case FFI_TYPE_SINT64: - if (intarg_count == NUM_GPR_ARG_REGISTERS-1) - intarg_count++; - if (intarg_count >= NUM_GPR_ARG_REGISTERS) - { - if (intarg_count%2 != 0) - { - intarg_count++; - next_arg++; - } - *(long long *)next_arg = *(long long *)*p_argv; - next_arg += 2; - } - else - { - /* whoops: abi states only certain register pairs - * can be used for passing long long int - * specifically (r3,r4), (r5,r6), (r7,r8), - * (r9,r10) and if next arg is long long but - * not correct starting register of pair then skip - * until the proper starting register - */ - if (intarg_count%2 != 0) - { - intarg_count ++; - gpr_base++; - } - *(long long *)gpr_base = *(long long *)*p_argv; - gpr_base += 2; - } - intarg_count += 2; - break; - - case FFI_TYPE_STRUCT: -#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE - case FFI_TYPE_LONGDOUBLE: -#endif - struct_copy_size = ((*ptr)->size + 15) & ~0xF; - copy_space -= struct_copy_size; - memcpy(copy_space, (char *)*p_argv, (*ptr)->size); - - gprvalue = (unsigned long)copy_space; - - FFI_ASSERT(copy_space > (char *)next_arg); - FFI_ASSERT(flags & FLAG_ARG_NEEDS_COPY); - goto putgpr; - - case FFI_TYPE_UINT8: - gprvalue = *(unsigned char *)*p_argv; - goto putgpr; - case FFI_TYPE_SINT8: - gprvalue = *(signed char *)*p_argv; - goto putgpr; - case FFI_TYPE_UINT16: - gprvalue = *(unsigned short *)*p_argv; - goto putgpr; - case FFI_TYPE_SINT16: - gprvalue = *(signed short *)*p_argv; - goto putgpr; - - case FFI_TYPE_INT: - case FFI_TYPE_UINT32: - case FFI_TYPE_SINT32: - case FFI_TYPE_POINTER: - gprvalue = *(unsigned *)*p_argv; - putgpr: - if (intarg_count >= NUM_GPR_ARG_REGISTERS) - *next_arg++ = gprvalue; - else - *gpr_base++ = gprvalue; - intarg_count++; - break; - } - } - - /* Check that we didn't overrun the stack... */ - FFI_ASSERT(copy_space >= (char *)next_arg); - FFI_ASSERT(gpr_base <= stacktop - ASM_NEEDS_REGISTERS); - FFI_ASSERT((unsigned *)fpr_base - <= stacktop - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS); - FFI_ASSERT(flags & FLAG_4_GPR_ARGUMENTS || intarg_count <= 4); -} - -/* About the LINUX64 ABI. */ -enum { - NUM_GPR_ARG_REGISTERS64 = 8, - NUM_FPR_ARG_REGISTERS64 = 13 -}; -enum { ASM_NEEDS_REGISTERS64 = 4 }; - -/* ffi_prep_args64 is called by the assembly routine once stack space - has been allocated for the function's arguments. - - The stack layout we want looks like this: - - | Ret addr from ffi_call_LINUX64 8bytes | higher addresses - |--------------------------------------------| - | CR save area 8bytes | - |--------------------------------------------| - | Previous backchain pointer 8 | stack pointer here - |--------------------------------------------|<+ <<< on entry to - | Saved r28-r31 4*8 | | ffi_call_LINUX64 - |--------------------------------------------| | - | GPR registers r3-r10 8*8 | | - |--------------------------------------------| | - | FPR registers f1-f13 (optional) 13*8 | | - |--------------------------------------------| | - | Parameter save area | | - |--------------------------------------------| | - | TOC save area 8 | | - |--------------------------------------------| | stack | - | Linker doubleword 8 | | grows | - |--------------------------------------------| | down V - | Compiler doubleword 8 | | - |--------------------------------------------| | lower addresses - | Space for callee's LR 8 | | - |--------------------------------------------| | - | CR save area 8 | | - |--------------------------------------------| | stack pointer here - | Current backchain pointer 8 |-/ during - |--------------------------------------------| <<< ffi_call_LINUX64 - - */ - -/*@-exportheader@*/ -void hidden ffi_prep_args64(extended_cif *ecif, unsigned long *const stack) -/*@=exportheader@*/ -{ - const unsigned long bytes = ecif->cif->bytes; - const unsigned long flags = ecif->cif->flags; - - /* 'stacktop' points at the previous backchain pointer. */ - unsigned long *const stacktop = stack + (bytes / sizeof(unsigned long)); - - /* 'next_arg' points at the space for gpr3, and grows upwards as - we use GPR registers, then continues at rest. */ - unsigned long *const gpr_base = stacktop - ASM_NEEDS_REGISTERS64 - - NUM_GPR_ARG_REGISTERS64; - unsigned long *const gpr_end = gpr_base + NUM_GPR_ARG_REGISTERS64; - unsigned long *const rest = stack + 6 + NUM_GPR_ARG_REGISTERS64; - unsigned long *next_arg = gpr_base; - - /* 'fpr_base' points at the space for fpr3, and grows upwards as - we use FPR registers. */ - double *fpr_base = (double *)gpr_base - NUM_FPR_ARG_REGISTERS64; - int fparg_count = 0; - - int i, words; - ffi_type **ptr; - double double_tmp; - void **p_argv; - unsigned long gprvalue; - - /* Check that everything starts aligned properly. */ - FFI_ASSERT(((unsigned long)(char *)stack & 0xF) == 0); - FFI_ASSERT(((unsigned long)(char *)stacktop & 0xF) == 0); - FFI_ASSERT((bytes & 0xF) == 0); - - /* Deal with return values that are actually pass-by-reference. */ - if (flags & FLAG_RETVAL_REFERENCE) - *next_arg++ = (unsigned long)(char *)ecif->rvalue; - - /* Now for the arguments. */ - p_argv = ecif->avalue; - for (ptr = ecif->cif->arg_types, i = ecif->cif->nargs; - i > 0; - i--, ptr++, p_argv++) - { - switch ((*ptr)->type) - { - case FFI_TYPE_FLOAT: - double_tmp = *(float *)*p_argv; - *(float *)next_arg = (float)double_tmp; - if (++next_arg == gpr_end) - next_arg = rest; - if (fparg_count < NUM_FPR_ARG_REGISTERS64) - *fpr_base++ = double_tmp; - fparg_count++; - FFI_ASSERT(flags & FLAG_FP_ARGUMENTS); - break; - - case FFI_TYPE_DOUBLE: - double_tmp = *(double *)*p_argv; - *(double *)next_arg = double_tmp; - if (++next_arg == gpr_end) - next_arg = rest; - if (fparg_count < NUM_FPR_ARG_REGISTERS64) - *fpr_base++ = double_tmp; - fparg_count++; - FFI_ASSERT(flags & FLAG_FP_ARGUMENTS); - break; - -#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE - case FFI_TYPE_LONGDOUBLE: - double_tmp = ((double *) *p_argv)[0]; - *(double *) next_arg = double_tmp; - if (++next_arg == gpr_end) - next_arg = rest; - if (fparg_count < NUM_FPR_ARG_REGISTERS64) - *fpr_base++ = double_tmp; - fparg_count++; - double_tmp = ((double *) *p_argv)[1]; - *(double *) next_arg = double_tmp; - if (++next_arg == gpr_end) - next_arg = rest; - if (fparg_count < NUM_FPR_ARG_REGISTERS64) - *fpr_base++ = double_tmp; - fparg_count++; - FFI_ASSERT(flags & FLAG_FP_ARGUMENTS); - break; -#endif - - case FFI_TYPE_STRUCT: - words = ((*ptr)->size + 7) / 8; - if (next_arg >= gpr_base && next_arg + words > gpr_end) - { - size_t first = (char *) gpr_end - (char *) next_arg; - memcpy((char *) next_arg, (char *) *p_argv, first); - memcpy((char *) rest, (char *) *p_argv + first, - (*ptr)->size - first); - next_arg = (unsigned long *) ((char *) rest + words * 8 - first); - } - else - { - char *where = (char *) next_arg; - - /* Structures with size less than eight bytes are passed - left-padded. */ - if ((*ptr)->size < 8) - where += 8 - (*ptr)->size; - - memcpy (where, (char *) *p_argv, (*ptr)->size); - next_arg += words; - if (next_arg == gpr_end) - next_arg = rest; - } - break; - - case FFI_TYPE_UINT8: - gprvalue = *(unsigned char *)*p_argv; - goto putgpr; - case FFI_TYPE_SINT8: - gprvalue = *(signed char *)*p_argv; - goto putgpr; - case FFI_TYPE_UINT16: - gprvalue = *(unsigned short *)*p_argv; - goto putgpr; - case FFI_TYPE_SINT16: - gprvalue = *(signed short *)*p_argv; - goto putgpr; - case FFI_TYPE_UINT32: - gprvalue = *(unsigned int *)*p_argv; - goto putgpr; - case FFI_TYPE_INT: - case FFI_TYPE_SINT32: - gprvalue = *(signed int *)*p_argv; - goto putgpr; - - case FFI_TYPE_UINT64: - case FFI_TYPE_SINT64: - case FFI_TYPE_POINTER: - gprvalue = *(unsigned long *)*p_argv; - putgpr: - *next_arg++ = gprvalue; - if (next_arg == gpr_end) - next_arg = rest; - break; - } - } - - FFI_ASSERT(flags & FLAG_4_GPR_ARGUMENTS - || (next_arg >= gpr_base && next_arg <= gpr_base + 4)); -} - - - -/* Perform machine dependent cif processing */ -ffi_status ffi_prep_cif_machdep(ffi_cif *cif) -{ - /* All this is for the SYSV and LINUX64 ABI. */ - int i; - ffi_type **ptr; - unsigned bytes; - int fparg_count = 0, intarg_count = 0; - unsigned flags = 0; - unsigned struct_copy_size = 0; - unsigned type = cif->rtype->type; - - if (cif->abi != FFI_LINUX64) - { - /* All the machine-independent calculation of cif->bytes will be wrong. - Redo the calculation for SYSV. */ - - /* Space for the frame pointer, callee's LR, and the asm's temp regs. */ - bytes = (2 + ASM_NEEDS_REGISTERS) * sizeof(int); - - /* Space for the GPR registers. */ - bytes += NUM_GPR_ARG_REGISTERS * sizeof(int); - } - else - { - /* 64-bit ABI. */ - - /* Space for backchain, CR, LR, cc/ld doubleword, TOC and the asm's temp - regs. */ - bytes = (6 + ASM_NEEDS_REGISTERS64) * sizeof(long); - - /* Space for the mandatory parm save area and general registers. */ - bytes += 2 * NUM_GPR_ARG_REGISTERS64 * sizeof(long); - -#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE - if (type == FFI_TYPE_LONGDOUBLE) - type = FFI_TYPE_DOUBLE; -#endif - } - - /* Return value handling. The rules for SYSV are as follows: - - 32-bit (or less) integer values are returned in gpr3; - - Structures of size <= 4 bytes also returned in gpr3; - - 64-bit integer values and structures between 5 and 8 bytes are returned - in gpr3 and gpr4; - - Single/double FP values are returned in fpr1; - - Larger structures and long double (if not equivalent to double) values - are allocated space and a pointer is passed as the first argument. - For LINUX64: - - integer values in gpr3; - - Structures/Unions by reference; - - Single/double FP values in fpr1, long double in fpr1,fpr2. */ - switch (type) - { - case FFI_TYPE_DOUBLE: - flags |= FLAG_RETURNS_64BITS; - /* Fall through. */ - case FFI_TYPE_FLOAT: - flags |= FLAG_RETURNS_FP; - break; - - case FFI_TYPE_UINT64: - case FFI_TYPE_SINT64: - flags |= FLAG_RETURNS_64BITS; - break; - - case FFI_TYPE_STRUCT: - if (cif->abi != FFI_GCC_SYSV && cif->abi != FFI_LINUX64) - { - if (cif->rtype->size <= 4) - break; - else if (cif->rtype->size <= 8) - { - flags |= FLAG_RETURNS_64BITS; - break; - } - } - /* else fall through. */ -#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE - case FFI_TYPE_LONGDOUBLE: -#endif - intarg_count++; - flags |= FLAG_RETVAL_REFERENCE; - /* Fall through. */ - case FFI_TYPE_VOID: - flags |= FLAG_RETURNS_NOTHING; - break; - - default: - /* Returns 32-bit integer, or similar. Nothing to do here. */ - break; - } - - if (cif->abi != FFI_LINUX64) - /* The first NUM_GPR_ARG_REGISTERS words of integer arguments, and the - first NUM_FPR_ARG_REGISTERS fp arguments, go in registers; the rest - goes on the stack. Structures and long doubles (if not equivalent - to double) are passed as a pointer to a copy of the structure. - Stuff on the stack needs to keep proper alignment. */ - for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++) - { - switch ((*ptr)->type) - { - case FFI_TYPE_FLOAT: - fparg_count++; - /* floating singles are not 8-aligned on stack */ - break; - - case FFI_TYPE_DOUBLE: - fparg_count++; - /* If this FP arg is going on the stack, it must be - 8-byte-aligned. */ - if (fparg_count > NUM_FPR_ARG_REGISTERS - && intarg_count%2 != 0) - intarg_count++; - break; - - case FFI_TYPE_UINT64: - case FFI_TYPE_SINT64: - /* '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 - be 8-byte-aligned. */ - if (intarg_count == NUM_GPR_ARG_REGISTERS-1 - || (intarg_count >= NUM_GPR_ARG_REGISTERS - && intarg_count%2 != 0)) - intarg_count++; - intarg_count += 2; - break; - - case FFI_TYPE_STRUCT: -#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE - case FFI_TYPE_LONGDOUBLE: -#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 - the SYSV ABI). */ - struct_copy_size += ((*ptr)->size + 15) & ~0xF; - /* Fall through (allocate space for the pointer). */ - - default: - /* Everything else is passed as a 4-byte word in a GPR, either - the object itself or a pointer to it. */ - intarg_count++; - break; - } - } - else - for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++) - { - switch ((*ptr)->type) - { -#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE - case FFI_TYPE_LONGDOUBLE: - fparg_count += 2; - intarg_count += 2; - break; -#endif - case FFI_TYPE_FLOAT: - case FFI_TYPE_DOUBLE: - fparg_count++; - intarg_count++; - break; - - case FFI_TYPE_STRUCT: - intarg_count += ((*ptr)->size + 7) / 8; - break; - - default: - /* Everything else is passed as a 8-byte word in a GPR, either - the object itself or a pointer to it. */ - intarg_count++; - break; - } - } - - if (fparg_count != 0) - flags |= FLAG_FP_ARGUMENTS; - if (intarg_count > 4) - flags |= FLAG_4_GPR_ARGUMENTS; - if (struct_copy_size != 0) - flags |= FLAG_ARG_NEEDS_COPY; - - if (cif->abi != FFI_LINUX64) - { - /* Space for the FPR registers, if needed. */ - if (fparg_count != 0) - bytes += NUM_FPR_ARG_REGISTERS * sizeof(double); - - /* Stack space. */ - if (intarg_count > NUM_GPR_ARG_REGISTERS) - bytes += (intarg_count - NUM_GPR_ARG_REGISTERS) * sizeof(int); - if (fparg_count > NUM_FPR_ARG_REGISTERS) - bytes += (fparg_count - NUM_FPR_ARG_REGISTERS) * sizeof(double); - } - else - { - /* Space for the FPR registers, if needed. */ - if (fparg_count != 0) - bytes += NUM_FPR_ARG_REGISTERS64 * sizeof(double); - - /* Stack space. */ - if (intarg_count > NUM_GPR_ARG_REGISTERS64) - bytes += (intarg_count - NUM_GPR_ARG_REGISTERS64) * sizeof(long); - } - - /* The stack space allocated needs to be a multiple of 16 bytes. */ - bytes = (bytes + 15) & ~0xF; - - /* Add in the space for the copied structures. */ - bytes += struct_copy_size; - - cif->flags = flags; - cif->bytes = bytes; - - return FFI_OK; -} - -/*@-declundef@*/ -/*@-exportheader@*/ -extern void ffi_call_SYSV(/*@out@*/ extended_cif *, - unsigned, unsigned, - /*@out@*/ unsigned *, - void (*fn)()); -extern void hidden ffi_call_LINUX64(/*@out@*/ extended_cif *, - unsigned long, unsigned long, - /*@out@*/ unsigned long *, - void (*fn)()); -/*@=declundef@*/ -/*@=exportheader@*/ - -void ffi_call(/*@dependent@*/ ffi_cif *cif, - void (*fn)(), - /*@out@*/ void *rvalue, - /*@dependent@*/ void **avalue) -{ - extended_cif ecif; - - ecif.cif = cif; - ecif.avalue = avalue; - - /* If the return value is a struct and we don't have a return */ - /* value address then we need to make one */ - - if ((rvalue == NULL) && - (cif->rtype->type == FFI_TYPE_STRUCT)) - { - /*@-sysunrecog@*/ - ecif.rvalue = alloca(cif->rtype->size); - /*@=sysunrecog@*/ - } - else - ecif.rvalue = rvalue; - - - switch (cif->abi) - { -#ifndef POWERPC64 - case FFI_SYSV: - case FFI_GCC_SYSV: - /*@-usedef@*/ - ffi_call_SYSV(&ecif, -cif->bytes, - cif->flags, ecif.rvalue, fn); - /*@=usedef@*/ - break; -#else - case FFI_LINUX64: - /*@-usedef@*/ - ffi_call_LINUX64(&ecif, -(long) cif->bytes, - cif->flags, ecif.rvalue, fn); - /*@=usedef@*/ - break; -#endif - default: - FFI_ASSERT(0); - break; - } -} - - -#ifndef POWERPC64 -static void flush_icache(char *, int); - -#define MIN_CACHE_LINE_SIZE 8 - -static void flush_icache(char * addr1, int size) -{ - int i; - char * addr; - for (i = 0; i < size; i += MIN_CACHE_LINE_SIZE) { - addr = addr1 + i; - __asm__ volatile ("icbi 0,%0;" "dcbf 0,%0;" : : "r"(addr) : "memory"); - } - addr = addr1 + size - 1; - __asm__ volatile ("icbi 0,%0;" "dcbf 0,%0;" "sync;" "isync;" : : "r"(addr) : "memory"); -} -#endif - -ffi_status -ffi_prep_closure (ffi_closure* closure, - ffi_cif* cif, - void (*fun)(ffi_cif*, void*, void**, void*), - void *user_data) -{ -#ifdef POWERPC64 - void **tramp = (void **) &closure->tramp[0]; - - FFI_ASSERT (cif->abi == FFI_LINUX64); - /* Copy function address and TOC from ffi_closure_LINUX64. */ - memcpy (tramp, (char *) ffi_closure_LINUX64, 16); - tramp[2] = (void *) closure; -#else - unsigned int *tramp; - - FFI_ASSERT (cif->abi == FFI_GCC_SYSV); - - tramp = (unsigned int *) &closure->tramp[0]; - tramp[0] = 0x7c0802a6; /* mflr r0 */ - tramp[1] = 0x4800000d; /* bl 10 <trampoline_initial+0x10> */ - tramp[4] = 0x7d6802a6; /* mflr r11 */ - tramp[5] = 0x7c0803a6; /* mtlr r0 */ - tramp[6] = 0x800b0000; /* lwz r0,0(r11) */ - tramp[7] = 0x816b0004; /* lwz r11,4(r11) */ - tramp[8] = 0x7c0903a6; /* mtctr r0 */ - tramp[9] = 0x4e800420; /* bctr */ - *(void **) &tramp[2] = (void *)ffi_closure_SYSV; /* function */ - *(void **) &tramp[3] = (void *)closure; /* context */ - - /* Flush the icache. */ - flush_icache(&closure->tramp[0],FFI_TRAMPOLINE_SIZE); -#endif - - closure->cif = cif; - closure->fun = fun; - closure->user_data = user_data; - - return FFI_OK; -} - -typedef union -{ - float f; - double d; -} ffi_dblfl; - -int ffi_closure_helper_SYSV (ffi_closure*, void*, unsigned long*, - ffi_dblfl*, unsigned long*); - -/* Basically the trampoline invokes ffi_closure_SYSV, and on - * entry, r11 holds the address of the closure. - * After storing the registers that could possibly contain - * parameters to be passed into the stack frame and setting - * up space for a return value, ffi_closure_SYSV invokes the - * following helper function to do most of the work - */ - -int -ffi_closure_helper_SYSV (ffi_closure* closure, void * rvalue, - unsigned long * pgr, ffi_dblfl * pfr, - unsigned long * pst) -{ - /* rvalue is the pointer to space for return value in closure assembly */ - /* pgr is the pointer to where r3-r10 are stored in ffi_closure_SYSV */ - /* pfr is the pointer to where f1-f8 are stored in ffi_closure_SYSV */ - /* pst is the pointer to outgoing parameter stack in original caller */ - - 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; - - cif = closure->cif; - avalue = alloca(cif->nargs * sizeof(void *)); - - nf = 0; - ng = 0; - - /* Copy the caller's structure return value address so that the closure - returns the data directly to the caller. */ - if (cif->rtype->type == FFI_TYPE_STRUCT) - { - rvalue = (void *) *pgr; - ng++; - pgr++; - } - - i = 0; - avn = cif->nargs; - arg_types = cif->arg_types; - - /* Grab the addresses of the arguments from the stack frame. */ - while (i < avn) - { - switch (arg_types[i]->type) - { - case FFI_TYPE_SINT8: - case FFI_TYPE_UINT8: - /* there are 8 gpr registers used to pass values */ - if (ng < 8) { - avalue[i] = (((char *)pgr)+3); - ng++; - pgr++; - } else { - avalue[i] = (((char *)pst)+3); - pst++; - } - break; - - case FFI_TYPE_SINT16: - case FFI_TYPE_UINT16: - /* there are 8 gpr registers used to pass values */ - if (ng < 8) { - avalue[i] = (((char *)pgr)+2); - ng++; - pgr++; - } else { - avalue[i] = (((char *)pst)+2); - pst++; - } - break; - - case FFI_TYPE_SINT32: - case FFI_TYPE_UINT32: - case FFI_TYPE_POINTER: - /* there are 8 gpr registers used to pass values */ - if (ng < 8) { - avalue[i] = pgr; - ng++; - pgr++; - } else { - avalue[i] = pst; - pst++; - } - break; - - case FFI_TYPE_STRUCT: - /* Structs are passed by reference. The address will appear in a - gpr if it is one of the first 8 arguments. */ - if (ng < 8) { - avalue[i] = (void *) *pgr; - ng++; - pgr++; - } else { - avalue[i] = (void *) *pst; - pst++; - } - break; - - case FFI_TYPE_SINT64: - case FFI_TYPE_UINT64: - /* 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) - * and if the entire pair aren't available then the outgoing - * parameter stack is used for both but an alignment of 8 - * must will be kept. So we must either look in pgr - * or pst to find the correct address for this type - * of parameter. - */ - if (ng < 7) { - if (ng & 0x01) { - /* skip r4, r6, r8 as starting points */ - ng++; - pgr++; - } - avalue[i] = pgr; - ng+=2; - pgr+=2; - } else { - if (((long)pst) & 4) pst++; - avalue[i] = pst; - pst+=2; - } - break; - - 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; - nf++; - 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; - nf++; - pst+=2; - } - break; - - default: - FFI_ASSERT(0); - } - - i++; - } - - - (closure->fun) (cif, rvalue, avalue, closure->user_data); - - /* Tell ffi_closure_SYSV how to perform return type promotions. */ - return cif->rtype->type; - -} - -int hidden ffi_closure_helper_LINUX64 (ffi_closure*, void*, unsigned long*, - ffi_dblfl*); - -int hidden -ffi_closure_helper_LINUX64 (ffi_closure *closure, void *rvalue, - unsigned long *pst, ffi_dblfl *pfr) -{ - /* rvalue is the pointer to space for return value in closure assembly */ - /* pst is the pointer to parameter save area - (r3-r10 are stored into its first 8 slots by ffi_closure_LINUX64) */ - /* pfr is the pointer to where f1-f13 are stored in ffi_closure_LINUX64 */ - - void **avalue; - ffi_type **arg_types; - long i, avn; - ffi_cif *cif; - ffi_dblfl *end_pfr = pfr + NUM_FPR_ARG_REGISTERS64; - - cif = closure->cif; - avalue = alloca (cif->nargs * sizeof (void *)); - - /* Copy the caller's structure return value address so that the closure - returns the data directly to the caller. */ - if (cif->rtype->type == FFI_TYPE_STRUCT) - { - rvalue = (void *) *pst; - pst++; - } - - i = 0; - avn = cif->nargs; - arg_types = cif->arg_types; - - /* Grab the addresses of the arguments from the stack frame. */ - while (i < avn) - { - switch (arg_types[i]->type) - { - case FFI_TYPE_SINT8: - case FFI_TYPE_UINT8: - avalue[i] = (char *) pst + 7; - pst++; - break; - - case FFI_TYPE_SINT16: - case FFI_TYPE_UINT16: - avalue[i] = (char *) pst + 6; - pst++; - break; - - case FFI_TYPE_SINT32: - case FFI_TYPE_UINT32: - avalue[i] = (char *) pst + 4; - pst++; - break; - - case FFI_TYPE_SINT64: - case FFI_TYPE_UINT64: - case FFI_TYPE_POINTER: - avalue[i] = pst; - pst++; - break; - - case FFI_TYPE_STRUCT: - /* Structures with size less than eight bytes are passed - left-padded. */ - if (arg_types[i]->size < 8) - avalue[i] = (char *) pst + 8 - arg_types[i]->size; - else - avalue[i] = pst; - pst += (arg_types[i]->size + 7) / 8; - break; - - case FFI_TYPE_FLOAT: - /* unfortunately float values are stored as doubles - * in the ffi_closure_LINUX64 code (since we don't check - * the type in that routine). - */ - - /* there are 13 64bit floating point registers */ - - if (pfr < end_pfr) - { - double temp = pfr->d; - pfr->f = (float) temp; - avalue[i] = pfr; - pfr++; - } - else - avalue[i] = pst; - pst++; - break; - - case FFI_TYPE_DOUBLE: - /* On the outgoing stack all values are aligned to 8 */ - /* there are 13 64bit floating point registers */ - - if (pfr < end_pfr) - { - avalue[i] = pfr; - pfr++; - } - else - avalue[i] = pst; - pst++; - break; - -#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE - case FFI_TYPE_LONGDOUBLE: - if (pfr + 1 < end_pfr) - { - avalue[i] = pfr; - pfr += 2; - } - else - { - if (pfr < end_pfr) - { - /* Passed partly in f13 and partly on the stack. - Move it all to the stack. */ - *pst = *(unsigned long *) pfr; - pfr++; - } - avalue[i] = pst; - } - pst += 2; - break; -#endif - - default: - FFI_ASSERT(0); - } - - i++; - } - - - (closure->fun) (cif, rvalue, avalue, closure->user_data); - - /* Tell ffi_closure_LINUX64 how to perform return type promotions. */ - return cif->rtype->type; -} diff --git a/libffi/src/powerpc/ffi_darwin.c b/libffi/src/powerpc/ffi_darwin.c deleted file mode 100644 index 116f9cb..0000000 --- a/libffi/src/powerpc/ffi_darwin.c +++ /dev/null @@ -1,704 +0,0 @@ -#ifdef __ppc__ -/* ----------------------------------------------------------------------- - ffi.c - Copyright (c) 1998 Geoffrey Keating - - PowerPC Foreign Function Interface - - Darwin ABI support (c) 2001 John Hornkvist - AIX ABI support (c) 2002 Free Software Foundation, Inc. - - 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 AUTHOR 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. - ----------------------------------------------------------------------- */ - -#include <ffi.h> -#include <ffi_common.h> - -#include <stdlib.h> - -extern void ffi_closure_ASM(void); - -enum { - /* The assembly depends on these exact flags. */ - FLAG_RETURNS_NOTHING = 1 << (31-30), /* These go in cr7 */ - FLAG_RETURNS_FP = 1 << (31-29), - FLAG_RETURNS_64BITS = 1 << (31-28), - - FLAG_ARG_NEEDS_COPY = 1 << (31- 7), - FLAG_FP_ARGUMENTS = 1 << (31- 6), /* cr1.eq; specified by ABI */ - FLAG_4_GPR_ARGUMENTS = 1 << (31- 5), - FLAG_RETVAL_REFERENCE = 1 << (31- 4) -}; - -/* About the DARWIN ABI. */ -enum { - NUM_GPR_ARG_REGISTERS = 8, - NUM_FPR_ARG_REGISTERS = 13 -}; -enum { ASM_NEEDS_REGISTERS = 4 }; - -/* ffi_prep_args is called by the assembly routine once stack space - has been allocated for the function's arguments. - - The stack layout we want looks like this: - - | Return address from ffi_call_DARWIN | higher addresses - |--------------------------------------------| - | Previous backchain pointer 4 | stack pointer here - |--------------------------------------------|<+ <<< on entry to - | Saved r28-r31 4*4 | | ffi_call_DARWIN - |--------------------------------------------| | - | Parameters (at least 8*4=32) | | - |--------------------------------------------| | - | Space for GPR2 4 | | - |--------------------------------------------| | stack | - | Reserved 2*4 | | grows | - |--------------------------------------------| | down V - | Space for callee's LR 4 | | - |--------------------------------------------| | lower addresses - | Saved CR 4 | | - |--------------------------------------------| | stack pointer here - | Current backchain pointer 4 |-/ during - |--------------------------------------------| <<< ffi_call_DARWIN - - */ - -/*@-exportheader@*/ -void ffi_prep_args(extended_cif *ecif, unsigned *const stack) -/*@=exportheader@*/ -{ - const unsigned bytes = ecif->cif->bytes; - const unsigned flags = ecif->cif->flags; - - /* 'stacktop' points at the previous backchain pointer. */ - unsigned *const stacktop = stack + (ecif->cif->bytes / sizeof(unsigned)); - - /* 'fpr_base' points at the space for fpr1, and grows upwards as - we use FPR registers. */ - double *fpr_base = (double*) (stacktop - ASM_NEEDS_REGISTERS) - NUM_FPR_ARG_REGISTERS; - int fparg_count = 0; - - - /* 'next_arg' grows up as we put parameters in it. */ - unsigned *next_arg = stack + 6; /* 6 reserved posistions. */ - - int i = ecif->cif->nargs; - double double_tmp; - void **p_argv = ecif->avalue; - unsigned gprvalue; - ffi_type** ptr = ecif->cif->arg_types; - char *dest_cpy; - unsigned size_al = 0; - - /* Check that everything starts aligned properly. */ - FFI_ASSERT(((unsigned)(char *)stack & 0xF) == 0); - FFI_ASSERT(((unsigned)(char *)stacktop & 0xF) == 0); - FFI_ASSERT((bytes & 0xF) == 0); - - /* Deal with return values that are actually pass-by-reference. - Rule: - Return values are referenced by r3, so r4 is the first parameter. */ - - if (flags & FLAG_RETVAL_REFERENCE) - *next_arg++ = (unsigned)(char *)ecif->rvalue; - - /* Now for the arguments. */ - for (; - i > 0; - i--, ptr++, p_argv++) - { - switch ((*ptr)->type) - { - /* If a floating-point parameter appears before all of the general- - purpose registers are filled, the corresponding GPRs that match - the size of the floating-point parameter are skipped. */ - case FFI_TYPE_FLOAT: - double_tmp = *(float *)*p_argv; - if (fparg_count >= NUM_FPR_ARG_REGISTERS) - *(double *)next_arg = double_tmp; - else - *fpr_base++ = double_tmp; - next_arg++; - fparg_count++; - FFI_ASSERT(flags & FLAG_FP_ARGUMENTS); - break; - case FFI_TYPE_DOUBLE: - double_tmp = *(double *)*p_argv; - if (fparg_count >= NUM_FPR_ARG_REGISTERS) - *(double *)next_arg = double_tmp; - else - *fpr_base++ = double_tmp; - next_arg += 2; - fparg_count++; - FFI_ASSERT(flags & FLAG_FP_ARGUMENTS); - break; - - case FFI_TYPE_UINT64: - case FFI_TYPE_SINT64: - *(long long *)next_arg = *(long long *)*p_argv; - next_arg+=2; - break; - case FFI_TYPE_UINT8: - gprvalue = *(unsigned char *)*p_argv; - goto putgpr; - case FFI_TYPE_SINT8: - gprvalue = *(signed char *)*p_argv; - goto putgpr; - case FFI_TYPE_UINT16: - gprvalue = *(unsigned short *)*p_argv; - goto putgpr; - case FFI_TYPE_SINT16: - gprvalue = *(signed short *)*p_argv; - goto putgpr; - - case FFI_TYPE_STRUCT: - -#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE - case FFI_TYPE_LONGDOUBLE: -#endif - dest_cpy = (char *) next_arg; - - /* Structures that match the basic modes (QI 1 byte, HI 2 bytes, - SI 4 bytes) are aligned as if they were those modes. - Structures with 3 byte in size are padded upwards. */ - size_al = (*ptr)->size; - /* If the first member of the struct is a double, then align - the struct to double-word. - Type 3 is defined in include/ffi.h. #define FFI_TYPE_DOUBLE 3. */ - if ((*ptr)->elements[0]->type == 3) - size_al = ALIGN((*ptr)->size, 8); - if (size_al < 3 && ecif->cif->abi == FFI_DARWIN) - dest_cpy += 4 - size_al; - - memcpy((char *)dest_cpy, (char *)*p_argv, size_al); - next_arg += (size_al + 3) / 4; - break; - - case FFI_TYPE_INT: - case FFI_TYPE_UINT32: - case FFI_TYPE_SINT32: - case FFI_TYPE_POINTER: - gprvalue = *(unsigned *)*p_argv; - putgpr: - *next_arg++ = gprvalue; - break; - default: - break; - } - } - - /* Check that we didn't overrun the stack... */ - //FFI_ASSERT(gpr_base <= stacktop - ASM_NEEDS_REGISTERS); - //FFI_ASSERT((unsigned *)fpr_base - // <= stacktop - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS); - //FFI_ASSERT(flags & FLAG_4_GPR_ARGUMENTS || intarg_count <= 4); -} - -/* Perform machine dependent cif processing. */ -ffi_status ffi_prep_cif_machdep(ffi_cif *cif) -{ - /* All this is for the DARWIN ABI. */ - int i; - ffi_type **ptr; - unsigned bytes; - int fparg_count = 0, intarg_count = 0; - unsigned flags = 0; - unsigned size_al = 0; - - /* All the machine-independent calculation of cif->bytes will be wrong. - Redo the calculation for DARWIN. */ - - /* Space for the frame pointer, callee's LR, CR, etc, and for - the asm's temp regs. */ - - bytes = (6 + ASM_NEEDS_REGISTERS) * sizeof(long); - - /* Return value handling. The rules are as follows: - - 32-bit (or less) integer values are returned in gpr3; - - Structures of size <= 4 bytes also returned in gpr3; - - 64-bit integer values and structures between 5 and 8 bytes are returned - in gpr3 and gpr4; - - Single/double FP values are returned in fpr1; - - Long double FP (if not equivalent to double) values are returned in - fpr1 and fpr2; - - Larger structures values are allocated space and a pointer is passed - as the first argument. */ - switch (cif->rtype->type) - { -#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE - case FFI_TYPE_LONGDOUBLE: -#endif - /* Fall through. */ - case FFI_TYPE_DOUBLE: - flags |= FLAG_RETURNS_64BITS; - /* Fall through. */ - case FFI_TYPE_FLOAT: - flags |= FLAG_RETURNS_FP; - break; - - case FFI_TYPE_UINT64: - case FFI_TYPE_SINT64: - flags |= FLAG_RETURNS_64BITS; - break; - - case FFI_TYPE_STRUCT: - flags |= FLAG_RETVAL_REFERENCE; - flags |= FLAG_RETURNS_NOTHING; - intarg_count++; - break; - case FFI_TYPE_VOID: - flags |= FLAG_RETURNS_NOTHING; - break; - - default: - /* Returns 32-bit integer, or similar. Nothing to do here. */ - break; - } - - /* The first NUM_GPR_ARG_REGISTERS words of integer arguments, and the - first NUM_FPR_ARG_REGISTERS fp arguments, go in registers; the rest - goes on the stack. Structures and long doubles (if not equivalent - to double) are passed as a pointer to a copy of the structure. - Stuff on the stack needs to keep proper alignment. */ - for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++) - { - switch ((*ptr)->type) - { - case FFI_TYPE_FLOAT: - case FFI_TYPE_DOUBLE: - fparg_count++; - /* If this FP arg is going on the stack, it must be - 8-byte-aligned. */ - if (fparg_count > NUM_FPR_ARG_REGISTERS - && intarg_count%2 != 0) - intarg_count++; - break; - - case FFI_TYPE_UINT64: - case FFI_TYPE_SINT64: - /* '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 - be 8-byte-aligned. */ - if (intarg_count == NUM_GPR_ARG_REGISTERS-1 - || (intarg_count >= NUM_GPR_ARG_REGISTERS && intarg_count%2 != 0)) - intarg_count++; - intarg_count += 2; - break; - - case FFI_TYPE_STRUCT: -#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE - case FFI_TYPE_LONGDOUBLE: -#endif - size_al = (*ptr)->size; - /* If the first member of the struct is a double, then align - the struct to double-word. - Type 3 is defined in include/ffi.h. #define FFI_TYPE_DOUBLE 3. */ - if ((*ptr)->elements[0]->type == 3) - size_al = ALIGN((*ptr)->size, 8); - intarg_count += (size_al + 3) / 4; - break; - - default: - /* Everything else is passed as a 4-byte word in a GPR, either - the object itself or a pointer to it. */ - intarg_count++; - break; - } - } - - if (fparg_count != 0) - flags |= FLAG_FP_ARGUMENTS; - - /* Space for the FPR registers, if needed. */ - if (fparg_count != 0) - bytes += NUM_FPR_ARG_REGISTERS * sizeof(double); - - /* Stack space. */ - if ((intarg_count + 2 * fparg_count) > NUM_GPR_ARG_REGISTERS) - bytes += (intarg_count + 2 * fparg_count) * sizeof(long); - else - bytes += NUM_GPR_ARG_REGISTERS * sizeof(long); - - /* The stack space allocated needs to be a multiple of 16 bytes. */ - bytes = (bytes + 15) & ~0xF; - - cif->flags = flags; - cif->bytes = bytes; - - return FFI_OK; -} - -/*@-declundef@*/ -/*@-exportheader@*/ -extern void ffi_call_AIX(/*@out@*/ extended_cif *, - unsigned, unsigned, - /*@out@*/ unsigned *, - void (*fn)(), - void (*fn2)()); -extern void ffi_call_DARWIN(/*@out@*/ extended_cif *, - unsigned, unsigned, - /*@out@*/ unsigned *, - void (*fn)(), - void (*fn2)()); -/*@=declundef@*/ -/*@=exportheader@*/ - -void ffi_call(/*@dependent@*/ ffi_cif *cif, - void (*fn)(), - /*@out@*/ void *rvalue, - /*@dependent@*/ void **avalue) -{ - extended_cif ecif; - - ecif.cif = cif; - ecif.avalue = avalue; - - /* If the return value is a struct and we don't have a return - value address then we need to make one. */ - - if ((rvalue == NULL) && - (cif->rtype->type == FFI_TYPE_STRUCT)) - { - /*@-sysunrecog@*/ - ecif.rvalue = alloca(cif->rtype->size); - /*@=sysunrecog@*/ - } - else - ecif.rvalue = rvalue; - - switch (cif->abi) - { - case FFI_AIX: - /*@-usedef@*/ - ffi_call_AIX(&ecif, -cif->bytes, - cif->flags, ecif.rvalue, fn, ffi_prep_args); - /*@=usedef@*/ - break; - case FFI_DARWIN: - /*@-usedef@*/ - ffi_call_DARWIN(&ecif, -cif->bytes, - cif->flags, ecif.rvalue, fn, ffi_prep_args); - /*@=usedef@*/ - break; - default: - FFI_ASSERT(0); - break; - } -} - -static void flush_icache(char *); -static void flush_range(char *, int); - -/* The layout of a function descriptor. A C function pointer really - points to one of these. */ - -typedef struct aix_fd_struct { - void *code_pointer; - void *toc; -} aix_fd; - -/* here I'd like to add the stack frame layout we use in darwin_closure.S - and aix_clsoure.S - - SP previous -> +---------------------------------------+ <--- child frame - | back chain to caller 4 | - +---------------------------------------+ 4 - | saved CR 4 | - +---------------------------------------+ 8 - | saved LR 4 | - +---------------------------------------+ 12 - | reserved for compilers 4 | - +---------------------------------------+ 16 - | reserved for binders 4 | - +---------------------------------------+ 20 - | saved TOC pointer 4 | - +---------------------------------------+ 24 - | always reserved 8*4=32 (previous GPRs)| - | according to the linkage convention | - | from AIX | - +---------------------------------------+ 56 - | our FPR area 13*8=104 | - | f1 | - | . | - | f13 | - +---------------------------------------+ 160 - | result area 8 | - +---------------------------------------+ 168 - | alignement to the next multiple of 16 | -SP current --> +---------------------------------------+ 176 <- parent frame - | back chain to caller 4 | - +---------------------------------------+ 180 - | saved CR 4 | - +---------------------------------------+ 184 - | saved LR 4 | - +---------------------------------------+ 188 - | reserved for compilers 4 | - +---------------------------------------+ 192 - | reserved for binders 4 | - +---------------------------------------+ 196 - | saved TOC pointer 4 | - +---------------------------------------+ 200 - | always reserved 8*4=32 we store our | - | GPRs here | - | r3 | - | . | - | r10 | - +---------------------------------------+ 232 - | overflow part | - +---------------------------------------+ xxx - | ???? | - +---------------------------------------+ xxx - -*/ -ffi_status -ffi_prep_closure (ffi_closure* closure, - ffi_cif* cif, - void (*fun)(ffi_cif*, void*, void**, void*), - void *user_data) -{ - unsigned int *tramp; - struct ffi_aix_trampoline_struct *tramp_aix; - aix_fd *fd; - - switch (cif->abi) - { - case FFI_DARWIN: - - FFI_ASSERT (cif->abi == FFI_DARWIN); - - tramp = (unsigned int *) &closure->tramp[0]; - tramp[0] = 0x7c0802a6; /* mflr r0 */ - tramp[1] = 0x429f000d; /* bcl- 20,4*cr7+so,0x10 */ - tramp[4] = 0x7d6802a6; /* mflr r11 */ - tramp[5] = 0x818b0000; /* lwz r12,0(r11) function address */ - tramp[6] = 0x7c0803a6; /* mtlr r0 */ - tramp[7] = 0x7d8903a6; /* mtctr r12 */ - tramp[8] = 0x816b0004; /* lwz r11,4(r11) static chain */ - tramp[9] = 0x4e800420; /* bctr */ - tramp[2] = (unsigned long) ffi_closure_ASM; /* function */ - tramp[3] = (unsigned long) closure; /* context */ - - closure->cif = cif; - closure->fun = fun; - closure->user_data = user_data; - - /* Flush the icache. Only necessary on Darwin. */ - flush_range(&closure->tramp[0],FFI_TRAMPOLINE_SIZE); - - break; - - case FFI_AIX: - - tramp_aix = (struct ffi_aix_trampoline_struct *) (closure->tramp); - fd = (aix_fd *)(void *)ffi_closure_ASM; - - FFI_ASSERT (cif->abi == FFI_AIX); - - tramp_aix->code_pointer = fd->code_pointer; - tramp_aix->toc = fd->toc; - tramp_aix->static_chain = closure; - closure->cif = cif; - closure->fun = fun; - closure->user_data = user_data; - - default: - - FFI_ASSERT(0); - break; - } - return FFI_OK; -} - -static void -flush_icache(char *addr) -{ -#ifndef _AIX - __asm__ volatile ( - "dcbf 0,%0;" - "sync;" - "icbi 0,%0;" - "sync;" - "isync;" - : : "r"(addr) : "memory"); -#endif -} - -static void -flush_range(char * addr1, int size) -{ -#define MIN_LINE_SIZE 32 - int i; - for (i = 0; i < size; i += MIN_LINE_SIZE) - flush_icache(addr1+i); - flush_icache(addr1+size-1); -} - -typedef union -{ - float f; - double d; -} ffi_dblfl; - -int ffi_closure_helper_DARWIN (ffi_closure*, void*, - unsigned long*, ffi_dblfl*); - -/* Basically the trampoline invokes ffi_closure_ASM, and on - entry, r11 holds the address of the closure. - After storing the registers that could possibly contain - parameters to be passed into the stack frame and setting - up space for a return value, ffi_closure_ASM invokes the - following helper function to do most of the work. */ - -int ffi_closure_helper_DARWIN (ffi_closure* closure, void * rvalue, - unsigned long * pgr, ffi_dblfl * pfr) -{ - /* rvalue is the pointer to space for return value in closure assembly - pgr is the pointer to where r3-r10 are stored in ffi_closure_ASM - pfr is the pointer to where f1-f13 are stored in ffi_closure_ASM. */ - - - 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_al; - - cif = closure->cif; - avalue = alloca(cif->nargs * sizeof(void *)); - - nf = 0; - ng = 0; - - /* Copy the caller's structure return value address so that the closure - returns the data directly to the caller. */ - if (cif->rtype->type == FFI_TYPE_STRUCT) - { - rvalue = (void *) *pgr; - pgr++; - ng++; - } - - i = 0; - avn = cif->nargs; - arg_types = cif->arg_types; - - /* Grab the addresses of the arguments from the stack frame. */ - while (i < avn) - { - switch (arg_types[i]->type) - { - case FFI_TYPE_SINT8: - case FFI_TYPE_UINT8: - avalue[i] = (char *) pgr + 3; - ng++; - pgr++; - break; - - case FFI_TYPE_SINT16: - case FFI_TYPE_UINT16: - avalue[i] = (char *) pgr + 2; - ng++; - pgr++; - break; - - case FFI_TYPE_SINT32: - case FFI_TYPE_UINT32: - case FFI_TYPE_POINTER: - avalue[i] = pgr; - ng++; - pgr++; - break; - - case FFI_TYPE_STRUCT: - /* Structures that match the basic modes (QI 1 byte, HI 2 bytes, - SI 4 bytes) are aligned as if they were those modes. */ - size_al = arg_types[i]->size; - /* If the first member of the struct is a double, then align - the struct to double-word. - Type 3 is defined in include/ffi.h. #define FFI_TYPE_DOUBLE 3. */ - if (arg_types[i]->elements[0]->type == 3) - size_al = ALIGN(arg_types[i]->size, 8); - if (size_al < 3 && cif->abi == FFI_DARWIN) - avalue[i] = (void*) pgr + 4 - size_al; - else - avalue[i] = (void*) pgr; - ng += (size_al + 3) / 4; - pgr += (size_al + 3) / 4; - break; - - case FFI_TYPE_SINT64: - case FFI_TYPE_UINT64: - /* Long long ints are passed in two gpr's. */ - avalue[i] = pgr; - ng += 2; - pgr += 2; - break; - - case FFI_TYPE_FLOAT: - /* A float value consumes a GPR. - There are 13 64bit floating point registers. */ - if (nf < NUM_FPR_ARG_REGISTERS) - { - temp = pfr->d; - pfr->f = (float)temp; - avalue[i] = pfr; - pfr++; - } - else - { - avalue[i] = pgr; - } - nf++; - ng++; - pgr++; - break; - - case FFI_TYPE_DOUBLE: - /* A double value consumes two GPRs. - There are 13 64bit floating point registers. */ - if (nf < NUM_FPR_ARG_REGISTERS) - { - avalue[i] = pfr; - pfr++; - } - else - { - avalue[i] = pgr; - } - nf++; - ng += 2; - pgr += 2; - break; - - default: - FFI_ASSERT(0); - } - i++; - } - - (closure->fun) (cif, rvalue, avalue, closure->user_data); - - /* Tell ffi_closure_ASM to perform return type promotions. */ - return cif->rtype->type; -} -#endif diff --git a/libffi/src/powerpc/ffitarget.h b/libffi/src/powerpc/ffitarget.h deleted file mode 100644 index 101ea78..0000000 --- a/libffi/src/powerpc/ffitarget.h +++ /dev/null @@ -1,91 +0,0 @@ -/* -----------------------------------------------------------------*-C-*- - ffitarget.h - Copyright (c) 1996-2003 Red Hat, 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 CYGNUS SOLUTIONS 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__) -#define POWERPC64 -#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, -# ifdef POWERPC64 - FFI_DEFAULT_ABI = FFI_LINUX64, -# else - FFI_DEFAULT_ABI = FFI_GCC_SYSV, -# 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 - - FFI_LAST_ABI = FFI_DEFAULT_ABI + 1 -} ffi_abi; -#endif - -/* ---- Definitions for closures ----------------------------------------- */ - -#define FFI_CLOSURES 1 -#define FFI_NATIVE_RAW_API 0 - -#if defined(POWERPC64) || defined(POWERPC_AIX) -#define FFI_TRAMPOLINE_SIZE 24 -#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 - diff --git a/libffi/src/powerpc/linux64.S b/libffi/src/powerpc/linux64.S deleted file mode 100644 index 11cf926..0000000 --- a/libffi/src/powerpc/linux64.S +++ /dev/null @@ -1,176 +0,0 @@ -/* ----------------------------------------------------------------------- - sysv.h - Copyright (c) 2003 Jakub Jelinek <jakub@redhat.com> - - PowerPC64 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 AUTHOR 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> - -#ifdef __powerpc64__ - .hidden ffi_call_LINUX64, .ffi_call_LINUX64 - .globl ffi_call_LINUX64, .ffi_call_LINUX64 - .section ".opd","aw" - .align 3 -ffi_call_LINUX64: - .quad .ffi_call_LINUX64,.TOC.@tocbase,0 - .size ffi_call_LINUX64,24 - .type .ffi_call_LINUX64,@function - .text -.ffi_call_LINUX64: -.LFB1: - mflr %r0 - std %r28, -32(%r1) - std %r29, -24(%r1) - std %r30, -16(%r1) - std %r31, -8(%r1) - std %r0, 16(%r1) - - mr %r28, %r1 /* our AP. */ - stdux %r1, %r1, %r4 -.LCFI0: - mr %r31, %r5 /* flags, */ - mr %r30, %r6 /* rvalue, */ - mr %r29, %r7 /* function address. */ - std %r2, 40(%r1) - - /* Call ffi_prep_args64. */ - mr %r4, %r1 - bl .ffi_prep_args64 - - ld %r0, 0(%r29) - ld %r2, 8(%r29) - ld %r11, 16(%r29) - - /* 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 %r0 - /* Load all those argument registers. */ - ld %r3, -32-(8*8)(%r28) - ld %r4, -32-(7*8)(%r28) - ld %r5, -32-(6*8)(%r28) - ld %r6, -32-(5*8)(%r28) - bf- 5, 1f - ld %r7, -32-(4*8)(%r28) - ld %r8, -32-(3*8)(%r28) - ld %r9, -32-(2*8)(%r28) - ld %r10, -32-(1*8)(%r28) -1: - - /* Load all the FP registers. */ - bf- 6, 2f - lfd %f1, -32-(21*8)(%r28) - lfd %f2, -32-(20*8)(%r28) - lfd %f3, -32-(19*8)(%r28) - lfd %f4, -32-(18*8)(%r28) - lfd %f5, -32-(17*8)(%r28) - lfd %f6, -32-(16*8)(%r28) - lfd %f7, -32-(15*8)(%r28) - lfd %f8, -32-(14*8)(%r28) - lfd %f9, -32-(13*8)(%r28) - lfd %f10, -32-(12*8)(%r28) - lfd %f11, -32-(11*8)(%r28) - lfd %f12, -32-(10*8)(%r28) - lfd %f13, -32-(9*8)(%r28) -2: - - /* Make the call. */ - bctrl - - /* Now, deal with the return value. */ - mtcrf 0x01, %r31 - bt- 30, .Ldone_return_value - bt- 29, .Lfp_return_value - std %r3, 0(%r30) - /* Fall through... */ - -.Ldone_return_value: - /* Restore the registers we used and return. */ - ld %r2, 40(%r1) - mr %r1, %r28 - ld %r0, 16(%r28) - ld %r28, -32(%r1) - mtlr %r0 - ld %r29, -24(%r1) - ld %r30, -16(%r1) - ld %r31, -8(%r1) - blr - -.Lfp_return_value: - bf 28, .Lfloat_return_value - stfd %f1, 0(%r30) - stfd %f2, 8(%r30) /* It might be a long double */ - b .Ldone_return_value -.Lfloat_return_value: - stfs %f1, 0(%r30) - b .Ldone_return_value -.LFE1: - .long 0 - .byte 0,12,0,1,128,4,0,0 - .size .ffi_call_LINUX64,.-.ffi_call_LINUX64 - - .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 - .ascii "zR\0" # CIE Augmentation - .uleb128 0x1 # CIE Code Alignment Factor - .sleb128 -8 # CIE Data Alignment Factor - .byte 0x41 # CIE RA Column - .uleb128 0x1 # Augmentation size - .byte 0x14 # FDE Encoding (pcrel udata8) - .byte 0xc # DW_CFA_def_cfa - .uleb128 0x1 - .uleb128 0x0 - .align 3 -.LECIE1: -.LSFDE1: - .4byte .LEFDE1-.LASFDE1 # FDE Length -.LASFDE1: - .4byte .LASFDE1-.Lframe1 # FDE CIE offset - .8byte .LFB1-. # FDE initial location - .8byte .LFE1-.LFB1 # FDE address range - .uleb128 0x0 # Augmentation size - .byte 0x2 # DW_CFA_advance_loc1 - .byte .LCFI0-.LFB1 - .byte 0xd # DW_CFA_def_cfa_register - .uleb128 0x1c - .byte 0x11 # DW_CFA_offset_extended_sf - .uleb128 0x41 - .sleb128 -2 - .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 - .align 3 -.LEFDE1: -#endif diff --git a/libffi/src/powerpc/linux64_closure.S b/libffi/src/powerpc/linux64_closure.S deleted file mode 100644 index fa331db..0000000 --- a/libffi/src/powerpc/linux64_closure.S +++ /dev/null @@ -1,205 +0,0 @@ -#define LIBFFI_ASM -#include <fficonfig.h> -#include <ffi.h> - - .file "linux64_closure.S" - -#ifdef __powerpc64__ - .hidden ffi_closure_LINUX64, .ffi_closure_LINUX64 - .globl ffi_closure_LINUX64, .ffi_closure_LINUX64 - .section ".opd","aw" - .align 3 -ffi_closure_LINUX64: - .quad .ffi_closure_LINUX64,.TOC.@tocbase,0 - .size ffi_closure_LINUX64,24 - .type .ffi_closure_LINUX64,@function - .text -.ffi_closure_LINUX64: -.LFB1: - # save general regs into parm save area - std %r3, 48(%r1) - std %r4, 56(%r1) - std %r5, 64(%r1) - std %r6, 72(%r1) - mflr %r0 - - std %r7, 80(%r1) - std %r8, 88(%r1) - std %r9, 96(%r1) - std %r10, 104(%r1) - std %r0, 16(%r1) - - # mandatory 48 bytes special reg save area + 64 bytes parm save area - # + 16 bytes retval area + 13*8 bytes fpr save area + round to 16 - stdu %r1, -240(%r1) -.LCFI0: - - # next save fpr 1 to fpr 13 - stfd %f1, 128+(0*8)(%r1) - stfd %f2, 128+(1*8)(%r1) - stfd %f3, 128+(2*8)(%r1) - stfd %f4, 128+(3*8)(%r1) - stfd %f5, 128+(4*8)(%r1) - stfd %f6, 128+(5*8)(%r1) - stfd %f7, 128+(6*8)(%r1) - stfd %f8, 128+(7*8)(%r1) - stfd %f9, 128+(8*8)(%r1) - stfd %f10, 128+(9*8)(%r1) - stfd %f11, 128+(10*8)(%r1) - stfd %f12, 128+(11*8)(%r1) - stfd %f13, 128+(12*8)(%r1) - - # 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 parameter save area - # in the previous frame - addi %r5, %r1, 240 + 48 - - # now load up the pointer to the saved fpr registers */ - addi %r6, %r1, 128 - - # make the call - bl .ffi_closure_helper_LINUX64 -.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 - sldi %r3, %r3, 4 # now multiply return type by 16 - addi %r4, %r4, .Lret_type0 - .Lret - ld %r0, 240+16(%r1) - add %r3, %r3, %r4 # add contents of table to table address - mtctr %r3 - bctr # jump to it - -# 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 - -.Lret_type0: -# case FFI_TYPE_VOID - mtlr %r0 - addi %r1, %r1, 240 - blr - nop -# case FFI_TYPE_INT - lwa %r3, 112+4(%r1) - mtlr %r0 - addi %r1, %r1, 240 - blr -# case FFI_TYPE_FLOAT - lfs %f1, 112+0(%r1) - mtlr %r0 - addi %r1, %r1, 240 - blr -# case FFI_TYPE_DOUBLE - lfd %f1, 112+0(%r1) - mtlr %r0 - addi %r1, %r1, 240 - blr -# case FFI_TYPE_LONGDOUBLE - lfd %f1, 112+0(%r1) - mtlr %r0 - lfd %f2, 112+8(%r1) - b .Lfinish -# case FFI_TYPE_UINT8 - lbz %r3, 112+7(%r1) - mtlr %r0 - addi %r1, %r1, 240 - blr -# case FFI_TYPE_SINT8 - lbz %r3, 112+7(%r1) - extsb %r3,%r3 - mtlr %r0 - b .Lfinish -# case FFI_TYPE_UINT16 - lhz %r3, 112+6(%r1) - mtlr %r0 -.Lfinish: - addi %r1, %r1, 240 - blr -# case FFI_TYPE_SINT16 - lha %r3, 112+6(%r1) - mtlr %r0 - addi %r1, %r1, 240 - blr -# case FFI_TYPE_UINT32 - lwz %r3, 112+4(%r1) - mtlr %r0 - addi %r1, %r1, 240 - blr -# case FFI_TYPE_SINT32 - lwa %r3, 112+4(%r1) - mtlr %r0 - addi %r1, %r1, 240 - blr -# case FFI_TYPE_UINT64 - ld %r3, 112+0(%r1) - mtlr %r0 - addi %r1, %r1, 240 - blr -# case FFI_TYPE_SINT64 - ld %r3, 112+0(%r1) - mtlr %r0 - addi %r1, %r1, 240 - blr -# case FFI_TYPE_STRUCT - mtlr %r0 - addi %r1, %r1, 240 - blr - nop -# case FFI_TYPE_POINTER - ld %r3, 112+0(%r1) - mtlr %r0 - addi %r1, %r1, 240 - blr -# esac -.LFE1: - .long 0 - .byte 0,12,0,1,128,0,0,0 - .size .ffi_closure_LINUX64,.-.ffi_closure_LINUX64 - - .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 - .ascii "zR\0" # CIE Augmentation - .uleb128 0x1 # CIE Code Alignment Factor - .sleb128 -8 # CIE Data Alignment Factor - .byte 0x41 # CIE RA Column - .uleb128 0x1 # Augmentation size - .byte 0x14 # FDE Encoding (pcrel udata8) - .byte 0xc # DW_CFA_def_cfa - .uleb128 0x1 - .uleb128 0x0 - .align 3 -.LECIE1: -.LSFDE1: - .4byte .LEFDE1-.LASFDE1 # FDE Length -.LASFDE1: - .4byte .LASFDE1-.Lframe1 # FDE CIE offset - .8byte .LFB1-. # FDE initial location - .8byte .LFE1-.LFB1 # FDE address range - .uleb128 0x0 # Augmentation size - .byte 0x2 # DW_CFA_advance_loc1 - .byte .LCFI0-.LFB1 - .byte 0xe # DW_CFA_def_cfa_offset - .uleb128 240 - .byte 0x11 # DW_CFA_offset_extended_sf - .uleb128 0x41 - .sleb128 -2 - .align 3 -.LEFDE1: -#endif diff --git a/libffi/src/powerpc/ppc_closure.S b/libffi/src/powerpc/ppc_closure.S deleted file mode 100644 index dce9dab..0000000 --- a/libffi/src/powerpc/ppc_closure.S +++ /dev/null @@ -1,250 +0,0 @@ -#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) - - # 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) - - # 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 JUMPTARGET(ffi_closure_helper_SYSV) - - # 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 - addi %r5,%r1,112 # get pointer to results area - bl .Lget_ret_type0_addr # get pointer to .Lret_type0 into LR - mflr %r4 # move to r4 - slwi %r3,%r3,4 # now multiply return type by 16 - 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 - - nop - nop - nop -.Lget_ret_type0_addr: - blrl - -# case FFI_TYPE_VOID -.Lret_type0: - b .Lfinish - nop - nop - nop - -# case FFI_TYPE_INT -.Lret_type1: - lwz %r3,0(%r5) - b .Lfinish - nop - nop - -# case FFI_TYPE_FLOAT -.Lret_type2: - lfs %f1,0(%r5) - b .Lfinish - nop - nop - -# case FFI_TYPE_DOUBLE -.Lret_type3: - lfd %f1,0(%r5) - b .Lfinish - nop - nop - -# case FFI_TYPE_LONGDOUBLE -.Lret_type4: - lfd %f1,0(%r5) - b .Lfinish - nop - nop - -# case FFI_TYPE_UINT8 -.Lret_type5: - lbz %r3,3(%r5) - b .Lfinish - nop - nop - -# case FFI_TYPE_SINT8 -.Lret_type6: - lbz %r3,3(%r5) - extsb %r3,%r3 - b .Lfinish - nop - -# case FFI_TYPE_UINT16 -.Lret_type7: - lhz %r3,2(%r5) - b .Lfinish - nop - nop - -# case FFI_TYPE_SINT16 -.Lret_type8: - lha %r3,2(%r5) - b .Lfinish - nop - nop - -# case FFI_TYPE_UINT32 -.Lret_type9: - lwz %r3,0(%r5) - b .Lfinish - nop - nop - -# case FFI_TYPE_SINT32 -.Lret_type10: - lwz %r3,0(%r5) - b .Lfinish - nop - nop - -# case FFI_TYPE_UINT64 -.Lret_type11: - lwz %r3,0(%r5) - lwz %r4,4(%r5) - b .Lfinish - nop - -# case FFI_TYPE_SINT64 -.Lret_type12: - lwz %r3,0(%r5) - lwz %r4,4(%r5) - b .Lfinish - nop - -# case FFI_TYPE_STRUCT -.Lret_type13: - b .Lfinish - nop - nop - nop - -# case FFI_TYPE_POINTER -.Lret_type14: - lwz %r3,0(%r5) - b .Lfinish - nop - nop - -# case done -.Lfinish: - - lwz %r0,148(%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 0x2f # DW_CFA_GNU_negative_offset_extended - .uleb128 0x41 - .uleb128 0x1 - .align 2 -.LEFDE1: - -#endif diff --git a/libffi/src/powerpc/sysv.S b/libffi/src/powerpc/sysv.S deleted file mode 100644 index a7aaa3f..0000000 --- a/libffi/src/powerpc/sysv.S +++ /dev/null @@ -1,191 +0,0 @@ -/* ----------------------------------------------------------------------- - sysv.h - Copyright (c) 1998 Geoffrey Keating - - PowerPC Assembly glue. - - $Id: sysv.S,v 1.1.1.1 1998/11/29 16:48:16 green Exp $ - - 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 AUTHOR 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 JUMPTARGET(ffi_prep_args_SYSV) - - /* 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 - 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) - /* 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) - b L(done_return_value) -L(float_return_value): - stfs %f1,0(%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 0x2f /* DW_CFA_GNU_negative_offset_extended */ - .uleb128 0x41 - .uleb128 0x1 - .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 |