summaryrefslogtreecommitdiffstats
path: root/js/src/ctypes/libffi/src/powerpc/linux64_closure.S
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/ctypes/libffi/src/powerpc/linux64_closure.S')
-rw-r--r--js/src/ctypes/libffi/src/powerpc/linux64_closure.S552
1 files changed, 552 insertions, 0 deletions
diff --git a/js/src/ctypes/libffi/src/powerpc/linux64_closure.S b/js/src/ctypes/libffi/src/powerpc/linux64_closure.S
new file mode 100644
index 0000000000..d67e4bbbd1
--- /dev/null
+++ b/js/src/ctypes/libffi/src/powerpc/linux64_closure.S
@@ -0,0 +1,552 @@
+/* -----------------------------------------------------------------------
+ sysv.h - Copyright (c) 2003 Jakub Jelinek <jakub@redhat.com>
+ Copyright (c) 2008 Red Hat, Inc.
+
+ 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 AUTHORS OR COPYRIGHT
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ DEALINGS IN THE SOFTWARE.
+ ----------------------------------------------------------------------- */
+#define LIBFFI_ASM
+#include <fficonfig.h>
+#include <ffi.h>
+
+ .file "linux64_closure.S"
+
+#ifdef POWERPC64
+ FFI_HIDDEN (ffi_closure_LINUX64)
+ .globl ffi_closure_LINUX64
+ .text
+ .cfi_startproc
+# if _CALL_ELF == 2
+ffi_closure_LINUX64:
+ addis %r2, %r12, .TOC.-ffi_closure_LINUX64@ha
+ addi %r2, %r2, .TOC.-ffi_closure_LINUX64@l
+ .localentry ffi_closure_LINUX64, . - ffi_closure_LINUX64
+# else
+ .section ".opd","aw"
+ .align 3
+ffi_closure_LINUX64:
+# ifdef _CALL_LINUX
+ .quad .L.ffi_closure_LINUX64,.TOC.@tocbase,0
+ .type ffi_closure_LINUX64,@function
+ .text
+.L.ffi_closure_LINUX64:
+# else
+ FFI_HIDDEN (.ffi_closure_LINUX64)
+ .globl .ffi_closure_LINUX64
+ .quad .ffi_closure_LINUX64,.TOC.@tocbase,0
+ .size ffi_closure_LINUX64,24
+ .type .ffi_closure_LINUX64,@function
+ .text
+.ffi_closure_LINUX64:
+# endif
+# endif
+
+# if _CALL_ELF == 2
+# ifdef __VEC__
+# 32 byte special reg save area + 64 byte parm save area
+# + 128 byte retval area + 13*8 fpr save area + 12*16 vec save area + round to 16
+# define STACKFRAME 528
+# else
+# 32 byte special reg save area + 64 byte parm save area
+# + 64 byte retval area + 13*8 fpr save area + round to 16
+# define STACKFRAME 272
+# endif
+# define PARMSAVE 32
+# define RETVAL PARMSAVE+64
+# else
+# 48 bytes special reg save area + 64 bytes parm save area
+# + 16 bytes retval area + 13*8 bytes fpr save area + round to 16
+# define STACKFRAME 240
+# define PARMSAVE 48
+# define RETVAL PARMSAVE+64
+# endif
+
+# if _CALL_ELF == 2
+ ld %r12, FFI_TRAMPOLINE_SIZE(%r11) # closure->cif
+ mflr %r0
+ lwz %r12, 28(%r12) # cif->flags
+ mtcrf 0x40, %r12
+ addi %r12, %r1, PARMSAVE
+ bt 7, 0f
+ # Our caller has not allocated a parameter save area.
+ # We need to allocate one here and use it to pass gprs to
+ # ffi_closure_helper_LINUX64.
+ addi %r12, %r1, -STACKFRAME+PARMSAVE
+0:
+ # Save general regs into parm save area
+ std %r3, 0(%r12)
+ std %r4, 8(%r12)
+ std %r5, 16(%r12)
+ std %r6, 24(%r12)
+ std %r7, 32(%r12)
+ std %r8, 40(%r12)
+ std %r9, 48(%r12)
+ std %r10, 56(%r12)
+
+ # load up the pointer to the parm save area
+ mr %r7, %r12
+# else
+ # copy r2 to r11 and load TOC into r2
+ mr %r11, %r2
+ ld %r2, 16(%r2)
+
+ mflr %r0
+ # Save general regs into parm save area
+ # This is the parameter save area set up by our caller.
+ std %r3, PARMSAVE+0(%r1)
+ std %r4, PARMSAVE+8(%r1)
+ std %r5, PARMSAVE+16(%r1)
+ std %r6, PARMSAVE+24(%r1)
+ std %r7, PARMSAVE+32(%r1)
+ std %r8, PARMSAVE+40(%r1)
+ std %r9, PARMSAVE+48(%r1)
+ std %r10, PARMSAVE+56(%r1)
+
+ # load up the pointer to the parm save area
+ addi %r7, %r1, PARMSAVE
+# endif
+ std %r0, 16(%r1)
+
+ # closure->cif
+ ld %r3, FFI_TRAMPOLINE_SIZE(%r11)
+ # closure->fun
+ ld %r4, FFI_TRAMPOLINE_SIZE+8(%r11)
+ # closure->user_data
+ ld %r5, FFI_TRAMPOLINE_SIZE+16(%r11)
+
+.Ldoclosure:
+ # next save fpr 1 to fpr 13
+ stfd %f1, -104+(0*8)(%r1)
+ stfd %f2, -104+(1*8)(%r1)
+ stfd %f3, -104+(2*8)(%r1)
+ stfd %f4, -104+(3*8)(%r1)
+ stfd %f5, -104+(4*8)(%r1)
+ stfd %f6, -104+(5*8)(%r1)
+ stfd %f7, -104+(6*8)(%r1)
+ stfd %f8, -104+(7*8)(%r1)
+ stfd %f9, -104+(8*8)(%r1)
+ stfd %f10, -104+(9*8)(%r1)
+ stfd %f11, -104+(10*8)(%r1)
+ stfd %f12, -104+(11*8)(%r1)
+ stfd %f13, -104+(12*8)(%r1)
+
+ # load up the pointer to the saved fpr registers
+ addi %r8, %r1, -104
+
+# ifdef __VEC__
+ # load up the pointer to the saved vector registers
+ # 8 bytes padding for 16-byte alignment at -112(%r1)
+ addi %r9, %r8, -24
+ stvx %v13, 0, %r9
+ addi %r9, %r9, -16
+ stvx %v12, 0, %r9
+ addi %r9, %r9, -16
+ stvx %v11, 0, %r9
+ addi %r9, %r9, -16
+ stvx %v10, 0, %r9
+ addi %r9, %r9, -16
+ stvx %v9, 0, %r9
+ addi %r9, %r9, -16
+ stvx %v8, 0, %r9
+ addi %r9, %r9, -16
+ stvx %v7, 0, %r9
+ addi %r9, %r9, -16
+ stvx %v6, 0, %r9
+ addi %r9, %r9, -16
+ stvx %v5, 0, %r9
+ addi %r9, %r9, -16
+ stvx %v4, 0, %r9
+ addi %r9, %r9, -16
+ stvx %v3, 0, %r9
+ addi %r9, %r9, -16
+ stvx %v2, 0, %r9
+# endif
+
+ # load up the pointer to the result storage
+ addi %r6, %r1, -STACKFRAME+RETVAL
+
+ stdu %r1, -STACKFRAME(%r1)
+ .cfi_def_cfa_offset STACKFRAME
+ .cfi_offset 65, 16
+
+ # make the call
+# if defined _CALL_LINUX || _CALL_ELF == 2
+ bl ffi_closure_helper_LINUX64
+# else
+ bl .ffi_closure_helper_LINUX64
+# endif
+.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
+ ld %r0, STACKFRAME+16(%r1)
+ cmpldi %r3, FFI_V2_TYPE_SMALL_STRUCT
+ bge .Lsmall
+ mflr %r4 # move address of .Lret to r4
+ sldi %r3, %r3, 4 # now multiply return type by 16
+ addi %r4, %r4, .Lret_type0 - .Lret
+ 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, STACKFRAME
+ .cfi_def_cfa_offset 0
+ blr
+ .cfi_def_cfa_offset STACKFRAME
+ nop
+# case FFI_TYPE_INT
+# ifdef __LITTLE_ENDIAN__
+ lwa %r3, RETVAL+0(%r1)
+# else
+ lwa %r3, RETVAL+4(%r1)
+# endif
+ mtlr %r0
+ addi %r1, %r1, STACKFRAME
+ .cfi_def_cfa_offset 0
+ blr
+ .cfi_def_cfa_offset STACKFRAME
+# case FFI_TYPE_FLOAT
+ lfs %f1, RETVAL+0(%r1)
+ mtlr %r0
+ addi %r1, %r1, STACKFRAME
+ .cfi_def_cfa_offset 0
+ blr
+ .cfi_def_cfa_offset STACKFRAME
+# case FFI_TYPE_DOUBLE
+ lfd %f1, RETVAL+0(%r1)
+ mtlr %r0
+ addi %r1, %r1, STACKFRAME
+ .cfi_def_cfa_offset 0
+ blr
+ .cfi_def_cfa_offset STACKFRAME
+# case FFI_TYPE_LONGDOUBLE
+ lfd %f1, RETVAL+0(%r1)
+ mtlr %r0
+ lfd %f2, RETVAL+8(%r1)
+ b .Lfinish
+# case FFI_TYPE_UINT8
+# ifdef __LITTLE_ENDIAN__
+ lbz %r3, RETVAL+0(%r1)
+# else
+ lbz %r3, RETVAL+7(%r1)
+# endif
+ mtlr %r0
+ addi %r1, %r1, STACKFRAME
+ .cfi_def_cfa_offset 0
+ blr
+ .cfi_def_cfa_offset STACKFRAME
+# case FFI_TYPE_SINT8
+# ifdef __LITTLE_ENDIAN__
+ lbz %r3, RETVAL+0(%r1)
+# else
+ lbz %r3, RETVAL+7(%r1)
+# endif
+ extsb %r3,%r3
+ mtlr %r0
+ b .Lfinish
+# case FFI_TYPE_UINT16
+# ifdef __LITTLE_ENDIAN__
+ lhz %r3, RETVAL+0(%r1)
+# else
+ lhz %r3, RETVAL+6(%r1)
+# endif
+ mtlr %r0
+.Lfinish:
+ addi %r1, %r1, STACKFRAME
+ .cfi_def_cfa_offset 0
+ blr
+ .cfi_def_cfa_offset STACKFRAME
+# case FFI_TYPE_SINT16
+# ifdef __LITTLE_ENDIAN__
+ lha %r3, RETVAL+0(%r1)
+# else
+ lha %r3, RETVAL+6(%r1)
+# endif
+ mtlr %r0
+ addi %r1, %r1, STACKFRAME
+ .cfi_def_cfa_offset 0
+ blr
+ .cfi_def_cfa_offset STACKFRAME
+# case FFI_TYPE_UINT32
+# ifdef __LITTLE_ENDIAN__
+ lwz %r3, RETVAL+0(%r1)
+# else
+ lwz %r3, RETVAL+4(%r1)
+# endif
+ mtlr %r0
+ addi %r1, %r1, STACKFRAME
+ .cfi_def_cfa_offset 0
+ blr
+ .cfi_def_cfa_offset STACKFRAME
+# case FFI_TYPE_SINT32
+# ifdef __LITTLE_ENDIAN__
+ lwa %r3, RETVAL+0(%r1)
+# else
+ lwa %r3, RETVAL+4(%r1)
+# endif
+ mtlr %r0
+ addi %r1, %r1, STACKFRAME
+ .cfi_def_cfa_offset 0
+ blr
+ .cfi_def_cfa_offset STACKFRAME
+# case FFI_TYPE_UINT64
+ ld %r3, RETVAL+0(%r1)
+ mtlr %r0
+ addi %r1, %r1, STACKFRAME
+ .cfi_def_cfa_offset 0
+ blr
+ .cfi_def_cfa_offset STACKFRAME
+# case FFI_TYPE_SINT64
+ ld %r3, RETVAL+0(%r1)
+ mtlr %r0
+ addi %r1, %r1, STACKFRAME
+ .cfi_def_cfa_offset 0
+ blr
+ .cfi_def_cfa_offset STACKFRAME
+# case FFI_TYPE_STRUCT
+ mtlr %r0
+ addi %r1, %r1, STACKFRAME
+ .cfi_def_cfa_offset 0
+ blr
+ .cfi_def_cfa_offset STACKFRAME
+ nop
+# case FFI_TYPE_POINTER
+ ld %r3, RETVAL+0(%r1)
+ mtlr %r0
+ addi %r1, %r1, STACKFRAME
+ .cfi_def_cfa_offset 0
+ blr
+ .cfi_def_cfa_offset STACKFRAME
+# case FFI_V2_TYPE_VECTOR
+ addi %r3, %r1, RETVAL
+ lvx %v2, 0, %r3
+ mtlr %r0
+ b .Lfinish
+# case FFI_V2_TYPE_VECTOR_HOMOG
+ addi %r3, %r1, RETVAL
+ lvx %v2, 0, %r3
+ addi %r3, %r3, 16
+ b .Lmorevector
+# case FFI_V2_TYPE_FLOAT_HOMOG
+ lfs %f1, RETVAL+0(%r1)
+ lfs %f2, RETVAL+4(%r1)
+ lfs %f3, RETVAL+8(%r1)
+ b .Lmorefloat
+# case FFI_V2_TYPE_DOUBLE_HOMOG
+ lfd %f1, RETVAL+0(%r1)
+ lfd %f2, RETVAL+8(%r1)
+ lfd %f3, RETVAL+16(%r1)
+ lfd %f4, RETVAL+24(%r1)
+ mtlr %r0
+ lfd %f5, RETVAL+32(%r1)
+ lfd %f6, RETVAL+40(%r1)
+ lfd %f7, RETVAL+48(%r1)
+ lfd %f8, RETVAL+56(%r1)
+ addi %r1, %r1, STACKFRAME
+ .cfi_def_cfa_offset 0
+ blr
+ .cfi_def_cfa_offset STACKFRAME
+.Lmorevector:
+ lvx %v3, 0, %r3
+ addi %r3, %r3, 16
+ lvx %v4, 0, %r3
+ addi %r3, %r3, 16
+ lvx %v5, 0, %r3
+ mtlr %r0
+ addi %r3, %r3, 16
+ lvx %v6, 0, %r3
+ addi %r3, %r3, 16
+ lvx %v7, 0, %r3
+ addi %r3, %r3, 16
+ lvx %v8, 0, %r3
+ addi %r3, %r3, 16
+ lvx %v9, 0, %r3
+ addi %r1, %r1, STACKFRAME
+ .cfi_def_cfa_offset 0
+ blr
+ .cfi_def_cfa_offset STACKFRAME
+.Lmorefloat:
+ lfs %f4, RETVAL+12(%r1)
+ mtlr %r0
+ lfs %f5, RETVAL+16(%r1)
+ lfs %f6, RETVAL+20(%r1)
+ lfs %f7, RETVAL+24(%r1)
+ lfs %f8, RETVAL+28(%r1)
+ addi %r1, %r1, STACKFRAME
+ .cfi_def_cfa_offset 0
+ blr
+ .cfi_def_cfa_offset STACKFRAME
+.Lsmall:
+# ifdef __LITTLE_ENDIAN__
+ ld %r3,RETVAL+0(%r1)
+ mtlr %r0
+ ld %r4,RETVAL+8(%r1)
+ addi %r1, %r1, STACKFRAME
+ .cfi_def_cfa_offset 0
+ blr
+# else
+ # A struct smaller than a dword is returned in the low bits of r3
+ # ie. right justified. Larger structs are passed left justified
+ # in r3 and r4. The return value area on the stack will have
+ # the structs as they are usually stored in memory.
+ cmpldi %r3, FFI_V2_TYPE_SMALL_STRUCT + 7 # size 8 bytes?
+ neg %r5, %r3
+ ld %r3,RETVAL+0(%r1)
+ blt .Lsmalldown
+ mtlr %r0
+ ld %r4,RETVAL+8(%r1)
+ addi %r1, %r1, STACKFRAME
+ .cfi_def_cfa_offset 0
+ blr
+ .cfi_def_cfa_offset STACKFRAME
+.Lsmalldown:
+ addi %r5, %r5, FFI_V2_TYPE_SMALL_STRUCT + 7
+ mtlr %r0
+ sldi %r5, %r5, 3
+ addi %r1, %r1, STACKFRAME
+ .cfi_def_cfa_offset 0
+ srd %r3, %r3, %r5
+ blr
+# endif
+
+ .cfi_endproc
+# if _CALL_ELF == 2
+ .size ffi_closure_LINUX64,.-ffi_closure_LINUX64
+# else
+# ifdef _CALL_LINUX
+ .size ffi_closure_LINUX64,.-.L.ffi_closure_LINUX64
+# else
+ .long 0
+ .byte 0,12,0,1,128,0,0,0
+ .size .ffi_closure_LINUX64,.-.ffi_closure_LINUX64
+# endif
+# endif
+
+
+ FFI_HIDDEN (ffi_go_closure_linux64)
+ .globl ffi_go_closure_linux64
+ .text
+ .cfi_startproc
+# if _CALL_ELF == 2
+ffi_go_closure_linux64:
+ addis %r2, %r12, .TOC.-ffi_go_closure_linux64@ha
+ addi %r2, %r2, .TOC.-ffi_go_closure_linux64@l
+ .localentry ffi_go_closure_linux64, . - ffi_go_closure_linux64
+# else
+ .section ".opd","aw"
+ .align 3
+ffi_go_closure_linux64:
+# ifdef _CALL_LINUX
+ .quad .L.ffi_go_closure_linux64,.TOC.@tocbase,0
+ .type ffi_go_closure_linux64,@function
+ .text
+.L.ffi_go_closure_linux64:
+# else
+ FFI_HIDDEN (.ffi_go_closure_linux64)
+ .globl .ffi_go_closure_linux64
+ .quad .ffi_go_closure_linux64,.TOC.@tocbase,0
+ .size ffi_go_closure_linux64,24
+ .type .ffi_go_closure_linux64,@function
+ .text
+.ffi_go_closure_linux64:
+# endif
+# endif
+
+# if _CALL_ELF == 2
+ ld %r12, 8(%r11) # closure->cif
+ mflr %r0
+ lwz %r12, 28(%r12) # cif->flags
+ mtcrf 0x40, %r12
+ addi %r12, %r1, PARMSAVE
+ bt 7, 0f
+ # Our caller has not allocated a parameter save area.
+ # We need to allocate one here and use it to pass gprs to
+ # ffi_closure_helper_LINUX64.
+ addi %r12, %r1, -STACKFRAME+PARMSAVE
+0:
+ # Save general regs into parm save area
+ std %r3, 0(%r12)
+ std %r4, 8(%r12)
+ std %r5, 16(%r12)
+ std %r6, 24(%r12)
+ std %r7, 32(%r12)
+ std %r8, 40(%r12)
+ std %r9, 48(%r12)
+ std %r10, 56(%r12)
+
+ # load up the pointer to the parm save area
+ mr %r7, %r12
+# else
+ mflr %r0
+ # Save general regs into parm save area
+ # This is the parameter save area set up by our caller.
+ std %r3, PARMSAVE+0(%r1)
+ std %r4, PARMSAVE+8(%r1)
+ std %r5, PARMSAVE+16(%r1)
+ std %r6, PARMSAVE+24(%r1)
+ std %r7, PARMSAVE+32(%r1)
+ std %r8, PARMSAVE+40(%r1)
+ std %r9, PARMSAVE+48(%r1)
+ std %r10, PARMSAVE+56(%r1)
+
+ # load up the pointer to the parm save area
+ addi %r7, %r1, PARMSAVE
+# endif
+ std %r0, 16(%r1)
+
+ # closure->cif
+ ld %r3, 8(%r11)
+ # closure->fun
+ ld %r4, 16(%r11)
+ # user_data
+ mr %r5, %r11
+ b .Ldoclosure
+
+ .cfi_endproc
+# if _CALL_ELF == 2
+ .size ffi_go_closure_linux64,.-ffi_go_closure_linux64
+# else
+# ifdef _CALL_LINUX
+ .size ffi_go_closure_linux64,.-.L.ffi_go_closure_linux64
+# else
+ .long 0
+ .byte 0,12,0,1,128,0,0,0
+ .size .ffi_go_closure_linux64,.-.ffi_go_closure_linux64
+# endif
+# endif
+#endif
+
+#if (defined __ELF__ && defined __linux__) || _CALL_ELF == 2
+ .section .note.GNU-stack,"",@progbits
+#endif