+++ /dev/null
-## Process this with automake to create Makefile.in
-
-AUTOMAKE_OPTIONS = foreign
-
-SUFFIXES = .c .lo .o .s .S
-
-.deps/%.P: $(srcdir)/%.s
- @echo "Computing dependencies for $<..."
- @o='o'; \
- test -n "$o" && o='$$o'; \
- $(MKDEP) $< | sed "s,^\(.*\)\.o:,\1.$$o \1.l$$o $@:," > $@
-
-.deps/%.P: $(srcdir)/%.S
- @echo "Computing dependencies for $<..."
- @o='o'; \
- test -n "$o" && o='$$o'; \
- $(MKDEP) $< | sed "s,^\(.*\)\.o:,\1.$$o \1.l$$o $@:," > $@
-
-lib_LTLIBRARIES = libffi.la
-noinst_PROGRAMS = ffitest
-
-TARGET_SRC_MIPS_GCC = mips/ffi.c mips/o32.S mips/n32.S
-TARGET_SRC_MIPS_SGI = mips/ffi.c mips/o32.s mips/n32.s
-TARGET_SRC_X86 = x86/ffi.c x86/sysv.S
-TARGET_SRC_SPARC = sparc/ffi.c sparc/v8.S
-TARGET_SRC_ALPHA = alpha/ffi.c alpha/osf.S
-TARGET_SRC_M68K = m68k/ffi.c m68k/sysv.S
-TARGET_SRC_POWERPC = powerpc/ffi.c powerpc/sysv.S
-TARGET_SRC_ARM = arm/sysv.S arm/ffi.c
-TARGET_SRC_S390 = s390/sysv.S s390/ffi.c
-
-##libffi_la_SOURCES = debug.c prep_cif.c types.c $(TARGET_SRC_@TARGET@)
-## Work around automake deficiency
-libffi_la_common_SOURCES = debug.c prep_cif.c types.c
-if MIPS_GCC
-libffi_la_SOURCES = $(libffi_la_common_SOURCES) $(TARGET_SRC_MIPS_GCC)
-endif
-if MIPS_SGI
-libffi_la_SOURCES = $(libffi_la_common_SOURCES) $(TARGET_SRC_MIPS_SGI)
-endif
-if X86
-libffi_la_SOURCES = $(libffi_la_common_SOURCES) $(TARGET_SRC_X86)
-endif
-if SPARC
-libffi_la_SOURCES = $(libffi_la_common_SOURCES) $(TARGET_SRC_SPARC)
-endif
-if ALPHA
-libffi_la_SOURCES = $(libffi_la_common_SOURCES) $(TARGET_SRC_ALPHA)
-endif
-if M68K
-libffi_la_SOURCES = $(libffi_la_common_SOURCES) $(TARGET_SRC_M68K)
-endif
-if POWERPC
-libffi_la_SOURCES = $(libffi_la_common_SOURCES) $(TARGET_SRC_POWERPC)
-endif
-if ARM
-libffi_la_SOURCES = $(libffi_la_common_SOURCES) $(TARGET_SRC_ARM)
-endif
-
-libffi_la_LDFLAGS = -version-info 2:3:1
-ffitest_SOURCES = ffitest.c
-ffitest_LDADD = libffi.la
-
-EXTRA_DIST = mips/ffi.c mips/n32.S mips/n32.s mips/o32.S mips/o32.s \
-sparc/ffi.c sparc/v8.S \
-x86/ffi.c x86/sysv.S \
-alpha/ffi.c alpha/osf.S \
-m68k/ffi.c m68k/sysv.S \
-powerpc/ffi.c powerpc/sysv.S powerpc/asm.h \
-arm/ffi.c arm/sysv.S
-
-VPATH = @srcdir@:@srcdir@/@TARGETDIR@
-
-if MIPS_SGI
-
-%.o: %.s
- $(COMPILE) -c $<
-
-# This rule should only be used for compiling with the SGI assembler.
-%.lo: %.s
- $(LTCOMPILE) -c $<
-
-else
-
-# This is the general rule.
-%.o: %.S
- $(COMPILE) -c $<
-
-# This is the general rule.
-%.lo: %.S
- $(LTCOMPILE) -c $<
-
-endif
-
-INCLUDES = -I$(top_srcdir)/include -I../include
-
-test: ffitest
- ./ffitest
-
-lint:
- $(LINT) $(INCLUDES) $(srcdir)/*.c $(srcdir)/@TARGETDIR@/*.c
+++ /dev/null
-# Makefile.in generated automatically by automake 1.4a from Makefile.am
-
-# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
-# This Makefile.in is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
-# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
-# PARTICULAR PURPOSE.
-
-SHELL = @SHELL@
-
-srcdir = @srcdir@
-top_srcdir = @top_srcdir@
-prefix = @prefix@
-exec_prefix = @exec_prefix@
-
-bindir = @bindir@
-sbindir = @sbindir@
-libexecdir = @libexecdir@
-datadir = @datadir@
-sysconfdir = @sysconfdir@
-sharedstatedir = @sharedstatedir@
-localstatedir = @localstatedir@
-libdir = @libdir@
-infodir = @infodir@
-mandir = @mandir@
-includedir = @includedir@
-oldincludedir = /usr/include
-
-DESTDIR =
-
-pkgdatadir = $(datadir)/@PACKAGE@
-pkglibdir = $(libdir)/@PACKAGE@
-pkgincludedir = $(includedir)/@PACKAGE@
-
-top_builddir = ..
-
-ACLOCAL = @ACLOCAL@
-AUTOCONF = @AUTOCONF@
-AUTOMAKE = @AUTOMAKE@
-AUTOHEADER = @AUTOHEADER@
-
-INSTALL = @INSTALL@
-INSTALL_PROGRAM = @INSTALL_PROGRAM@
-INSTALL_DATA = @INSTALL_DATA@
-INSTALL_SCRIPT = @INSTALL_SCRIPT@
-INSTALL_STRIP_FLAG =
-transform = @program_transform_name@
-
-NORMAL_INSTALL = :
-PRE_INSTALL = :
-POST_INSTALL = :
-NORMAL_UNINSTALL = :
-PRE_UNINSTALL = :
-POST_UNINSTALL = :
-host_alias = @host_alias@
-host_triplet = @host@
-AMTAR = @AMTAR@
-AMTARFLAGS = @AMTARFLAGS@
-AS = @AS@
-CC = @CC@
-DLLTOOL = @DLLTOOL@
-EXEEXT = @EXEEXT@
-LD = @LD@
-LIBTOOL = @LIBTOOL@
-LN_S = @LN_S@
-MAINT = @MAINT@
-MAKEINFO = @MAKEINFO@
-NM = @NM@
-PACKAGE = @PACKAGE@
-RANLIB = @RANLIB@
-SHELL = @SHELL@
-TARGET = @TARGET@
-TARGETDIR = @TARGETDIR@
-USE_SYMBOL_UNDERSCORE = @USE_SYMBOL_UNDERSCORE@
-VERSION = @VERSION@
-
-
-AUTOMAKE_OPTIONS = foreign
-
-SUFFIXES = .c .lo .o .s .S
-
-lib_LTLIBRARIES = libffi.la
-noinst_PROGRAMS = ffitest
-
-TARGET_SRC_MIPS_GCC = mips/ffi.c mips/o32.S mips/n32.S
-TARGET_SRC_MIPS_SGI = mips/ffi.c mips/o32.s mips/n32.s
-TARGET_SRC_X86 = x86/ffi.c x86/sysv.S
-TARGET_SRC_SPARC = sparc/ffi.c sparc/v8.S
-TARGET_SRC_ALPHA = alpha/ffi.c alpha/osf.S
-TARGET_SRC_M68K = m68k/ffi.c m68k/sysv.S
-TARGET_SRC_POWERPC = powerpc/ffi.c powerpc/sysv.S
-TARGET_SRC_ARM = arm/sysv.S arm/ffi.c
-
-libffi_la_common_SOURCES = debug.c prep_cif.c types.c
-@MIPS_GCC_TRUE@libffi_la_SOURCES = @MIPS_GCC_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_MIPS_GCC)
-@MIPS_SGI_TRUE@libffi_la_SOURCES = @MIPS_SGI_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_MIPS_SGI)
-@X86_TRUE@libffi_la_SOURCES = @X86_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_X86)
-@SPARC_TRUE@libffi_la_SOURCES = @SPARC_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_SPARC)
-@ALPHA_TRUE@libffi_la_SOURCES = @ALPHA_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_ALPHA)
-@M68K_TRUE@libffi_la_SOURCES = @M68K_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_M68K)
-@POWERPC_TRUE@libffi_la_SOURCES = @POWERPC_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_POWERPC)
-@ARM_TRUE@libffi_la_SOURCES = @ARM_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_ARM)
-
-libffi_la_LDFLAGS = -version-info 2:3:1
-ffitest_SOURCES = ffitest.c
-ffitest_LDADD = libffi.la
-
-EXTRA_DIST = mips/ffi.c mips/n32.S mips/n32.s mips/o32.S mips/o32.s \
-sparc/ffi.c sparc/v8.S \
-x86/ffi.c x86/sysv.S \
-alpha/ffi.c alpha/osf.S \
-m68k/ffi.c m68k/sysv.S \
-powerpc/ffi.c powerpc/sysv.S powerpc/asm.h \
-arm/ffi.c arm/sysv.S
-
-
-VPATH = @srcdir@:@srcdir@/@TARGETDIR@
-
-INCLUDES = -I$(top_srcdir)/include -I../include
-subdir = src
-mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
-CONFIG_HEADER = ../fficonfig.h
-CONFIG_CLEAN_FILES =
-LTLIBRARIES = $(lib_LTLIBRARIES)
-
-
-DEFS = @DEFS@ -I. -I$(srcdir) -I..
-CPPFLAGS = @CPPFLAGS@
-LDFLAGS = @LDFLAGS@
-LIBS = @LIBS@
-libffi_la_LIBADD =
-@ALPHA_TRUE@am_libffi_la_OBJECTS = debug.lo prep_cif.lo types.lo ffi.lo \
-@ALPHA_TRUE@osf.lo
-@ARM_TRUE@am_libffi_la_OBJECTS = debug.lo prep_cif.lo types.lo sysv.lo \
-@ARM_TRUE@ffi.lo
-@M68K_TRUE@am_libffi_la_OBJECTS = debug.lo prep_cif.lo types.lo ffi.lo \
-@M68K_TRUE@sysv.lo
-@MIPS_GCC_TRUE@am_libffi_la_OBJECTS = debug.lo prep_cif.lo types.lo \
-@MIPS_GCC_TRUE@ffi.lo o32.lo n32.lo
-@MIPS_SGI_TRUE@am_libffi_la_OBJECTS = debug.lo prep_cif.lo types.lo \
-@MIPS_SGI_TRUE@ffi.lo o32.lo n32.lo
-@POWERPC_TRUE@am_libffi_la_OBJECTS = debug.lo prep_cif.lo types.lo \
-@POWERPC_TRUE@ffi.lo sysv.lo
-@SPARC_TRUE@am_libffi_la_OBJECTS = debug.lo prep_cif.lo types.lo ffi.lo \
-@SPARC_TRUE@v8.lo
-@X86_TRUE@am_libffi_la_OBJECTS = debug.lo prep_cif.lo types.lo ffi.lo \
-@X86_TRUE@sysv.lo
-libffi_la_OBJECTS = $(am_libffi_la_OBJECTS)
-noinst_PROGRAMS = ffitest$(EXEEXT)
-PROGRAMS = $(noinst_PROGRAMS)
-
-am_ffitest_OBJECTS = ffitest.o
-ffitest_OBJECTS = $(am_ffitest_OBJECTS)
-ffitest_DEPENDENCIES = libffi.la
-ffitest_LDFLAGS =
-COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
-LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
-CFLAGS = @CFLAGS@
-CCLD = $(CC)
-LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
-DIST_SOURCES = $(libffi_la_SOURCES) $(ffitest_SOURCES)
-DIST_COMMON = Makefile.am Makefile.in
-
-
-DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
-
-GZIP_ENV = --best
-SOURCES = $(libffi_la_SOURCES) $(ffitest_SOURCES)
-OBJECTS = $(am_libffi_la_OBJECTS) $(am_ffitest_OBJECTS)
-
-all: all-redirect
-.SUFFIXES:
-.SUFFIXES: .S .c .lo .o .s
-$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
- cd $(top_srcdir) && $(AUTOMAKE) --cygnus src/Makefile
-
-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
- cd $(top_builddir) \
- && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
-
-
-mostlyclean-libLTLIBRARIES:
-
-clean-libLTLIBRARIES:
- -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
-
-distclean-libLTLIBRARIES:
-
-maintainer-clean-libLTLIBRARIES:
-
-install-libLTLIBRARIES: $(lib_LTLIBRARIES)
- @$(NORMAL_INSTALL)
- $(mkinstalldirs) $(DESTDIR)$(libdir)
- @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
- if test -f $$p; then \
- echo "$(LIBTOOL) --mode=install $(INSTALL) $$p $(DESTDIR)$(libdir)/$$p"; \
- $(LIBTOOL) --mode=install $(INSTALL) $$p $(DESTDIR)$(libdir)/$$p; \
- else :; fi; \
- done
-
-uninstall-libLTLIBRARIES:
- @$(NORMAL_UNINSTALL)
- @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
- echo " $(LIBTOOL) --mode=uninstall rm -f $(DESTDIR)$(libdir)/$$p"; \
- $(LIBTOOL) --mode=uninstall rm -f $(DESTDIR)$(libdir)/$$p; \
- done
-
-mostlyclean-compile:
- -rm -f *.o core *.core
-
-clean-compile:
-
-distclean-compile:
- -rm -f *.tab.c
-
-maintainer-clean-compile:
-
-mostlyclean-libtool:
- -rm -f *.lo
-
-clean-libtool:
- -rm -rf .libs _libs
-
-distclean-libtool:
-
-maintainer-clean-libtool:
-ffi.lo: alpha/ffi.c
-osf.lo: alpha/osf.S
-sysv.lo: arm/sysv.S
-o32.lo: mips/o32.S
-n32.lo: mips/n32.S
-v8.lo: sparc/v8.S
-
-libffi.la: $(libffi_la_OBJECTS) $(libffi_la_DEPENDENCIES)
- $(LINK) -rpath $(libdir) $(libffi_la_LDFLAGS) $(libffi_la_OBJECTS) $(libffi_la_LIBADD) $(LIBS)
-
-mostlyclean-noinstPROGRAMS:
-
-clean-noinstPROGRAMS:
- -test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS)
-
-distclean-noinstPROGRAMS:
-
-maintainer-clean-noinstPROGRAMS:
-
-ffitest$(EXEEXT): $(ffitest_OBJECTS) $(ffitest_DEPENDENCIES)
- @rm -f ffitest$(EXEEXT)
- $(LINK) $(ffitest_LDFLAGS) $(ffitest_OBJECTS) $(ffitest_LDADD) $(LIBS)
-.S.o:
- $(COMPILE) -c $<
-.S.lo:
- $(LTCOMPILE) -c -o $@ $<
-.c.o:
- $(COMPILE) -c $<
-.c.lo:
- $(LTCOMPILE) -c -o $@ $<
-.s.o:
- $(COMPILE) -c $<
-.s.lo:
- $(LTCOMPILE) -c -o $@ $<
-
-tags: TAGS
-
-ID: $(HEADERS) $(SOURCES) $(LISP)
- list='$(SOURCES) $(HEADERS)'; \
- unique=`for i in $$list; do echo $$i; done | \
- awk ' { files[$$0] = 1; } \
- END { for (i in files) print i; }'`; \
- here=`pwd` && cd $(srcdir) \
- && mkid -f$$here/ID $$unique $(LISP)
-
-TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP)
- tags=; \
- here=`pwd`; \
- list='$(SOURCES) $(HEADERS)'; \
- unique=`for i in $$list; do echo $$i; done | \
- awk ' { files[$$0] = 1; } \
- END { for (i in files) print i; }'`; \
- test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
- || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS)
-
-mostlyclean-tags:
-
-clean-tags:
-
-distclean-tags:
- -rm -f TAGS ID
-
-maintainer-clean-tags:
-
-distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
-
-distdir: $(DISTFILES)
- $(mkinstalldirs) $(distdir)/alpha $(distdir)/arm $(distdir)/m68k \
- $(distdir)/mips $(distdir)/powerpc $(distdir)/sparc \
- $(distdir)/x86
- @for file in $(DISTFILES); do \
- if test -f $$file; then d=.; else d=$(srcdir); fi; \
- if test -d $$d/$$file; then \
- cp -pr $$d/$$file $(distdir)/$$file; \
- else \
- test -f $(distdir)/$$file \
- || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
- || cp -p $$d/$$file $(distdir)/$$file || :; \
- fi; \
- done
-info-am:
-info: info-am
-dvi-am:
-dvi: dvi-am
-check-am:
-check: check-am
-installcheck-am:
-installcheck: installcheck-am
-install-info-am:
-install-info: install-info-am
-install-exec-am: install-libLTLIBRARIES
-install-exec: install-exec-am
-
-install-data-am:
-install-data: install-data-am
-
-install-am: all-am
- @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
-install: install-am
-uninstall-am: uninstall-libLTLIBRARIES
-uninstall: uninstall-am
-all-am: Makefile $(LTLIBRARIES) $(PROGRAMS)
-all-redirect: all-am
-install-strip:
- $(MAKE) $(AM_MAKEFLAGS) INSTALL_STRIP_FLAG=-s install
-installdirs:
- $(mkinstalldirs) $(DESTDIR)$(libdir)
-
-
-mostlyclean-generic:
-
-clean-generic:
-
-distclean-generic:
- -rm -f Makefile $(CONFIG_CLEAN_FILES)
- -rm -f config.cache config.log stamp-h stamp-h[0-9]*
-
-maintainer-clean-generic:
-mostlyclean-am: mostlyclean-libLTLIBRARIES mostlyclean-compile \
- mostlyclean-libtool mostlyclean-noinstPROGRAMS \
- mostlyclean-tags mostlyclean-generic
-
-mostlyclean: mostlyclean-am
-
-clean-am: clean-libLTLIBRARIES clean-compile clean-libtool \
- clean-noinstPROGRAMS clean-tags clean-generic \
- mostlyclean-am
-
-clean: clean-am
-
-distclean-am: distclean-libLTLIBRARIES distclean-compile \
- distclean-libtool distclean-noinstPROGRAMS \
- distclean-tags distclean-generic clean-am
- -rm -f libtool
-
-distclean: distclean-am
-
-maintainer-clean-am: maintainer-clean-libLTLIBRARIES \
- maintainer-clean-compile maintainer-clean-libtool \
- maintainer-clean-noinstPROGRAMS maintainer-clean-tags \
- maintainer-clean-generic distclean-am
- @echo "This command is intended for maintainers to use;"
- @echo "it deletes files that may require special tools to rebuild."
-
-maintainer-clean: maintainer-clean-am
-
-.PHONY: mostlyclean-libLTLIBRARIES distclean-libLTLIBRARIES \
-clean-libLTLIBRARIES maintainer-clean-libLTLIBRARIES \
-uninstall-libLTLIBRARIES install-libLTLIBRARIES mostlyclean-compile \
-distclean-compile clean-compile maintainer-clean-compile \
-mostlyclean-libtool distclean-libtool clean-libtool \
-maintainer-clean-libtool mostlyclean-noinstPROGRAMS \
-distclean-noinstPROGRAMS clean-noinstPROGRAMS \
-maintainer-clean-noinstPROGRAMS tags mostlyclean-tags distclean-tags \
-clean-tags maintainer-clean-tags distdir info-am info dvi-am dvi check \
-check-am installcheck-am installcheck install-info-am install-info \
-install-exec-am install-exec install-data-am install-data install-am \
-install uninstall-am uninstall all-redirect all-am all install-strip \
-installdirs mostlyclean-generic distclean-generic clean-generic \
-maintainer-clean-generic clean mostlyclean distclean maintainer-clean
-
-
-.deps/%.P: $(srcdir)/%.s
- @echo "Computing dependencies for $<..."
- @o='o'; \
- test -n "$o" && o='$$o'; \
- $(MKDEP) $< | sed "s,^\(.*\)\.o:,\1.$$o \1.l$$o $@:," > $@
-
-.deps/%.P: $(srcdir)/%.S
- @echo "Computing dependencies for $<..."
- @o='o'; \
- test -n "$o" && o='$$o'; \
- $(MKDEP) $< | sed "s,^\(.*\)\.o:,\1.$$o \1.l$$o $@:," > $@
-
-@MIPS_SGI_TRUE@%.o: %.s
-@MIPS_SGI_TRUE@ $(COMPILE) -c $<
-
-# This rule should only be used for compiling with the SGI assembler.
-@MIPS_SGI_TRUE@%.lo: %.s
-@MIPS_SGI_TRUE@ $(LTCOMPILE) -c $<
-
-# This is the general rule.
-@MIPS_SGI_FALSE@%.o: %.S
-@MIPS_SGI_FALSE@ $(COMPILE) -c $<
-
-# This is the general rule.
-@MIPS_SGI_FALSE@%.lo: %.S
-@MIPS_SGI_FALSE@ $(LTCOMPILE) -c $<
-
-test: ffitest
- ./ffitest
-
-lint:
- $(LINT) $(INCLUDES) $(srcdir)/*.c $(srcdir)/@TARGETDIR@/*.c
-
-# Tell versions [3.59,3.63) of GNU make to not export all variables.
-# Otherwise a system limit (for SysV at least) may be exceeded.
-.NOEXPORT:
+++ /dev/null
-/* -----------------------------------------------------------------------
- ffi.c - Copyright (c) 1998 Cygnus Solutions
-
- Alpha Foreign Function Interface
-
- 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.
- ----------------------------------------------------------------------- */
-
-#include <ffi.h>
-#include <ffi_common.h>
-
-#include <stdlib.h>
-
-extern void ffi_call_osf(void *, unsigned long, unsigned, void *, void (*)());
-extern void ffi_closure_osf(void);
-
-
-ffi_status
-ffi_prep_cif_machdep(ffi_cif *cif)
-{
- /* Adjust cif->bytes to represent a minimum 6 words for the temporary
- register argument loading area. */
- if (cif->bytes < 6*SIZEOF_ARG)
- cif->bytes = 6*SIZEOF_ARG;
-
- /* Set the return type flag */
- switch (cif->rtype->type)
- {
- case FFI_TYPE_STRUCT:
- case FFI_TYPE_FLOAT:
- case FFI_TYPE_DOUBLE:
- cif->flags = cif->rtype->type;
- break;
-
- default:
- cif->flags = FFI_TYPE_INT;
- break;
- }
-
- return FFI_OK;
-}
-
-void
-ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
-{
- unsigned long *stack, *argp;
- long i, avn;
- ffi_type **arg_types;
-
- FFI_ASSERT (cif->abi == FFI_OSF);
-
- /* 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->flags == FFI_TYPE_STRUCT)
- rvalue = alloca(cif->rtype->size);
-
- /* Allocate the space for the arguments, plus 4 words of temp
- space for ffi_call_osf. */
- argp = stack = alloca(cif->bytes + 4*SIZEOF_ARG);
-
- if (cif->flags == FFI_TYPE_STRUCT)
- *(void **) argp++ = rvalue;
-
- i = 0;
- avn = cif->nargs;
- arg_types = cif->arg_types;
-
- while (i < avn)
- {
- switch ((*arg_types)->type)
- {
- case FFI_TYPE_SINT8:
- *(SINT64 *) argp = *(SINT8 *)(* avalue);
- break;
-
- case FFI_TYPE_UINT8:
- *(SINT64 *) argp = *(UINT8 *)(* avalue);
- break;
-
- case FFI_TYPE_SINT16:
- *(SINT64 *) argp = *(SINT16 *)(* avalue);
- break;
-
- case FFI_TYPE_UINT16:
- *(SINT64 *) argp = *(UINT16 *)(* avalue);
- break;
-
- case FFI_TYPE_SINT32:
- case FFI_TYPE_UINT32:
- /* Note that unsigned 32-bit quantities are sign extended. */
- *(SINT64 *) argp = *(SINT32 *)(* avalue);
- break;
-
- case FFI_TYPE_SINT64:
- case FFI_TYPE_UINT64:
- case FFI_TYPE_POINTER:
- *(UINT64 *) argp = *(UINT64 *)(* avalue);
- break;
-
- case FFI_TYPE_FLOAT:
- if (argp - stack < 6)
- {
- /* Note the conversion -- all the fp regs are loaded as
- doubles. The in-register format is the same. */
- *(double *) argp = *(float *)(* avalue);
- }
- else
- *(float *) argp = *(float *)(* avalue);
- break;
-
- case FFI_TYPE_DOUBLE:
- *(double *) argp = *(double *)(* avalue);
- break;
-
- case FFI_TYPE_STRUCT:
- memcpy(argp, *avalue, (*arg_types)->size);
- break;
-
- default:
- FFI_ASSERT(0);
- }
-
- argp += ALIGN((*arg_types)->size, SIZEOF_ARG) / SIZEOF_ARG;
- i++, arg_types++, avalue++;
- }
-
- ffi_call_osf(stack, cif->bytes, cif->flags, rvalue, fn);
-}
-
-
-ffi_status
-ffi_prep_closure (ffi_closure* closure,
- ffi_cif* cif,
- void (*fun)(ffi_cif*, void*, void**, void*),
- void *user_data)
-{
- unsigned int *tramp;
-
- FFI_ASSERT (cif->abi == FFI_OSF);
-
- tramp = (unsigned int *) &closure->tramp[0];
- tramp[0] = 0x47fb0401; /* mov $27,$1 */
- tramp[1] = 0xa77b0010; /* ldq $27,16($27) */
- tramp[2] = 0x6bfb0000; /* jmp $31,($27),0 */
- tramp[3] = 0x47ff041f; /* nop */
- *(void **) &tramp[4] = ffi_closure_osf;
-
- closure->cif = cif;
- closure->fun = fun;
- closure->user_data = user_data;
-
- /* Flush the Icache. */
- asm volatile ("imb" : : : "memory");
-
- return FFI_OK;
-}
-
-int
-ffi_closure_osf_inner(ffi_closure *closure, void *rvalue, unsigned long *argp)
-{
- ffi_cif *cif;
- void **avalue;
- ffi_type **arg_types;
- long i, avn, argn;
-
- cif = closure->cif;
- avalue = alloca(cif->nargs * sizeof(void *));
-
- argn = 0;
-
- /* Copy the caller's structure return address to that the closure
- returns the data directly to the caller. */
- if (cif->flags == FFI_TYPE_STRUCT)
- {
- rvalue = (void *) argp[0];
- argn = 1;
- }
-
- 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:
- case FFI_TYPE_SINT16:
- case FFI_TYPE_UINT16:
- case FFI_TYPE_SINT32:
- case FFI_TYPE_UINT32:
- case FFI_TYPE_SINT64:
- case FFI_TYPE_UINT64:
- case FFI_TYPE_POINTER:
- case FFI_TYPE_STRUCT:
- avalue[i] = &argp[argn];
- break;
-
- case FFI_TYPE_FLOAT:
- if (argn < 6)
- {
- /* Floats coming from registers need conversion from double
- back to float format. */
- *(float *)&argp[argn - 6] = *(double *)&argp[argn - 6];
- avalue[i] = &argp[argn - 6];
- }
- else
- avalue[i] = &argp[argn];
- break;
-
- case FFI_TYPE_DOUBLE:
- avalue[i] = &argp[argn - (argn < 6 ? 6 : 0)];
- break;
-
- default:
- FFI_ASSERT(0);
- }
-
- argn += ALIGN(arg_types[i]->size, SIZEOF_ARG) / SIZEOF_ARG;
- i++;
- }
-
- /* Invoke the closure. */
- (closure->fun) (cif, rvalue, avalue, closure->user_data);
-
- /* Tell ffi_closure_osf how to perform return type promotions. */
- return cif->rtype->type;
-}
+++ /dev/null
-/* -----------------------------------------------------------------------
- osf.S - Copyright (c) 1998 Cygnus Solutions
-
- Alpha/OSF Foreign Function Interface
-
- 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.
- ----------------------------------------------------------------------- */
-
-#define LIBFFI_ASM
-#include <ffi.h>
-
- .arch ev6
- .text
-
-/* ffi_call_osf (void *args, unsigned long bytes, unsigned flags,
- void *raddr, void (*fnaddr)());
-
- Bit o trickiness here -- ARGS+BYTES is the base of the stack frame
- for this function. This has been allocated by ffi_call. We also
- deallocate some of the stack that has been alloca'd. */
-
- .align 3
- .globl ffi_call_osf
- .ent ffi_call_osf
-ffi_call_osf:
- .frame $15, 32, $26, 0
- .mask 0x4008000, -32
- addq $16,$17,$1
- mov $16, $30
- stq $26, 0($1)
- stq $15, 8($1)
- stq $18, 16($1)
- mov $1, $15
- .prologue 0
-
- stq $19, 24($1)
- mov $20, $27
-
- # Load up all of the (potential) argument registers.
- ldq $16, 0($30)
- ldt $f16, 0($30)
- ldt $f17, 8($30)
- ldq $17, 8($30)
- ldt $f18, 16($30)
- ldq $18, 16($30)
- ldt $f19, 24($30)
- ldq $19, 24($30)
- ldt $f20, 32($30)
- ldq $20, 32($30)
- ldt $f21, 40($30)
- ldq $21, 40($30)
-
- # Deallocate the register argument area.
- lda $30, 48($30)
-
- jsr $26, ($27), 0
- ldgp $29, 0($26)
-
- # If the return value pointer is NULL, assume no return value.
- ldq $19, 24($15)
- ldq $18, 16($15)
- ldq $26, 0($15)
- beq $19, $noretval
-
- # Store the return value out in the proper type.
- cmpeq $18, FFI_TYPE_INT, $1
- bne $1, $retint
- cmpeq $18, FFI_TYPE_FLOAT, $2
- bne $2, $retfloat
- cmpeq $18, FFI_TYPE_DOUBLE, $3
- bne $3, $retdouble
-
-$noretval:
- ldq $15, 8($15)
- ret
-
-$retint:
- stq $0, 0($19)
- nop
- ldq $15, 8($15)
- ret
-
-$retfloat:
- sts $f0, 0($19)
- nop
- ldq $15, 8($15)
- ret
-
-$retdouble:
- stt $f0, 0($19)
- nop
- ldq $15, 8($15)
- ret
-
- .end ffi_call_osf
-
-/* ffi_closure_osf(...)
-
- Receives the closure argument in $1. */
-
- .align 3
- .globl ffi_closure_osf
- .ent ffi_closure_osf
-ffi_closure_osf:
- .frame $30, 16*8, $26, 0
- .mask 0x4000000, -16*8
- ldgp $29, 0($27)
- subq $30, 16*8, $30
- stq $26, 0($30)
- .prologue 1
-
- # Store all of the potential argument registers in va_list format.
- stt $f16, 4*8($30)
- stt $f17, 5*8($30)
- stt $f18, 6*8($30)
- stt $f19, 7*8($30)
- stt $f20, 8*8($30)
- stt $f21, 9*8($30)
- stq $16, 10*8($30)
- stq $17, 11*8($30)
- stq $18, 12*8($30)
- stq $19, 13*8($30)
- stq $20, 14*8($30)
- stq $21, 15*8($30)
-
- # Call ffi_closure_osf_inner to do the bulk of the work.
- mov $1, $16
- lda $17, 2*8($30)
- lda $18, 10*8($30)
- jsr $26, ffi_closure_osf_inner
- ldgp $29, 0($26)
- ldq $26, 0($30)
-
- # Load up the return value in the proper type.
- lda $1, $load_table
- s4addq $0, $1, $1
- ldl $1, 0($1)
- addq $1, $29, $1
- jmp $31, ($1), $load_32
-
- .align 4
-$load_none:
- addq $30, 16*8, $30
- ret
-
- .align 4
-$load_float:
- lds $f0, 16($30)
- nop
- addq $30, 16*8, $30
- ret
-
- .align 4
-$load_double:
- ldt $f0, 16($30)
- nop
- addq $30, 16*8, $30
- ret
-
- .align 4
-$load_u8:
-#ifdef __alpha_bwx__
- ldbu $0, 16($30)
- nop
-#else
- ldq $0, 16($30)
- and $0, 255, $0
-#endif
- addq $30, 16*8, $30
- ret
-
- .align 4
-$load_s8:
-#ifdef __alpha_bwx__
- ldbu $0, 16($30)
- sextb $0, $0
-#else
- ldq $0, 16($30)
- sll $0, 56, $0
- sra $0, 56, $0
-#endif
- addq $30, 16*8, $30
- ret
-
- .align 4
-$load_u16:
-#ifdef __alpha_bwx__
- ldwu $0, 16($30)
- nop
-#else
- ldq $0, 16($30)
- zapnot $0, 3, $0
-#endif
- addq $30, 16*8, $30
- ret
-
- .align 4
-$load_s16:
-#ifdef __alpha_bwx__
- ldwu $0, 16($30)
- sextw $0, $0
-#else
- ldq $0, 16($30)
- sll $0, 48, $0
- sra $0, 48, $0
-#endif
- addq $30, 16*8, $30
- ret
-
- .align 4
-$load_32:
- ldl $0, 16($30)
- nop
- addq $30, 16*8, $30
- ret
-
- .align 4
-$load_64:
- ldq $0, 16($30)
- nop
- addq $30, 16*8, $30
- ret
-
- .end ffi_closure_osf
-
-.section .rodata
-$load_table:
- .gprel32 $load_none # FFI_TYPE_VOID
- .gprel32 $load_32 # FFI_TYPE_INT
- .gprel32 $load_float # FFI_TYPE_FLOAT
- .gprel32 $load_double # FFI_TYPE_DOUBLE
- .gprel32 $load_double # FFI_TYPE_LONGDOUBLE
- .gprel32 $load_u8 # FFI_TYPE_UINT8
- .gprel32 $load_s8 # FFI_TYPE_SINT8
- .gprel32 $load_u16 # FFI_TYPE_UINT16
- .gprel32 $load_s16 # FFI_TYPE_SINT16
- .gprel32 $load_32 # FFI_TYPE_UINT32
- .gprel32 $load_32 # FFI_TYPE_SINT32
- .gprel32 $load_64 # FFI_TYPE_UINT64
- .gprel32 $load_64 # FFI_TYPE_SINT64
- .gprel32 $load_none # FFI_TYPE_STRUCT
- .gprel32 $load_64 # FFI_TYPE_POINTER
-
-/* Assert that the table above is in sync with ffi.h. */
-
-#if FFI_TYPE_FLOAT != 2 \
- || FFI_TYPE_DOUBLE != 3 \
- || FFI_TYPE_UINT8 != 5 \
- || FFI_TYPE_SINT8 != 6 \
- || FFI_TYPE_UINT16 != 7 \
- || FFI_TYPE_SINT16 != 8 \
- || FFI_TYPE_UINT32 != 9 \
- || FFI_TYPE_SINT32 != 10 \
- || FFI_TYPE_UINT64 != 11 \
- || FFI_TYPE_SINT64 != 12 \
- || FFI_TYPE_STRUCT != 13 \
- || FFI_TYPE_POINTER != 14 \
- || FFI_TYPE_LAST != 14
-#error "osf.S out of sync with ffi.h"
-#endif
+++ /dev/null
-/* -----------------------------------------------------------------------
- ffi.c - Copyright (c) 1998 Cygnus Solutions
-
- ARM Foreign Function Interface
-
- 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.
- ----------------------------------------------------------------------- */
-
-#include <ffi.h>
-#include <ffi_common.h>
-
-#include <stdlib.h>
-
-/* ffi_prep_args is called by the assembly routine once stack space
- has been allocated for the function's arguments */
-
-/*@-exportheader@*/
-void ffi_prep_args(char *stack, extended_cif *ecif)
-/*@=exportheader@*/
-{
- register unsigned int i;
- register int tmp;
- register unsigned int avn;
- register void **p_argv;
- register char *argp;
- register ffi_type **p_arg;
-
- tmp = 0;
- argp = stack;
-
- if ( ecif->cif->rtype->type == FFI_TYPE_STRUCT ) {
- *(void **) argp = ecif->rvalue;
- argp += 4;
- }
-
- avn = ecif->cif->nargs;
- p_argv = ecif->avalue;
-
- for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
- (i != 0) && (avn != 0);
- i--, p_arg++)
- {
- size_t z;
-
- /* Align if necessary */
- if (((*p_arg)->alignment - 1) & (unsigned) argp) {
- argp = (char *) ALIGN(argp, (*p_arg)->alignment);
- }
-
- if (avn != 0)
- {
- avn--;
- z = (*p_arg)->size;
- if (z < sizeof(int))
- {
- z = sizeof(int);
- switch ((*p_arg)->type)
- {
- case FFI_TYPE_SINT8:
- *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
- break;
-
- case FFI_TYPE_UINT8:
- *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
- break;
-
- case FFI_TYPE_SINT16:
- *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
- break;
-
- case FFI_TYPE_UINT16:
- *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
- break;
-
- case FFI_TYPE_STRUCT:
- *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
- break;
-
- default:
- FFI_ASSERT(0);
- }
- }
- else if (z == sizeof(int))
- {
- *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
- }
- else
- {
- memcpy(argp, *p_argv, z);
- }
- p_argv++;
- argp += z;
- }
- }
-
- return;
-}
-
-/* Perform machine dependent cif processing */
-ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
-{
- /* Set the return type flag */
- switch (cif->rtype->type)
- {
- case FFI_TYPE_VOID:
- case FFI_TYPE_STRUCT:
- case FFI_TYPE_FLOAT:
- case FFI_TYPE_DOUBLE:
- cif->flags = (unsigned) cif->rtype->type;
- break;
-
- default:
- cif->flags = FFI_TYPE_INT;
- break;
- }
-
- return FFI_OK;
-}
-
-/*@-declundef@*/
-/*@-exportheader@*/
-extern void ffi_call_SYSV(void (*)(char *, extended_cif *),
- /*@out@*/ extended_cif *,
- unsigned, unsigned,
- /*@out@*/ unsigned *,
- 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)
- {
- case FFI_SYSV:
- /*@-usedef@*/
- ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes,
- cif->flags, ecif.rvalue, fn);
- /*@=usedef@*/
- break;
- default:
- FFI_ASSERT(0);
- break;
- }
-}
+++ /dev/null
-/* -----------------------------------------------------------------------
- sysv.S - Copyright (c) 1998 Cygnus Solutions
-
- ARM Foreign Function Interface
-
- 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.
- ----------------------------------------------------------------------- */
-
-#define LIBFFI_ASM
-#include <ffi.h>
-#ifdef HAVE_MACHINE_ASM_H
-#include <machine/asm.h>
-#else
-/* XXX these lose for some platforms, I'm sure. */
-#define CNAME(x) x
-#define ENTRY(x) .globl CNAME(x); .type CNAME(x),%function; CNAME(x):
-#endif
-
-.text
-
- # a1: ffi_prep_args
- # a2: &ecif
- # a3: cif->bytes
- # a4: fig->flags
- # sp+0: ecif.rvalue
- # sp+4: fn
-
- # This assumes we are using gas.
-ENTRY(ffi_call_SYSV)
- # Save registers
- stmfd sp!, {a1-a4, fp, lr}
- mov fp, sp
-
- # Make room for all of the new args.
- sub sp, fp, a3
-
- # Place all of the ffi_prep_args in position
- mov ip, a1
- mov a1, sp
- # a2 already set
-
- # And call
- mov lr, pc
- mov pc, ip
-
- # move first 4 parameters in registers
- ldr a1, [sp, #0]
- ldr a2, [sp, #4]
- ldr a3, [sp, #8]
- ldr a4, [sp, #12]
-
- # and adjust stack
- ldr ip, [fp, #8]
- cmp ip, #16
- movge ip, #16
- add sp, sp, ip
-
- # call function
- mov lr, pc
- ldr pc, [fp, #28]
-
- # Remove the space we pushed for the args
- mov sp, fp
-
- # Load a3 with the pointer to storage for the return value
- ldr a3, [sp, #24]
-
- # Load a4 with the return type code
- ldr a4, [sp, #12]
-
- # If the return value pointer is NULL, assume no return value.
- cmp a3, #0
- beq epilogue
-
-# return INT
- cmp a4, #FFI_TYPE_INT
- streq a1, [a3]
- beq epilogue
-
-# return FLOAT
- cmp a4, #FFI_TYPE_FLOAT
- stfeqs f0, [a3]
- beq epilogue
-
-# return DOUBLE or LONGDOUBLE
- cmp a4, #FFI_TYPE_DOUBLE
- stfeqd f0, [a3]
-
-epilogue:
- ldmfd sp!, {a1-a4, fp, pc}
-
-.ffi_call_SYSV_end:
- .size CNAME(ffi_call_SYSV),.ffi_call_SYSV_end-CNAME(ffi_call_SYSV)
-
+++ /dev/null
-/* -----------------------------------------------------------------------
- debug.c - Copyright (c) 1996 Red Hat, 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 RED HAT 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>
-
-/* General debugging routines */
-
-void ffi_stop_here(void)
-{
- /* This function is only useful for debugging purposes.
- Place a breakpoint on ffi_stop_here to be notified of
- significant events. */
-}
-
-/* This function should only be called via the FFI_ASSERT() macro */
-
-int ffi_assert(char *file, int line)
-{
- fprintf(stderr, "ASSERTION FAILURE: %s line %d\n", file, line);
- ffi_stop_here();
- abort();
-
- /* This has to return something for the compiler not to complain */
- /*@notreached@*/
- return 0;
-}
-
-/* Perform a sanity check on an ffi_type structure */
-
-bool ffi_type_test(ffi_type *a)
-{
- /*@-usedef@*/
- FFI_ASSERT(a->type <= FFI_TYPE_LAST);
- FFI_ASSERT(a->type > FFI_TYPE_VOID ? a->size > 0 : 1);
- FFI_ASSERT(a->type > FFI_TYPE_VOID ? a->alignment > 0 : 1);
- FFI_ASSERT(a->type == FFI_TYPE_STRUCT ? a->elements != NULL : 1);
- /*@=usedef@*/
-
- /* This is a silly thing to return, but it keeps the compiler from
- issuing warnings about "a" not being used in non-debug builds. */
- return (a != NULL);
-}
+++ /dev/null
-/* -----------------------------------------------------------------------
- ffitest.c - Copyright (c) 1996, 1997, 1998 Cygnus Solutions
-
- 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 RED HAT 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 <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <float.h>
-
-/* This is lame. Long double support is barely there under SunOS 4.x */
-#if defined(SPARC) && (SIZEOF_LONG_DOUBLE != 16)
-#define BROKEN_LONG_DOUBLE
-#endif
-
-#define CHECK(x) !(x) ? fail(__FILE__, __LINE__) : 0
-
-static int fail(char *file, int line)
-{
- fprintf(stderr, "Test failure: %s line %d\n", file, line);
- exit(EXIT_FAILURE);
- /*@notreached@*/
- return 0;
-}
-
-#define MAX_ARGS 256
-
-static size_t my_strlen(char *s)
-{
- return (strlen(s));
-}
-
-static int promotion(signed char sc, signed short ss,
- unsigned char uc, unsigned short us)
-{
- int r = (int) sc + (int) ss + (int) uc + (int) us;
-
- return r;
-}
-
-static signed char return_sc(signed char sc)
-{
- return sc;
-}
-
-static unsigned char return_uc(unsigned char uc)
-{
- return uc;
-}
-
-static long long return_ll(long long ll)
-{
- return ll;
-}
-
-static int floating(int a, float b, double c, long double d, int e)
-{
- int i;
-
-#if 0
- /* This is ifdef'd out for now. long double support under SunOS/gcc
- is pretty much non-existent. You'll get the odd bus error in library
- routines like printf(). */
- printf("%d %f %f %Lf %d\n", a, (double)b, c, d, e);
-#endif
-
- i = (int) ((float)a/b + ((float)c/(float)d));
-
- return i;
-}
-
-static float many(float f1,
- float f2,
- float f3,
- float f4,
- float f5,
- float f6,
- float f7,
- float f8,
- float f9,
- float f10,
- float f11,
- float f12,
- float f13)
-{
-#if 0
- printf("%f %f %f %f %f %f %f %f %f %f %f %f %f\n",
- (double) f1, (double) f2, (double) f3, (double) f4, (double) f5,
- (double) f6, (double) f7, (double) f8, (double) f9, (double) f10,
- (double) f11, (double) f12, (double) f13);
-#endif
-
- return ((f1/f2+f3/f4+f5/f6+f7/f8+f9/f10+f11/f12) * f13);
-}
-
-static double dblit(float f)
-{
- return f/3.0;
-}
-
-static long double ldblit(float f)
-{
- return (long double) (((long double) f)/ (long double) 3.0);
-}
-
-typedef struct
-{
- unsigned char uc;
- double d;
- unsigned int ui;
-} test_structure_1;
-
-typedef struct
-{
- double d1;
- double d2;
-} test_structure_2;
-
-typedef struct
-{
- int si;
-} test_structure_3;
-
-typedef struct
-{
- unsigned ui1;
- unsigned ui2;
- unsigned ui3;
-} test_structure_4;
-
-typedef struct
-{
- char c1;
- char c2;
-} test_structure_5;
-
-static test_structure_1 struct1(test_structure_1 ts)
-{
- /*@-type@*/
- ts.uc++;
- /*@=type@*/
- ts.d--;
- ts.ui++;
-
- return ts;
-}
-
-static test_structure_2 struct2(test_structure_2 ts)
-{
- ts.d1--;
- ts.d2--;
-
- return ts;
-}
-
-static test_structure_3 struct3(test_structure_3 ts)
-{
- ts.si = -(ts.si*2);
-
- return ts;
-}
-
-static test_structure_4 struct4(test_structure_4 ts)
-{
- ts.ui3 = ts.ui1 * ts.ui2 * ts.ui3;
-
- return ts;
-}
-
-static test_structure_5 struct5(test_structure_5 ts1, test_structure_5 ts2)
-{
- ts1.c1 += ts2.c1;
- ts1.c2 -= ts2.c2;
-
- return ts1;
-}
-
-/* Take an int and a float argument, together with int userdata, and */
-/* return the sum. */
-static void closure_test_fn(ffi_cif* cif,void* resp,void** args, void* userdata)
-{
- *(int*)resp =
- *(int *)args[0] + (int)(*(float *)args[1]) + (int)(long)userdata;
-}
-
-typedef int (*closure_test_type)(int, float);
-
-int main(/*@unused@*/ int argc, /*@unused@*/ char *argv[])
-{
- ffi_cif cif;
- ffi_type *args[MAX_ARGS];
- void *values[MAX_ARGS];
- char *s;
- signed char sc;
- unsigned char uc;
- signed short ss;
- unsigned short us;
- unsigned long ul;
- long long ll;
- float f;
- double d;
- long double ld;
- signed int si1;
- signed int si2;
-
-#if defined(ALPHA) || defined(IA64) || defined(SPARC64) || (defined(MIPS) && (_MIPS_SIM == _ABIN32))
- long long rint;
-#else
- int rint;
-#endif
- long long rlonglong;
-
- ffi_type ts1_type;
- ffi_type ts2_type;
- ffi_type ts3_type;
- ffi_type ts4_type;
- ffi_type ts5_type;
- ffi_type *ts1_type_elements[4];
- ffi_type *ts2_type_elements[3];
- ffi_type *ts3_type_elements[2];
- ffi_type *ts4_type_elements[4];
- ffi_type *ts5_type_elements[3];
-
- ts1_type.size = 0;
- ts1_type.alignment = 0;
- ts1_type.type = FFI_TYPE_STRUCT;
-
- ts2_type.size = 0;
- ts2_type.alignment = 0;
- ts2_type.type = FFI_TYPE_STRUCT;
-
- ts3_type.size = 0;
- ts3_type.alignment = 0;
- ts3_type.type = FFI_TYPE_STRUCT;
-
- ts4_type.size = 0;
- ts4_type.alignment = 0;
- ts4_type.type = FFI_TYPE_STRUCT;
-
- ts5_type.size = 0;
- ts5_type.alignment = 0;
- ts5_type.type = FFI_TYPE_STRUCT;
-
- /*@-immediatetrans@*/
- ts1_type.elements = ts1_type_elements;
- ts2_type.elements = ts2_type_elements;
- ts3_type.elements = ts3_type_elements;
- ts4_type.elements = ts4_type_elements;
- ts5_type.elements = ts5_type_elements;
- /*@=immediatetrans@*/
-
- ts1_type_elements[0] = &ffi_type_uchar;
- ts1_type_elements[1] = &ffi_type_double;
- ts1_type_elements[2] = &ffi_type_uint;
- ts1_type_elements[3] = NULL;
-
- ts2_type_elements[0] = &ffi_type_double;
- ts2_type_elements[1] = &ffi_type_double;
- ts2_type_elements[2] = NULL;
-
- ts3_type_elements[0] = &ffi_type_sint;
- ts3_type_elements[1] = NULL;
-
- ts4_type_elements[0] = &ffi_type_uint;
- ts4_type_elements[1] = &ffi_type_uint;
- ts4_type_elements[2] = &ffi_type_uint;
- ts4_type_elements[3] = NULL;
-
- ts5_type_elements[0] = &ffi_type_schar;
- ts5_type_elements[1] = &ffi_type_schar;
- ts5_type_elements[2] = NULL;
-
- ul = 0;
-
- /* return value tests */
- {
-#if defined(MIPS) /* || defined(ARM) */
- puts ("long long tests not run. This is a known bug on this architecture.");
-#else
- args[0] = &ffi_type_sint64;
- values[0] = ≪
-
- /* Initialize the cif */
- CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
- &ffi_type_sint64, args) == FFI_OK);
-
- for (ll = 0LL; ll < 100LL; ll++)
- {
- ul++;
- ffi_call(&cif, FFI_FN(return_ll), &rlonglong, values);
- CHECK(rlonglong == ll);
- }
-
- for (ll = 55555555555000LL; ll < 55555555555100LL; ll++)
- {
- ul++;
- ffi_call(&cif, FFI_FN(return_ll), &rlonglong, values);
- CHECK(rlonglong == ll);
- }
-#endif
-
- args[0] = &ffi_type_schar;
- values[0] = ≻
-
- /* Initialize the cif */
- CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
- &ffi_type_schar, args) == FFI_OK);
-
- for (sc = (signed char) -127;
- sc < (signed char) 127; /*@-type@*/ sc++ /*@=type@*/)
- {
- ul++;
- ffi_call(&cif, FFI_FN(return_sc), &rint, values);
- CHECK(rint == (int) sc);
- }
-
- args[0] = &ffi_type_uchar;
- values[0] = &uc;
-
- /* Initialize the cif */
- CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
- &ffi_type_uchar, args) == FFI_OK);
-
- for (uc = (unsigned char) '\x00';
- uc < (unsigned char) '\xff'; /*@-type@*/ uc++ /*@=type@*/)
- {
- ul++;
- ffi_call(&cif, FFI_FN(return_uc), &rint, values);
- CHECK(rint == (signed int) uc);
- }
-
- printf("%lu return value tests run\n", ul);
- }
-
-#ifdef BROKEN_LONG_DOUBLE
- printf ("This architecture has broken `long double' support. No floating point\ntests have been run.\n");
-#else
- /* float arg tests */
- {
- args[0] = &ffi_type_float;
- values[0] = &f;
-
- /* Initialize the cif */
- CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
- &ffi_type_longdouble, args) == FFI_OK);
-
- f = 3.14159;
-
-#if 0
- /* This is ifdef'd out for now. long double support under SunOS/gcc
- is pretty much non-existent. You'll get the odd bus error in library
- routines like printf(). */
- printf ("%Lf\n", ldblit(f));
-#endif
- ld = 666;
- ffi_call(&cif, FFI_FN(ldblit), &ld, values);
-
-#if 0
- /* This is ifdef'd out for now. long double support under SunOS/gcc
- is pretty much non-existent. You'll get the odd bus error in library
- routines like printf(). */
- printf ("%Lf, %Lf, %Lf, %Lf\n", ld, ldblit(f), ld - ldblit(f), LDBL_EPSILON);
-#endif
-
- /* These are not always the same!! Check for a reasonable delta */
- /*@-realcompare@*/
- if (ld - ldblit(f) < LDBL_EPSILON)
- /*@=realcompare@*/
- puts("long double return value tests ok!");
- else
- CHECK(0);
- }
-
- /* float arg tests */
- {
- args[0] = &ffi_type_sint;
- values[0] = &si1;
- args[1] = &ffi_type_float;
- values[1] = &f;
- args[2] = &ffi_type_double;
- values[2] = &d;
- args[3] = &ffi_type_longdouble;
- values[3] = &ld;
- args[4] = &ffi_type_sint;
- values[4] = &si2;
-
- /* Initialize the cif */
- CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 5,
- &ffi_type_sint, args) == FFI_OK);
-
- si1 = 6;
- f = 3.14159;
- d = (double)1.0/(double)3.0;
- ld = 2.71828182846L;
- si2 = 10;
-
- floating (si1, f, d, ld, si2);
-
- ffi_call(&cif, FFI_FN(floating), &rint, values);
-
- printf ("%d vs %d\n", rint, floating (si1, f, d, ld, si2));
-
- CHECK(rint == floating(si1, f, d, ld, si2));
-
- printf("float arg tests ok!\n");
- }
-#endif
-
- /* strlen tests */
- {
- args[0] = &ffi_type_pointer;
- values[0] = (void*) &s;
-
- /* Initialize the cif */
- CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
- &ffi_type_sint, args) == FFI_OK);
-
- s = "a";
- ffi_call(&cif, FFI_FN(my_strlen), &rint, values);
- CHECK(rint == 1);
-
- s = "1234567";
- ffi_call(&cif, FFI_FN(my_strlen), &rint, values);
- CHECK(rint == 7);
-
- s = "1234567890123456789012345";
- ffi_call(&cif, FFI_FN(my_strlen), &rint, values);
- CHECK(rint == 25);
-
- printf("strlen tests passed\n");
- }
-
- /* float arg tests */
- {
- args[0] = &ffi_type_float;
- values[0] = &f;
-
- /* Initialize the cif */
- CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
- &ffi_type_double, args) == FFI_OK);
-
- f = 3.14159;
-
- ffi_call(&cif, FFI_FN(dblit), &d, values);
-
- /* These are not always the same!! Check for a reasonable delta */
- /*@-realcompare@*/
- CHECK(d - dblit(f) < DBL_EPSILON);
- /*@=realcompare@*/
-
- printf("double return value tests ok!\n");
- }
-
- /* many arg tests */
- {
- float ff;
- float fa[13];
-
- for (ul = 0; ul < 13; ul++)
- {
- args[ul] = &ffi_type_float;
- values[ul] = &fa[ul];
- fa[ul] = (float) ul;
- }
-
- /* Initialize the cif */
- CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 13,
- &ffi_type_float, args) == FFI_OK);
-
- /*@-usedef@*/
- ff = many(fa[0], fa[1],
- fa[2], fa[3],
- fa[4], fa[5],
- fa[6], fa[7],
- fa[8], fa[9],
- fa[10],fa[11],fa[12]);
- /*@=usedef@*/
-
- ffi_call(&cif, FFI_FN(many), &f, values);
-
- /*@-realcompare@*/
- if (f - ff < FLT_EPSILON)
- /*@=realcompare@*/
- printf("many arg tests ok!\n");
- else
-#ifdef POWERPC
- printf("many arg tests failed! This is a gcc bug.\n");
-#else
- CHECK(0);
-#endif
- }
-
- /* promotion tests */
- {
- args[0] = &ffi_type_schar;
- args[1] = &ffi_type_sshort;
- args[2] = &ffi_type_uchar;
- args[3] = &ffi_type_ushort;
- values[0] = ≻
- values[1] = &ss;
- values[2] = &uc;
- values[3] = &us;
-
- /* Initialize the cif */
- CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4,
- &ffi_type_sint, args) == FFI_OK);
-
- us = 0;
- ul = 0;
-
- for (sc = (signed char) -127;
- sc <= (signed char) 120; /*@-type@*/ sc += 1 /*@=type@*/)
- for (ss = -30000; ss <= 30000; ss += 10000)
- for (uc = (unsigned char) 0;
- uc <= (unsigned char) 200; /*@-type@*/ uc += 20 /*@=type@*/)
- for (us = 0; us <= 60000; us += 10000)
- {
- ul++;
- ffi_call(&cif, FFI_FN(promotion), &rint, values);
- CHECK(rint == (int) sc + (int) ss + (int) uc + (int) us);
- }
- printf("%lu promotion tests run\n", ul);
- }
-
-#ifndef X86_WIN32 /* Structures dont work on Win32 */
-
- /* struct tests */
- {
- test_structure_1 ts1_arg;
- /* This is a hack to get a properly aligned result buffer */
- test_structure_1 *ts1_result =
- (test_structure_1 *) malloc (sizeof(test_structure_1));
-
- args[0] = &ts1_type;
- values[0] = &ts1_arg;
-
- /* Initialize the cif */
- CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
- &ts1_type, args) == FFI_OK);
-
- ts1_arg.uc = '\x01';
- ts1_arg.d = 3.14159;
- ts1_arg.ui = 555;
-
- ffi_call(&cif, FFI_FN(struct1), ts1_result, values);
-
- CHECK(ts1_result->ui == 556);
- CHECK(ts1_result->d == 3.14159 - 1);
-
- puts ("structure test 1 ok!\n");
-
- free (ts1_result);
- }
-
- /* struct tests */
- {
- test_structure_2 ts2_arg;
-
- /* This is a hack to get a properly aligned result buffer */
- test_structure_2 *ts2_result =
- (test_structure_2 *) malloc (sizeof(test_structure_2));
-
- args[0] = &ts2_type;
- values[0] = &ts2_arg;
-
- /* Initialize the cif */
- CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
- &ts2_type, args) == FFI_OK);
-
- ts2_arg.d1 = 5.55;
- ts2_arg.d2 = 6.66;
-
- printf ("%g\n", ts2_result->d1);
- printf ("%g\n", ts2_result->d2);
-
- ffi_call(&cif, FFI_FN(struct2), ts2_result, values);
-
- printf ("%g\n", ts2_result->d1);
- printf ("%g\n", ts2_result->d2);
-
- CHECK(ts2_result->d1 == 5.55 - 1);
- CHECK(ts2_result->d2 == 6.66 - 1);
-
- printf("structure test 2 ok!\n");
-
- free (ts2_result);
- }
-
- /* struct tests */
- {
- int compare_value;
- test_structure_3 ts3_arg;
- test_structure_3 *ts3_result =
- (test_structure_3 *) malloc (sizeof(test_structure_3));
-
- args[0] = &ts3_type;
- values[0] = &ts3_arg;
-
- /* Initialize the cif */
- CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
- &ts3_type, args) == FFI_OK);
-
- ts3_arg.si = -123;
- compare_value = ts3_arg.si;
-
- ffi_call(&cif, FFI_FN(struct3), ts3_result, values);
-
- printf ("%d %d\n", ts3_result->si, -(compare_value*2));
-
- if (ts3_result->si == -(ts3_arg.si*2))
- puts ("structure test 3 ok!");
- else
- {
- puts ("Structure test 3 found structure passing bug.");
- puts (" Current versions of GCC are not 100% compliant with the");
- puts (" n32 ABI. There is a known problem related to passing");
- puts (" small structures. Send a bug report to the gcc maintainers.");
- }
-
- free (ts3_result);
- }
-
- /* struct tests */
- {
- test_structure_4 ts4_arg;
-
- /* This is a hack to get a properly aligned result buffer */
- test_structure_4 *ts4_result =
- (test_structure_4 *) malloc (sizeof(test_structure_4));
-
- args[0] = &ts4_type;
- values[0] = &ts4_arg;
-
- /* Initialize the cif */
- CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
- &ts4_type, args) == FFI_OK);
-
- ts4_arg.ui1 = 2;
- ts4_arg.ui2 = 3;
- ts4_arg.ui3 = 4;
-
- ffi_call (&cif, FFI_FN(struct4), ts4_result, values);
-
- if (ts4_result->ui3 == 2U * 3U * 4U)
- puts ("structure test 4 ok!");
- else
- puts ("Structure test 4 found GCC's structure passing bug.");
-
- free (ts4_result);
- }
-
- /* struct tests */
- {
- test_structure_5 ts5_arg1, ts5_arg2;
-
- /* This is a hack to get a properly aligned result buffer */
- test_structure_5 *ts5_result =
- (test_structure_5 *) malloc (sizeof(test_structure_5));
-
- args[0] = &ts5_type;
- args[1] = &ts5_type;
- values[0] = &ts5_arg1;
- values[1] = &ts5_arg2;
-
- /* Initialize the cif */
- CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2,
- &ts5_type, args) == FFI_OK);
-
- ts5_arg1.c1 = 2;
- ts5_arg1.c2 = 6;
- ts5_arg2.c1 = 5;
- ts5_arg2.c2 = 3;
-
- ffi_call (&cif, FFI_FN(struct5), ts5_result, values);
-
- if (ts5_result->c1 == 7
- && ts5_result->c2 == 3)
- puts ("structure test 5 ok!");
- else
- puts ("Structure test 5 found GCC's structure passing bug.");
-
- free (ts5_result);
- }
-
-#else
- printf("Structure passing doesn't work on Win32.\n");
-#endif /* X86_WIN32 */
-
-# if FFI_CLOSURES
- /* A simple closure test */
- {
- ffi_closure cl;
- ffi_type * cl_arg_types[3];
-
- cl_arg_types[0] = &ffi_type_sint;
- cl_arg_types[1] = &ffi_type_float;
- cl_arg_types[2] = NULL;
-
- /* Initialize the cif */
- CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2,
- &ffi_type_sint, cl_arg_types) == FFI_OK);
-
- CHECK(ffi_prep_closure(&cl, &cif, closure_test_fn,
- (void *) 3 /* userdata */)
- == FFI_OK);
- CHECK((*((closure_test_type)(&cl)))(1, 2.0) == 6);
- }
-# endif
-
- /* If we arrived here, all is good */
- (void) puts("\nLooks good. No surprises.\n");
-
- /*@-compdestroy@*/
-
- return 0;
-}
-
+++ /dev/null
-/* -----------------------------------------------------------------------
- ffi.c - Copyright (c) 1998 Cygnus Solutions
- Copyright (c) 2000 Hewlett Packard Company
-
- IA64 Foreign Function Interface
-
- 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.
- ----------------------------------------------------------------------- */
-
-#include <ffi.h>
-#include <ffi_common.h>
-
-#include <stdlib.h>
-
-#include "ia64_flags.h"
-
-/* Memory image of fp register contents. Should eventually be an fp */
-/* type long enough to hold an entire register. For now we use double. */
-typedef double float80;
-
-/* The stack layout at call to ffi_prep_regs. Other_args will remain */
-/* on the stack for the actual call. Everything else we be transferred */
-/* to registers and popped by the assembly code. */
-
-struct ia64_args {
- long scratch[2]; /* Two scratch words at top of stack. */
- /* Allows sp to passed as arg pointer. */
- void * r8_contents; /* Value to be passed in r8 */
- long spare; /* Not used. */
- float80 fp_regs[8]; /* Contents of 8 floating point argument */
- /* registers. */
- long out_regs[8]; /* Contents of the 8 out registers used */
- /* for integer parameters. */
- long other_args[0]; /* Arguments passed on stack, variable size */
- /* Treated as continuation of out_regs. */
-};
-
-static size_t float_type_size(unsigned short tp)
-{
- switch(tp) {
- case FFI_TYPE_FLOAT:
- return sizeof(float);
- case FFI_TYPE_DOUBLE:
- return sizeof(double);
-#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
- case FFI_TYPE_LONGDOUBLE:
- return sizeof(long double);
-#endif
- default:
- FFI_ASSERT(0);
- }
-}
-
-/*
- * Is type a struct containing at most n floats, doubles, or extended
- * doubles, all of the same fp type?
- * If so, set *element_type to the fp type.
- */
-static bool is_homogeneous_fp_aggregate(ffi_type * type, int n,
- unsigned short * element_type)
-{
- ffi_type **ptr;
- unsigned short element, struct_element;
-
- int type_set = 0;
-
- FFI_ASSERT(type != NULL);
-
- FFI_ASSERT(type->elements != NULL);
-
- ptr = &(type->elements[0]);
-
- while ((*ptr) != NULL)
- {
- switch((*ptr) -> type) {
- case FFI_TYPE_FLOAT:
- if (type_set && element != FFI_TYPE_FLOAT) return 0;
- if (--n < 0) return FALSE;
- type_set = 1;
- element = FFI_TYPE_FLOAT;
- break;
- case FFI_TYPE_DOUBLE:
- if (type_set && element != FFI_TYPE_DOUBLE) return 0;
- if (--n < 0) return FALSE;
- type_set = 1;
- element = FFI_TYPE_DOUBLE;
- break;
- case FFI_TYPE_STRUCT:
- if (!is_homogeneous_fp_aggregate(type, n, &struct_element))
- return FALSE;
- if (type_set && struct_element != element) return FALSE;
- n -= (type -> size)/float_type_size(element);
- element = struct_element;
- if (n < 0) return FALSE;
- break;
- /* case FFI_TYPE_LONGDOUBLE:
- Not yet implemented. */
- default:
- return FALSE;
- }
- ptr++;
- }
- *element_type = element;
- return TRUE;
-
-}
-
-/* ffi_prep_args is called by the assembly routine once stack space
- has been allocated for the function's arguments. Returns nonzero
- if fp registers are used for arguments. */
-
-static bool
-ffi_prep_args(struct ia64_args *stack, extended_cif *ecif, int bytes)
-{
- register long i, avn;
- register void **p_argv;
- register long *argp = stack -> out_regs;
- register float80 *fp_argp = stack -> fp_regs;
- register ffi_type **p_arg;
-
- /* For big return structs, r8 needs to contain the target address. */
- /* Since r8 is otherwise dead, we set it unconditionally. */
- stack -> r8_contents = ecif -> rvalue;
- i = 0;
- avn = ecif->cif->nargs;
- p_arg = ecif->cif->arg_types;
- p_argv = ecif->avalue;
- while (i < avn)
- {
- size_t z; /* z is in units of arg slots or words, not bytes. */
-
- switch ((*p_arg)->type)
- {
- case FFI_TYPE_SINT8:
- z = 1;
- *(SINT64 *) argp = *(SINT8 *)(* p_argv);
- break;
-
- case FFI_TYPE_UINT8:
- z = 1;
- *(UINT64 *) argp = *(UINT8 *)(* p_argv);
- break;
-
- case FFI_TYPE_SINT16:
- z = 1;
- *(SINT64 *) argp = *(SINT16 *)(* p_argv);
- break;
-
- case FFI_TYPE_UINT16:
- z = 1;
- *(UINT64 *) argp = *(UINT16 *)(* p_argv);
- break;
-
- case FFI_TYPE_SINT32:
- z = 1;
- *(SINT64 *) argp = *(SINT32 *)(* p_argv);
- break;
-
- case FFI_TYPE_UINT32:
- z = 1;
- *(UINT64 *) argp = *(UINT32 *)(* p_argv);
- break;
-
- case FFI_TYPE_SINT64:
- case FFI_TYPE_UINT64:
- case FFI_TYPE_POINTER:
- z = 1;
- *(UINT64 *) argp = *(UINT64 *)(* p_argv);
- break;
-
- case FFI_TYPE_FLOAT:
- z = 1;
- if (fp_argp - stack->fp_regs < 8)
- {
- /* Note the conversion -- all the fp regs are loaded as
- doubles. */
- *fp_argp++ = *(float *)(* p_argv);
- }
- /* Also put it into the integer registers or memory: */
- *(UINT64 *) argp = *(UINT32 *)(* p_argv);
- break;
-
- case FFI_TYPE_DOUBLE:
- z = 1;
- if (fp_argp - stack->fp_regs < 8)
- *fp_argp++ = *(double *)(* p_argv);
- /* Also put it into the integer registers or memory: */
- *(double *) argp = *(double *)(* p_argv);
- break;
-
- case FFI_TYPE_STRUCT:
- {
- size_t sz = (*p_arg)->size;
- unsigned short element_type;
- z = ((*p_arg)->size + SIZEOF_ARG - 1)/SIZEOF_ARG;
- if (is_homogeneous_fp_aggregate(*p_arg, 8, &element_type)) {
- int i;
- int nelements = sz/float_type_size(element_type);
- for (i = 0; i < nelements; ++i) {
- switch (element_type) {
- case FFI_TYPE_FLOAT:
- if (fp_argp - stack->fp_regs < 8)
- *fp_argp++ = ((float *)(* p_argv))[i];
- break;
- case FFI_TYPE_DOUBLE:
- if (fp_argp - stack->fp_regs < 8)
- *fp_argp++ = ((double *)(* p_argv))[i];
- break;
- default:
- /* Extended precision not yet implemented. */
- abort();
- }
- }
- }
- /* And pass it in integer registers as a struct, with */
- /* its actual field sizes packed into registers. */
- memcpy(argp, *p_argv, (*p_arg)->size);
- }
- break;
-
- default:
- FFI_ASSERT(0);
- }
-
- argp += z;
- i++, p_arg++, p_argv++;
- }
- return (fp_argp != stack -> fp_regs);
-}
-
-/* Perform machine dependent cif processing */
-ffi_status
-ffi_prep_cif_machdep(ffi_cif *cif)
-{
- long i, avn;
- bool is_simple = TRUE;
- long simple_flag = FFI_SIMPLE_V;
- /* Adjust cif->bytes to include space for the 2 scratch words,
- r8 register contents, spare word,
- the 8 fp register contents, and all 8 integer register contents.
- This will be removed before the call, though 2 scratch words must
- remain. */
-
- cif->bytes += 4*sizeof(long) + 8 *sizeof(float80);
- if (cif->bytes < sizeof(struct ia64_args))
- cif->bytes = sizeof(struct ia64_args);
-
- /* The stack must be double word aligned, so round bytes up
- appropriately. */
-
- cif->bytes = ALIGN(cif->bytes, 2*sizeof(void*));
-
- avn = cif->nargs;
- if (avn <= 2) {
- for (i = 0; i < avn; ++i) {
- switch(cif -> arg_types[i] -> type) {
- case FFI_TYPE_SINT32:
- simple_flag = FFI_ADD_INT_ARG(simple_flag);
- break;
- case FFI_TYPE_SINT64:
- case FFI_TYPE_UINT64:
- case FFI_TYPE_POINTER:
- simple_flag = FFI_ADD_LONG_ARG(simple_flag);
- break;
- default:
- is_simple = FALSE;
- }
- }
- } else {
- is_simple = FALSE;
- }
-
- /* Set the return type flag */
- switch (cif->rtype->type)
- {
- case FFI_TYPE_VOID:
- cif->flags = FFI_TYPE_VOID;
- break;
-
- case FFI_TYPE_STRUCT:
- {
- size_t sz = cif -> rtype -> size;
- unsigned short element_type;
-
- is_simple = FALSE;
- if (is_homogeneous_fp_aggregate(cif -> rtype, 8, &element_type)) {
- int nelements = sz/float_type_size(element_type);
- if (nelements <= 1) {
- if (0 == nelements) {
- cif -> flags = FFI_TYPE_VOID;
- } else {
- cif -> flags = element_type;
- }
- } else {
- switch(element_type) {
- case FFI_TYPE_FLOAT:
- cif -> flags = FFI_IS_FLOAT_FP_AGGREGATE | nelements;
- break;
- case FFI_TYPE_DOUBLE:
- cif -> flags = FFI_IS_DOUBLE_FP_AGGREGATE | nelements;
- break;
- default:
- /* long double NYI */
- abort();
- }
- }
- break;
- }
- if (sz <= 32) {
- if (sz <= 8) {
- cif->flags = FFI_TYPE_INT;
- } else if (sz <= 16) {
- cif->flags = FFI_IS_SMALL_STRUCT2;
- } else if (sz <= 24) {
- cif->flags = FFI_IS_SMALL_STRUCT3;
- } else {
- cif->flags = FFI_IS_SMALL_STRUCT4;
- }
- } else {
- cif->flags = FFI_TYPE_STRUCT;
- }
- }
- break;
-
- case FFI_TYPE_FLOAT:
- is_simple = FALSE;
- cif->flags = FFI_TYPE_FLOAT;
- break;
-
- case FFI_TYPE_DOUBLE:
- is_simple = FALSE;
- cif->flags = FFI_TYPE_DOUBLE;
- break;
-
- default:
- cif->flags = FFI_TYPE_INT;
- /* This seems to depend on little endian mode, and the fact that */
- /* the return pointer always points to at least 8 bytes. But */
- /* that also seems to be true for other platforms. */
- break;
- }
-
- if (is_simple) cif -> flags |= simple_flag;
- return FFI_OK;
-}
-
-extern int ffi_call_unix(bool (*)(struct ia64_args *, extended_cif *, int),
- extended_cif *, unsigned,
- unsigned, unsigned *, void (*)());
-
-void
-ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
-{
- extended_cif ecif;
- long simple = cif -> flags & FFI_SIMPLE;
-
- /* Should this also check for Unix ABI? */
- /* This is almost, but not quite, machine independent. Note that */
- /* we can get away with not caring about length of the result because */
- /* we assume we are little endian, and the result buffer is large */
- /* enough. */
- /* This needs work for HP/UX. */
- if (simple) {
- long (*lfn)() = (long (*)())fn;
- long result;
- switch(simple) {
- case FFI_SIMPLE_V:
- result = lfn();
- break;
- case FFI_SIMPLE_I:
- result = lfn(*(int *)avalue[0]);
- break;
- case FFI_SIMPLE_L:
- result = lfn(*(long *)avalue[0]);
- break;
- case FFI_SIMPLE_II:
- result = lfn(*(int *)avalue[0], *(int *)avalue[1]);
- break;
- case FFI_SIMPLE_IL:
- result = lfn(*(int *)avalue[0], *(long *)avalue[1]);
- break;
- case FFI_SIMPLE_LI:
- result = lfn(*(long *)avalue[0], *(int *)avalue[1]);
- break;
- case FFI_SIMPLE_LL:
- result = lfn(*(long *)avalue[0], *(long *)avalue[1]);
- break;
- }
- if ((cif->flags & ~FFI_SIMPLE) != FFI_TYPE_VOID && 0 != rvalue) {
- * (long *)rvalue = result;
- }
- return;
- }
- 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)
- ecif.rvalue = alloca(cif->rtype->size);
- else
- ecif.rvalue = rvalue;
-
- switch (cif->abi)
- {
- case FFI_UNIX:
- ffi_call_unix(ffi_prep_args, &ecif, cif->bytes,
- cif->flags, rvalue, fn);
- break;
-
- default:
- FFI_ASSERT(0);
- break;
- }
-}
-
-/*
- * Closures represent a pair consisting of a function pointer, and
- * some user data. A closure is invoked by reinterpreting the closure
- * as a function pointer, and branching to it. Thus we can make an
- * interpreted function callable as a C function: We turn the interpreter
- * itself, together with a pointer specifying the interpreted procedure,
- * into a closure.
- * On X86, the first few words of the closure structure actually contain code,
- * which will do the right thing. On most other architectures, this
- * would raise some Icache/Dcache coherence issues (which can be solved, but
- * often not cheaply).
- * For IA64, function pointer are already pairs consisting of a code
- * pointer, and a gp pointer. The latter is needed to access global variables.
- * Here we set up such a pair as the first two words of the closure (in
- * the "trampoline" area), but we replace the gp pointer with a pointer
- * to the closure itself. We also add the real gp pointer to the
- * closure. This allows the function entry code to both retrieve the
- * user data, and to restire the correct gp pointer.
- */
-
-static void
-ffi_prep_incoming_args_UNIX(struct ia64_args *args, void **rvalue,
- void **avalue, ffi_cif *cif);
-
-/* This function is entered with the doctored gp (r1) value.
- * This code is extremely gcc specific. There is some argument that
- * it should really be written in assembly code, since it depends on
- * gcc properties that might change over time.
- */
-
-/* ffi_closure_UNIX is an assembly routine, which copies the register */
-/* state into s struct ia64_args, and the invokes */
-/* ffi_closure_UNIX_inner. It also recovers the closure pointer */
-/* from its fake gp pointer. */
-void ffi_closure_UNIX();
-
-#ifndef __GNUC__
-# error This requires gcc
-#endif
-void
-ffi_closure_UNIX_inner (ffi_closure *closure, struct ia64_args * args)
-/* Hopefully declarint this as a varargs function will force all args */
-/* to memory. */
-{
- // this is our return value storage
- long double res;
-
- // our various things...
- ffi_cif *cif;
- unsigned short rtype;
- void *resp;
- void **arg_area;
-
- resp = (void*)&res;
- cif = closure->cif;
- arg_area = (void**) alloca (cif->nargs * sizeof (void*));
-
- /* this call will initialize ARG_AREA, such that each
- * element in that array points to the corresponding
- * value on the stack; and if the function returns
- * a structure, it will re-set RESP to point to the
- * structure return address. */
-
- ffi_prep_incoming_args_UNIX(args, (void**)&resp, arg_area, cif);
-
- (closure->fun) (cif, resp, arg_area, closure->user_data);
-
- rtype = cif->flags;
-
- /* now, do a generic return based on the value of rtype */
- if (rtype == FFI_TYPE_INT)
- {
- asm volatile ("ld8 r8=[%0]" : : "r" (resp) : "r8");
- }
- else if (rtype == FFI_TYPE_FLOAT)
- {
- asm volatile ("ldfs f8=[%0]" : : "r" (resp) : "f8");
- }
- else if (rtype == FFI_TYPE_DOUBLE)
- {
- asm volatile ("ldfd f8=[%0]" : : "r" (resp) : "f8");
- }
- else if (rtype == FFI_IS_SMALL_STRUCT2)
- {
- asm volatile ("ld8 r8=[%0]; ld8 r9=[%1]"
- : : "r" (resp), "r" (resp+8) : "r8","r9");
- }
- else if (rtype == FFI_IS_SMALL_STRUCT3)
- {
- asm volatile ("ld8 r8=[%0]; ld8 r9=[%1]; ld8 r10=[%2]"
- : : "r" (resp), "r" (resp+8), "r" (resp+16)
- : "r8","r9","r10");
- }
- else if (rtype == FFI_IS_SMALL_STRUCT4)
- {
- asm volatile ("ld8 r8=[%0]; ld8 r9=[%1]; ld8 r10=[%2]; ld8 r11=[%3]"
- : : "r" (resp), "r" (resp+8), "r" (resp+16), "r" (resp+24)
- : "r8","r9","r10","r11");
- }
- else if (rtype != FFI_TYPE_VOID && rtype != FFI_TYPE_STRUCT)
- {
- /* Can only happen for homogeneous FP aggregates? */
- abort();
- }
-}
-
-static void
-ffi_prep_incoming_args_UNIX(struct ia64_args *args, void **rvalue,
- void **avalue, ffi_cif *cif)
-{
- register unsigned int i;
- register unsigned int avn;
- register void **p_argv;
- register unsigned long *argp = args -> out_regs;
- unsigned fp_reg_num = 0;
- register ffi_type **p_arg;
-
- avn = cif->nargs;
- p_argv = avalue;
-
- for (i = cif->nargs, p_arg = cif->arg_types; i != 0; i--, p_arg++)
- {
- size_t z; /* In units of words or argument slots. */
-
- switch ((*p_arg)->type)
- {
- case FFI_TYPE_SINT8:
- case FFI_TYPE_UINT8:
- case FFI_TYPE_SINT16:
- case FFI_TYPE_UINT16:
- case FFI_TYPE_SINT32:
- case FFI_TYPE_UINT32:
- case FFI_TYPE_SINT64:
- case FFI_TYPE_UINT64:
- case FFI_TYPE_POINTER:
- z = 1;
- *p_argv = (void *)argp;
- break;
-
- case FFI_TYPE_FLOAT:
- z = 1;
- /* Convert argument back to float in place from the saved value */
- if (fp_reg_num < 8) {
- *(float *)argp = args -> fp_regs[fp_reg_num++];
- } else {
- *(float *)argp = *(double *)argp;
- }
- *p_argv = (void *)argp;
- break;
-
- case FFI_TYPE_DOUBLE:
- z = 1;
- if (fp_reg_num < 8) {
- *p_argv = args -> fp_regs + fp_reg_num++;
- } else {
- *p_argv = (void *)argp;
- }
- break;
-
- case FFI_TYPE_STRUCT:
- {
- size_t sz = (*p_arg)->size;
- unsigned short element_type;
- z = ((*p_arg)->size + SIZEOF_ARG - 1)/SIZEOF_ARG;
- if (is_homogeneous_fp_aggregate(*p_arg, 8, &element_type)) {
- int nelements = sz/float_type_size(element_type);
- if (nelements + fp_reg_num >= 8) {
- /* hard case NYI. */
- abort();
- }
- if (element_type == FFI_TYPE_DOUBLE) {
- *p_argv = args -> fp_regs + fp_reg_num;
- fp_reg_num += nelements;
- break;
- }
- if (element_type == FFI_TYPE_FLOAT) {
- int j;
- for (j = 0; j < nelements; ++ j) {
- ((float *)argp)[j] = args -> fp_regs[fp_reg_num + j];
- }
- *p_argv = (void *)argp;
- fp_reg_num += nelements;
- break;
- }
- abort(); /* Other fp types NYI */
- }
- }
- break;
-
- default:
- FFI_ASSERT(0);
- }
-
- argp += z;
- p_argv++;
-
- }
-
- return;
-}
-
-
-/* Fill in a closure to refer to the specified fun and user_data. */
-/* cif specifies the argument and result types for fun. */
-/* the cif must already be prep'ed */
-
-/* The layout of a function descriptor. A C function pointer really */
-/* points to one of these. */
-typedef struct ia64_fd_struct {
- void *code_pointer;
- void *gp;
-} ia64_fd;
-
-ffi_status
-ffi_prep_closure (ffi_closure* closure,
- ffi_cif* cif,
- void (*fun)(ffi_cif*,void*,void**,void*),
- void *user_data)
-{
- struct ffi_ia64_trampoline_struct *tramp =
- (struct ffi_ia64_trampoline_struct *) (closure -> tramp);
- ia64_fd *fd = (ia64_fd *)(void *)ffi_closure_UNIX;
-
- FFI_ASSERT (cif->abi == FFI_UNIX);
-
- tramp -> code_pointer = fd -> code_pointer;
- tramp -> real_gp = fd -> gp;
- tramp -> fake_gp = closure;
- closure->cif = cif;
- closure->user_data = user_data;
- closure->fun = fun;
-
- return FFI_OK;
-}
-
-
+++ /dev/null
-/* -----------------------------------------------------------------------
- ia64_flags.h - Copyright (c) 2000 Hewlett Packard Company
-
- IA64/unix Foreign Function Interface
-
- Original author: Hans Boehm, HP Labs
-
- 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.
- ----------------------------------------------------------------------- */
-
-
-/* Homogeneous Floating Point Aggregates (HFAs) which are returned */
-/* in FP registers. The least significant bits specify the size in */
-/* words. */
-#define FFI_IS_FLOAT_FP_AGGREGATE 0x1000
-#define FFI_IS_DOUBLE_FP_AGGREGATE 0x0800
-#define FLOAT_FP_AGGREGATE_BIT 12
-#define DOUBLE_FP_AGGREGATE_BIT 11
-
-/* Small structures containing N words. If N=1, they are returned */
-/* as though they were integers. */
-#define FFI_IS_SMALL_STRUCT2 0x40 /* Struct > 8, <=16 bytes */
-#define FFI_IS_SMALL_STRUCT3 0x41 /* Struct > 16 <= 24 bytes */
-#define FFI_IS_SMALL_STRUCT4 0x42 /* Struct > 24, <=32 bytes */
-
-/* Flag values identifying particularly simple cases, which are */
-/* handled specially. We treat functions as simple if they take all */
-/* arguments can be passed as 32 or 64 bit integer quantities, there is */
-/* either no return value or it can be treated as a 64bit integer, and */
-/* if there are at most 2 arguments. */
-/* This is OR'ed with the normal flag values. */
-#define FFI_SIMPLE_V 0x10000 /* () -> X */
-#define FFI_SIMPLE_I 0x20000 /* (int) -> X */
-#define FFI_SIMPLE_L 0x30000 /* (long) -> X */
-#define FFI_SIMPLE_II 0x40000 /* (int,int) -> X */
-#define FFI_SIMPLE_IL 0x50000 /* (int,long) -> X */
-#define FFI_SIMPLE_LI 0x60000 /* (long,int) -> X */
-#define FFI_SIMPLE_LL 0x70000 /* (long,long) -> X */
-
-/* Mask for all of the FFI_SIMPLE bits: */
-#define FFI_SIMPLE 0xf0000
-
-/* An easy way to build FFI_SIMPLE flags from FFI_SIMPLE_V: */
-#define FFI_ADD_LONG_ARG(flag) (((flag) << 1) | 0x10000)
-#define FFI_ADD_INT_ARG(flag) ((flag) << 1)
+++ /dev/null
-/* -----------------------------------------------------------------------
- unix.S - Copyright (c) 1998 Cygnus Solutions
- Copyright (c) 2000 Hewlett Packard Company
-
- IA64/unix Foreign Function Interface
-
- Primary author: Hans Boehm, HP Labs
-
- Loosely modeled on Cygnus code for other platforms.
-
- 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.
- ----------------------------------------------------------------------- */
-
-#define LIBFFI_ASM
-#include <ffi.h>
-#include "ia64_flags.h"
-
-/* parameters: */
-#define callback in0
-#define ecifp in1
-#define bytes in2
-#define flags in3
-#define raddr in4
-#define fn in5
-
-#define FLOAT_SZ 8 /* in-memory size of fp operands */
-
-.text
- .align 16
- .global ffi_call_unix#
- .proc ffi_call_unix#
-ffi_call_unix:
- alloc loc0=ar.pfs,6,5,8,0
- mov loc1=b0;
- sub sp=sp,bytes
- mov loc4=r1 /* Save gp */
- ld8 r8=[callback],8 /* code address of callback */
- ;;
- mov out0=sp
- mov out1=ecifp
- mov out2=bytes
- ld8 r1=[callback] /* Set up gp for callback. Unnecessary? */
- mov b6=r8
- ;;
- br.call.sptk.many b0 = b6 /* call ffi_prep_args */
- cmp.eq p6,p0=0,r8 /* r8 nonzero ==> need fp regs */
- ;;
-(p6) add loc2=32+8*FLOAT_SZ,sp
-(p6) br.cond.dptk.many fp_done
- ;; /* Quiets warning; needed? */
- add loc2=32,sp
- add loc3=32+FLOAT_SZ,sp
- ;;
- ldfd f8=[loc2],2*FLOAT_SZ
- ldfd f9=[loc3],2*FLOAT_SZ
- ;;
- ldfd f10=[loc2],2*FLOAT_SZ
- ldfd f11=[loc3],2*FLOAT_SZ
- ;;
- ldfd f12=[loc2],2*FLOAT_SZ
- ldfd f13=[loc3],2*FLOAT_SZ
- ;;
- ldfd f14=[loc2],2*FLOAT_SZ
- ldfd f15=[loc3]
-fp_done:
- add r9=16,sp /* Pointer to r8_contents */
- /* loc2 points at first integer register value. */
- add loc3=8,loc2
- ;;
- ld8 r8=[r9] /* Just in case we return large struct */
- ld8 out0=[loc2],16
- ld8 out1=[loc3],16
- ;;
- ld8 out2=[loc2],16
- ld8 out3=[loc3],16
- ;;
- ld8 out4=[loc2],16
- ld8 out5=[loc3],16
- ;;
- ld8 out6=[loc2],16
- ld8 out7=[loc3]
- /* loc2 points at first stack parameter. Set sp to 16 bytes */
- /* below that. */
- add sp=-16,loc2
-
- ld8 r8=[fn],8
- ;;
- ld8 r1=[fn] /* Set up gp */
- mov b6=r8;;
- br.call.sptk.many b0 = b6 /* call ffi_prep_args */
-
- /* Handle return value. */
- cmp.eq p6,p0=0,raddr
- cmp.eq p7,p0=FFI_TYPE_INT,flags
- cmp.eq p10,p0=FFI_IS_SMALL_STRUCT2,flags
- cmp.eq p11,p0=FFI_IS_SMALL_STRUCT3,flags
- cmp.eq p12,p0=FFI_IS_SMALL_STRUCT4,flags
- ;;
-(p6) br.cond.dpnt.few done /* Dont copy ret values if raddr = 0 */
-(p7) br.cond.dptk.few copy1
-(p10) br.cond.dpnt.few copy2
-(p11) br.cond.dpnt.few copy3
-(p12) br.cond.dpnt.few copy4
- cmp.eq p8,p0=FFI_TYPE_FLOAT,flags
- cmp.eq p9,p0=FFI_TYPE_DOUBLE,flags
- tbit.nz p6,p0=flags,FLOAT_FP_AGGREGATE_BIT
- tbit.nz p7,p0=flags,DOUBLE_FP_AGGREGATE_BIT
- ;;
-(p8) stfs [raddr]=f8
-(p9) stfd [raddr]=f8
- ;;
-(p6) br.cond.dpnt.few handle_float_hfa
-(p7) br.cond.dpnt.few handle_double_hfa
- br done
-
-copy4:
- add loc3=24,raddr
- ;;
- st8 [loc3]=r11
-copy3:
- add loc3=16,raddr
- ;;
- st8 [loc3]=r10
-copy2:
- add loc3=8,raddr
- ;;
- st8 [loc3]=r9
-copy1:
- st8 [raddr]=r8
- /* In the big struct case, raddr was passed as an argument. */
- /* In the void case there was nothing to do. */
-
-done:
- mov r1=loc4 /* Restore gp */
- mov ar.pfs = loc0
- mov b0 = loc1
- br.ret.sptk.many b0
-
-handle_double_hfa:
- /* Homogeneous floating point array of doubles is returned in */
- /* registers f8-f15. Save one at a time to return area. */
- and flags=0xf,flags /* Retrieve size */
- ;;
- cmp.eq p6,p0=2,flags
- cmp.eq p7,p0=3,flags
- cmp.eq p8,p0=4,flags
- cmp.eq p9,p0=5,flags
- cmp.eq p10,p0=6,flags
- cmp.eq p11,p0=7,flags
- cmp.eq p12,p0=8,flags
- ;;
-(p6) br.cond.dptk.few dhfa2
-(p7) br.cond.dptk.few dhfa3
-(p8) br.cond.dptk.few dhfa4
-(p9) br.cond.dptk.few dhfa5
-(p10) br.cond.dptk.few dhfa6
-(p11) br.cond.dptk.few dhfa7
-dhfa8: add loc3=7*8,raddr
- ;;
- stfd [loc3]=f15
-dhfa7: add loc3=6*8,raddr
- ;;
- stfd [loc3]=f14
-dhfa6: add loc3=5*8,raddr
- ;;
- stfd [loc3]=f13
-dhfa5: add loc3=4*8,raddr
- ;;
- stfd [loc3]=f12
-dhfa4: add loc3=3*8,raddr
- ;;
- stfd [loc3]=f11
-dhfa3: add loc3=2*8,raddr
- ;;
- stfd [loc3]=f10
-dhfa2: add loc3=1*8,raddr
- ;;
- stfd [loc3]=f9
- stfd [raddr]=f8
- br done
-
-handle_float_hfa:
- /* Homogeneous floating point array of floats is returned in */
- /* registers f8-f15. Save one at a time to return area. */
- and flags=0xf,flags /* Retrieve size */
- ;;
- cmp.eq p6,p0=2,flags
- cmp.eq p7,p0=3,flags
- cmp.eq p8,p0=4,flags
- cmp.eq p9,p0=5,flags
- cmp.eq p10,p0=6,flags
- cmp.eq p11,p0=7,flags
- cmp.eq p12,p0=8,flags
- ;;
-(p6) br.cond.dptk.few shfa2
-(p7) br.cond.dptk.few shfa3
-(p8) br.cond.dptk.few shfa4
-(p9) br.cond.dptk.few shfa5
-(p10) br.cond.dptk.few shfa6
-(p11) br.cond.dptk.few shfa7
-shfa8: add loc3=7*4,raddr
- ;;
- stfd [loc3]=f15
-shfa7: add loc3=6*4,raddr
- ;;
- stfd [loc3]=f14
-shfa6: add loc3=5*4,raddr
- ;;
- stfd [loc3]=f13
-shfa5: add loc3=4*4,raddr
- ;;
- stfd [loc3]=f12
-shfa4: add loc3=3*4,raddr
- ;;
- stfd [loc3]=f11
-shfa3: add loc3=2*4,raddr
- ;;
- stfd [loc3]=f10
-shfa2: add loc3=1*4,raddr
- ;;
- stfd [loc3]=f9
- stfd [raddr]=f8
- br done
-
- .endp ffi_call_unix
-
-
-.text
- .align 16
- .global ffi_closure_UNIX
- .proc ffi_closure_UNIX
-ffi_closure_UNIX:
- alloc loc0=ar.pfs,8,2,2,0
- mov loc1=b0
- /* Retrieve closure pointer and real gp. */
- mov out0=gp
- add gp=16,gp
- ;;
- ld8 gp=[gp]
- /* Reserve a structia64_args on the stack such that arguments */
- /* past the first 8 are automatically placed in the right */
- /* slot. Note that when we start the sp points at 2 8-byte */
- /* scratch words, followed by the extra arguments. */
-# define BASIC_ARGS_SZ (8*FLOAT_SZ+8*8+2*8)
-# define FIRST_FP_OFFSET (4*8)
- add r14=-(BASIC_ARGS_SZ-FIRST_FP_OFFSET),sp
- add r15=-(BASIC_ARGS_SZ-FIRST_FP_OFFSET-FLOAT_SZ),sp
- add sp=-BASIC_ARGS_SZ,sp
- /* r14 points to fp_regs[0], r15 points to fp_regs[1] */
- ;;
- stfd [r14]=f8,2*FLOAT_SZ
- stfd [r15]=f9,2*FLOAT_SZ
- ;;
- stfd [r14]=f10,2*FLOAT_SZ
- stfd [r15]=f11,2*FLOAT_SZ
- ;;
- stfd [r14]=f12,2*FLOAT_SZ
- stfd [r15]=f13,2*FLOAT_SZ
- ;;
- stfd [r14]=f14,FLOAT_SZ+8
- stfd [r15]=f15,2*8
- ;;
- /* r14 points to first parameter register area, r15 to second. */
- st8 [r14]=in0,2*8
- st8 [r15]=in1,2*8
- ;;
- st8 [r14]=in2,2*8
- st8 [r15]=in3,2*8
- ;;
- st8 [r14]=in4,2*8
- st8 [r15]=in5,2*8
- ;;
- st8 [r14]=in6,2*8
- st8 [r15]=in7,2*8
- /* Call ffi_closure_UNIX_inner */
- mov out1=sp
- br.call.sptk.many b0=ffi_closure_UNIX_inner
- ;;
- mov b0=loc1
- mov ar.pfs=loc0
- br.ret.sptk.many b0
- .endp ffi_closure_UNIX
-
-
+++ /dev/null
-/* -----------------------------------------------------------------------
- java_raw_api.c - Copyright (c) 1999 Cygnus Solutions
-
- Cloned from raw_api.c
-
- Raw_api.c author: Kresten Krab Thorup <krab@gnu.org>
- Java_raw_api.c author: Hans-J. Boehm <hboehm@hpl.hp.com>
-
- $Id $
-
- 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 RED HAT 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.
- ----------------------------------------------------------------------- */
-
-/* This defines a Java- and 64-bit specific variant of the raw API. */
-/* It assumes that "raw" argument blocks look like Java stacks on a */
-/* 64-bit machine. Arguments that can be stored in a single stack */
-/* stack slots (longs, doubles) occupy 128 bits, but only the first */
-/* 64 bits are actually used. */
-
-#include <ffi.h>
-#include <ffi_common.h>
-
-#if !defined(NO_JAVA_RAW_API) && !defined(FFI_NO_RAW_API)
-
-size_t
-ffi_java_raw_size (ffi_cif *cif)
-{
- size_t result = 0;
- int i;
-
- ffi_type **at = cif->arg_types;
-
- for (i = cif->nargs-1; i >= 0; i--, at++)
- {
- switch((*at) -> type) {
- case FFI_TYPE_UINT64:
- case FFI_TYPE_SINT64:
- result += 2 * SIZEOF_ARG;
- break;
- case FFI_TYPE_STRUCT:
- /* No structure parameters in Java. */
- abort();
- default:
- result += SIZEOF_ARG;
- }
- }
-
- return result;
-}
-
-
-void
-ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args)
-{
- unsigned i;
- ffi_type **tp = cif->arg_types;
-
-#if WORDS_BIGENDIAN
-
- for (i = 0; i < cif->nargs; i++, tp++, args++)
- {
- switch ((*tp)->type)
- {
- case FFI_TYPE_UINT8:
- case FFI_TYPE_SINT8:
- *args = (void*) ((char*)(raw++) + SIZEOF_ARG - 1);
- break;
-
- case FFI_TYPE_UINT16:
- case FFI_TYPE_SINT16:
- *args = (void*) ((char*)(raw++) + SIZEOF_ARG - 2);
- break;
-
-#if SIZEOF_ARG >= 4
- case FFI_TYPE_UINT32:
- case FFI_TYPE_SINT32:
- *args = (void*) ((char*)(raw++) + SIZEOF_ARG - 4);
- break;
-#endif
-
-#if SIZEOF_ARG == 8
- case FFI_TYPE_UINT64:
- case FFI_TYPE_SINT64:
- case FFI_TYPE_DOUBLE:
- *args = (void *)raw;
- raw += 2;
- break;
-#endif
-
- case FFI_TYPE_POINTER:
- *args = (void*) &(raw++)->ptr;
- break;
-
- default:
- *args = raw;
- raw += ALIGN ((*tp)->size, SIZEOF_ARG) / SIZEOF_ARG;
- }
- }
-
-#else /* WORDS_BIGENDIAN */
-
-#if !PDP
-
- /* then assume little endian */
- for (i = 0; i < cif->nargs; i++, tp++, args++)
- {
-#if SIZEOF_ARG == 8
- switch((*tp)->type) {
- case FFI_TYPE_UINT64:
- case FFI_TYPE_SINT64:
- case FFI_TYPE_DOUBLE:
- *args = (void*) raw;
- raw += 2;
- break;
- default:
- *args = (void*) raw++;
- }
-#else /* SIZEOF_ARG != 8 */
- *args = (void*) raw;
- raw += ALIGN ((*tp)->size, sizeof (void*)) / sizeof (void*);
-#endif /* SIZEOF_ARG == 8 */
- }
-
-#else
-#error "pdp endian not supported"
-#endif /* ! PDP */
-
-#endif /* WORDS_BIGENDIAN */
-}
-
-void
-ffi_java_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw)
-{
- unsigned i;
- ffi_type **tp = cif->arg_types;
-
- for (i = 0; i < cif->nargs; i++, tp++, args++)
- {
- switch ((*tp)->type)
- {
- case FFI_TYPE_UINT8:
- (raw++)->uint = *(UINT8*) (*args);
- break;
-
- case FFI_TYPE_SINT8:
- (raw++)->sint = *(SINT8*) (*args);
- break;
-
- case FFI_TYPE_UINT16:
- (raw++)->uint = *(UINT16*) (*args);
- break;
-
- case FFI_TYPE_SINT16:
- (raw++)->sint = *(SINT16*) (*args);
- break;
-
-#if SIZEOF_ARG >= 4
- case FFI_TYPE_UINT32:
- (raw++)->uint = *(UINT32*) (*args);
- break;
-
- case FFI_TYPE_SINT32:
- (raw++)->sint = *(SINT32*) (*args);
- break;
-#endif
- case FFI_TYPE_FLOAT:
- (raw++)->flt = *(FLOAT32*) (*args);
- break;
-
-#if SIZEOF_ARG == 8
- case FFI_TYPE_UINT64:
- case FFI_TYPE_SINT64:
- case FFI_TYPE_DOUBLE:
- raw->uint = *(UINT64*) (*args);
- raw += 2;
- break;
-#endif
-
- case FFI_TYPE_POINTER:
- (raw++)->ptr = **(void***) args;
- break;
-
- default:
-#if SIZEOF_ARG == 8
- FFI_ASSERT(FALSE); /* Should have covered all cases */
-#else
- memcpy ((void*) raw->data, (void*)*args, (*tp)->size);
- raw += ALIGN ((*tp)->size, SIZEOF_ARG) / SIZEOF_ARG;
-#endif
- }
- }
-}
-
-#if !FFI_NATIVE_RAW_API
-
-
-/* This is a generic definition of ffi_raw_call, to be used if the
- * native system does not provide a machine-specific implementation.
- * Having this, allows code to be written for the raw API, without
- * the need for system-specific code to handle input in that format;
- * these following couple of functions will handle the translation forth
- * and back automatically. */
-
-void ffi_java_raw_call (/*@dependent@*/ ffi_cif *cif,
- void (*fn)(),
- /*@out@*/ void *rvalue,
- /*@dependent@*/ ffi_raw *raw)
-{
- void **avalue = (void**) alloca (cif->nargs * sizeof (void*));
- ffi_java_raw_to_ptrarray (cif, raw, avalue);
- ffi_call (cif, fn, rvalue, avalue);
-}
-
-#if FFI_CLOSURES /* base system provides closures */
-
-static void
-ffi_java_translate_args (ffi_cif *cif, void *rvalue,
- void **avalue, void *user_data)
-{
- ffi_raw *raw = (ffi_raw*)alloca (ffi_java_raw_size (cif));
- ffi_raw_closure *cl = (ffi_raw_closure*)user_data;
-
- ffi_java_ptrarray_to_raw (cif, avalue, raw);
- (*cl->fun) (cif, rvalue, raw, cl->user_data);
-}
-
-/* Again, here is the generic version of ffi_prep_raw_closure, which
- * will install an intermediate "hub" for translation of arguments from
- * the pointer-array format, to the raw format */
-
-ffi_status
-ffi_prep_java_raw_closure (ffi_raw_closure* cl,
- ffi_cif *cif,
- void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
- void *user_data)
-{
- ffi_status status;
-
- status = ffi_prep_closure ((ffi_closure*) cl,
- cif,
- &ffi_java_translate_args,
- (void*)cl);
- if (status == FFI_OK)
- {
- cl->fun = fun;
- cl->user_data = user_data;
- }
-
- return status;
-}
-
-#endif /* FFI_CLOSURES */
-#endif /* !FFI_NATIVE_RAW_API */
-#endif /* !FFI_NO_RAW_API */
+++ /dev/null
-/* -----------------------------------------------------------------------
- ffi.c
-
- m68k Foreign Function Interface
- ----------------------------------------------------------------------- */
-
-#include <ffi.h>
-#include <ffi_common.h>
-
-#include <stdlib.h>
-
-/* ffi_prep_args is called by the assembly routine once stack space has
- been allocated for the function's arguments. */
-
-static void *
-ffi_prep_args (void *stack, extended_cif *ecif)
-{
- unsigned int i;
- int tmp;
- unsigned int avn;
- void **p_argv;
- char *argp;
- ffi_type **p_arg;
- void *struct_value_ptr;
-
- tmp = 0;
- argp = stack;
-
- if (ecif->cif->rtype->type == FFI_TYPE_STRUCT
- && ecif->cif->rtype->size > 8)
- struct_value_ptr = ecif->rvalue;
- else
- struct_value_ptr = NULL;
-
- avn = ecif->cif->nargs;
- p_argv = ecif->avalue;
-
- for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
- i != 0 && avn != 0;
- i--, p_arg++)
- {
- size_t z;
-
- /* Align if necessary. */
- if (((*p_arg)->alignment - 1) & (unsigned) argp)
- argp = (char *) ALIGN (argp, (*p_arg)->alignment);
-
- if (avn != 0)
- {
- avn--;
- z = (*p_arg)->size;
- if (z < sizeof (int))
- {
- switch ((*p_arg)->type)
- {
- case FFI_TYPE_SINT8:
- *(signed int *) argp = (signed int) *(SINT8 *) *p_argv;
- break;
-
- case FFI_TYPE_UINT8:
- *(unsigned int *) argp = (unsigned int) *(UINT8 *) *p_argv;
- break;
-
- case FFI_TYPE_SINT16:
- *(signed int *) argp = (signed int) *(SINT16 *) *p_argv;
- break;
-
- case FFI_TYPE_UINT16:
- *(unsigned int *) argp = (unsigned int) *(UINT16 *) *p_argv;
- break;
-
- case FFI_TYPE_STRUCT:
- memcpy (argp + sizeof (int) - z, *p_argv, z);
- break;
-
- default:
- FFI_ASSERT (0);
- }
- z = sizeof (int);
- }
- else
- memcpy (argp, *p_argv, z);
- p_argv++;
- argp += z;
- }
- }
-
- return struct_value_ptr;
-}
-
-#define CIF_FLAGS_INT 1
-#define CIF_FLAGS_DINT 2
-#define CIF_FLAGS_FLOAT 4
-#define CIF_FLAGS_DOUBLE 8
-#define CIF_FLAGS_LDOUBLE 16
-#define CIF_FLAGS_POINTER 32
-#define CIF_FLAGS_STRUCT 64
-
-/* Perform machine dependent cif processing */
-ffi_status
-ffi_prep_cif_machdep (ffi_cif *cif)
-{
- /* Set the return type flag */
- switch (cif->rtype->type)
- {
- case FFI_TYPE_VOID:
- cif->flags = 0;
- break;
-
- case FFI_TYPE_STRUCT:
- if (cif->rtype->size > 4 && cif->rtype->size <= 8)
- cif->flags = CIF_FLAGS_DINT;
- else if (cif->rtype->size <= 4)
- cif->flags = CIF_FLAGS_STRUCT;
- else
- cif->flags = 0;
- break;
-
- case FFI_TYPE_FLOAT:
- cif->flags = CIF_FLAGS_FLOAT;
- break;
-
- case FFI_TYPE_DOUBLE:
- cif->flags = CIF_FLAGS_DOUBLE;
- break;
-
- case FFI_TYPE_LONGDOUBLE:
- cif->flags = CIF_FLAGS_LDOUBLE;
- break;
-
- case FFI_TYPE_POINTER:
- cif->flags = CIF_FLAGS_POINTER;
- break;
-
- case FFI_TYPE_SINT64:
- case FFI_TYPE_UINT64:
- cif->flags = CIF_FLAGS_DINT;
- break;
-
- default:
- cif->flags = CIF_FLAGS_INT;
- break;
- }
-
- return FFI_OK;
-}
-
-extern void ffi_call_SYSV (void *(*) (void *, extended_cif *),
- extended_cif *,
- unsigned, unsigned, unsigned,
- void *, void (*fn) ());
-
-void
-ffi_call (ffi_cif *cif, void (*fn) (), void *rvalue, 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
- && cif->rtype->size > 8)
- ecif.rvalue = alloca (cif->rtype->size);
- else
- ecif.rvalue = rvalue;
-
-
- switch (cif->abi)
- {
- case FFI_SYSV:
- ffi_call_SYSV (ffi_prep_args, &ecif, cif->bytes,
- cif->flags, cif->rtype->size * 8,
- ecif.rvalue, fn);
- break;
-
- default:
- FFI_ASSERT (0);
- break;
- }
-}
+++ /dev/null
-/* -----------------------------------------------------------------------
- sysv.S
-
- m68k Foreign Function Interface
- ----------------------------------------------------------------------- */
-
-#define LIBFFI_ASM
-#include <ffi.h>
-
- .text
-
- .globl ffi_call_SYSV
- .type ffi_call_SYSV,@function
-
-ffi_call_SYSV:
- link %fp,#0
- move.l %d2,-(%sp)
-
- | Make room for all of the new args.
- sub.l 16(%fp),%sp
-
- | Call ffi_prep_args
- move.l 12(%fp),-(%sp)
- pea 4(%sp)
- move.l 8(%fp),%a0
- jsr (%a0)
- addq.l #8,%sp
-
- | Pass pointer to struct value, if any
- move.l %a0,%a1
-
- | Call the function
- move.l 32(%fp),%a0
- jsr (%a0)
-
- | Remove the space we pushed for the args
- add.l 16(%fp),%sp
-
- | Load the pointer to storage for the return value
- move.l 28(%fp),%a1
-
- | Load the return type code
- move.l 20(%fp),%d2
-
- | If the return value pointer is NULL, assume no return value.
- tst.l %a1
- jbeq noretval
-
- btst #0,%d2
- jbeq retlongint
- move.l %d0,(%a1)
- jbra epilogue
-
-retlongint:
- btst #1,%d2
- jbeq retfloat
- move.l %d0,(%a1)
- move.l %d1,4(%a1)
- jbra epilogue
-
-retfloat:
- btst #2,%d2
- jbeq retdouble
- fmove.s %fp0,(%a1)
- jbra epilogue
-
-retdouble:
- btst #3,%d2
- jbeq retlongdouble
- fmove.d %fp0,(%a1)
- jbra epilogue
-
-retlongdouble:
- btst #4,%d2
- jbeq retpointer
- fmove.x %fp0,(%a1)
- jbra epilogue
-
-retpointer:
- btst #5,%d2
- jbeq retstruct
- move.l %a0,(%a1)
- jbra epilogue
-
-retstruct:
- btst #6,%d2
- jbeq noretval
- move.l 24(%fp),%d2
- bfins %d0,(%a1){#0,%d2}
-
-noretval:
-epilogue:
- move.l (%sp)+,%d2
- unlk %a6
- rts
- .size ffi_call_SYSV,.-ffi_call_SYSV
+++ /dev/null
-/* -----------------------------------------------------------------------
- ffi.c - Copyright (c) 1996 Cygnus Solutions
-
- MIPS Foreign Function Interface
-
- 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.
- ----------------------------------------------------------------------- */
-
-#include <ffi.h>
-#include <ffi_common.h>
-
-#include <stdlib.h>
-
-#if _MIPS_SIM == _MIPS_SIM_NABI32
-#define FIX_ARGP \
-FFI_ASSERT(argp <= &stack[bytes]); \
-if (argp == &stack[bytes]) \
-{ \
- argp = stack; \
- ffi_stop_here(); \
-}
-#else
-#define FIX_ARGP
-#endif
-
-
-/* ffi_prep_args is called by the assembly routine once stack space
- has been allocated for the function's arguments */
-
-static void ffi_prep_args(char *stack,
- extended_cif *ecif,
- int bytes,
- int flags)
-{
- register int i;
- register int avn;
- register void **p_argv;
- register char *argp;
- register ffi_type **p_arg;
-
-#if _MIPS_SIM == _MIPS_SIM_NABI32
- /* If more than 8 double words are used, the remainder go
- on the stack. We reorder stuff on the stack here to
- support this easily. */
- if (bytes > 8 * SIZEOF_ARG)
- argp = &stack[bytes - (8 * SIZEOF_ARG)];
- else
- argp = stack;
-#else
- argp = stack;
-#endif
-
- memset(stack, 0, bytes);
-
-#if _MIPS_SIM == _MIPS_SIM_NABI32
- if ( ecif->cif->rstruct_flag != 0 )
-#else
- if ( ecif->cif->rtype->type == FFI_TYPE_STRUCT )
-#endif
- {
- *(SLOT_TYPE_UNSIGNED *) argp = (SLOT_TYPE_UNSIGNED) ecif->rvalue;
- argp += sizeof(SLOT_TYPE_UNSIGNED);
- FIX_ARGP;
- }
-
- avn = ecif->cif->nargs;
- p_argv = ecif->avalue;
-
- for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
- i && avn;
- i--, p_arg++)
- {
- size_t z;
-
- /* Align if necessary */
- if (((*p_arg)->alignment - 1) & (unsigned) argp) {
- argp = (char *) ALIGN(argp, (*p_arg)->alignment);
- FIX_ARGP;
- }
-
-#if _MIPS_SIM == _MIPS_SIM_ABI32
-#define OFFSET 0
-#else
-#define OFFSET sizeof(int)
-#endif
-
- if (avn)
- {
- avn--;
- z = (*p_arg)->size;
- if (z < sizeof(SLOT_TYPE_UNSIGNED))
- {
- z = sizeof(SLOT_TYPE_UNSIGNED);
-
- switch ((*p_arg)->type)
- {
- case FFI_TYPE_SINT8:
- *(SINT32 *) &argp[OFFSET] = (SINT32)*(SINT8 *)(* p_argv);
- break;
-
- case FFI_TYPE_UINT8:
- *(UINT32 *) &argp[OFFSET] = (UINT32)*(UINT8 *)(* p_argv);
- break;
-
- case FFI_TYPE_SINT16:
- *(SINT32 *) &argp[OFFSET] = (SINT32)*(SINT16 *)(* p_argv);
- break;
-
- case FFI_TYPE_UINT16:
- *(UINT32 *) &argp[OFFSET] = (UINT32)*(UINT16 *)(* p_argv);
- break;
-
- case FFI_TYPE_SINT32:
- *(SINT32 *) &argp[OFFSET] = (SINT32)*(SINT32 *)(* p_argv);
- break;
-
- case FFI_TYPE_UINT32:
- case FFI_TYPE_POINTER:
- *(UINT32 *) &argp[OFFSET] = (UINT32)*(UINT32 *)(* p_argv);
- break;
-
- /* This can only happen with 64bit slots */
- case FFI_TYPE_FLOAT:
- *(float *) argp = *(float *)(* p_argv);
- break;
-
- /* Handle small structures */
- case FFI_TYPE_STRUCT:
- memcpy(argp, *p_argv, (*p_arg)->size);
- break;
-
- default:
- FFI_ASSERT(0);
- }
- }
- else
- {
-#if _MIPS_SIM == _MIPS_SIM_ABI32
- memcpy(argp, *p_argv, z);
-#else
- {
- unsigned end = (unsigned) argp+z;
- unsigned cap = (unsigned) stack+bytes;
-
- /* Check if the data will fit within the register
- space. Handle it if it doesn't. */
-
- if (end <= cap)
- memcpy(argp, *p_argv, z);
- else
- {
- unsigned portion = end - cap;
-
- memcpy(argp, *p_argv, portion);
- argp = stack;
- memcpy(argp,
- (void*)((unsigned)(*p_argv)+portion), z - portion);
- }
- }
-#endif
- }
- p_argv++;
- argp += z;
- FIX_ARGP;
- }
- }
-
- return;
-}
-
-#if _MIPS_SIM == _MIPS_SIM_NABI32
-
-/* The n32 spec says that if "a chunk consists solely of a double
- float field (but not a double, which is part of a union), it
- is passed in a floating point register. Any other chunk is
- passed in an integer register". This code traverses structure
- definitions and generates the appropriate flags. */
-
-unsigned calc_n32_struct_flags(ffi_type *arg, unsigned *shift)
-{
- unsigned flags = 0;
- unsigned index = 0;
-
- ffi_type *e;
-
- while (e = arg->elements[index])
- {
- if (e->type == FFI_TYPE_DOUBLE)
- {
- flags += (FFI_TYPE_DOUBLE << *shift);
- *shift += FFI_FLAG_BITS;
- }
- else if (e->type == FFI_TYPE_STRUCT)
- flags += calc_n32_struct_flags(e, shift);
- else
- *shift += FFI_FLAG_BITS;
-
- index++;
- }
-
- return flags;
-}
-
-unsigned calc_n32_return_struct_flags(ffi_type *arg)
-{
- unsigned flags = 0;
- unsigned index = 0;
- unsigned small = FFI_TYPE_SMALLSTRUCT;
- ffi_type *e;
-
- /* Returning structures under n32 is a tricky thing.
- A struct with only one or two floating point fields
- is returned in $f0 (and $f2 if necessary). Any other
- struct results at most 128 bits are returned in $2
- (the first 64 bits) and $3 (remainder, if necessary).
- Larger structs are handled normally. */
-
- if (arg->size > 16)
- return 0;
-
- if (arg->size > 8)
- small = FFI_TYPE_SMALLSTRUCT2;
-
- e = arg->elements[0];
- if (e->type == FFI_TYPE_DOUBLE)
- flags = FFI_TYPE_DOUBLE << FFI_FLAG_BITS;
- else if (e->type == FFI_TYPE_FLOAT)
- flags = FFI_TYPE_FLOAT << FFI_FLAG_BITS;
-
- if (flags && (e = arg->elements[1]))
- {
- if (e->type == FFI_TYPE_DOUBLE)
- flags += FFI_TYPE_DOUBLE;
- else if (e->type == FFI_TYPE_FLOAT)
- flags += FFI_TYPE_FLOAT;
- else
- return small;
-
- if (flags && (arg->elements[2]))
- {
- /* There are three arguments and the first two are
- floats! This must be passed the old way. */
- return small;
- }
- }
- else
- if (!flags)
- return small;
-
- return flags;
-}
-
-#endif
-
-/* Perform machine dependent cif processing */
-ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
-{
- cif->flags = 0;
-
-#if _MIPS_SIM == _MIPS_SIM_ABI32
- /* Set the flags necessary for O32 processing */
-
- if (cif->rtype->type != FFI_TYPE_STRUCT)
- {
- if (cif->nargs > 0)
- {
- switch ((cif->arg_types)[0]->type)
- {
- case FFI_TYPE_FLOAT:
- case FFI_TYPE_DOUBLE:
- cif->flags += (cif->arg_types)[0]->type;
- break;
-
- default:
- break;
- }
-
- if (cif->nargs > 1)
- {
- /* Only handle the second argument if the first
- is a float or double. */
- if (cif->flags)
- {
- switch ((cif->arg_types)[1]->type)
- {
- case FFI_TYPE_FLOAT:
- case FFI_TYPE_DOUBLE:
- cif->flags += (cif->arg_types)[1]->type << FFI_FLAG_BITS;
- break;
-
- default:
- break;
- }
- }
- }
- }
- }
-
- /* Set the return type flag */
- switch (cif->rtype->type)
- {
- case FFI_TYPE_VOID:
- case FFI_TYPE_STRUCT:
- case FFI_TYPE_FLOAT:
- case FFI_TYPE_DOUBLE:
- cif->flags += cif->rtype->type << (FFI_FLAG_BITS * 2);
- break;
-
- default:
- cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 2);
- break;
- }
-#endif
-
-#if _MIPS_SIM == _MIPS_SIM_NABI32
- /* Set the flags necessary for N32 processing */
- {
- unsigned shift = 0;
- unsigned count = (cif->nargs < 8) ? cif->nargs : 8;
- unsigned index = 0;
-
- unsigned struct_flags = 0;
-
- if (cif->rtype->type == FFI_TYPE_STRUCT)
- {
- struct_flags = calc_n32_return_struct_flags(cif->rtype);
-
- if (struct_flags == 0)
- {
- /* This means that the structure is being passed as
- a hidden argument */
-
- shift = FFI_FLAG_BITS;
- count = (cif->nargs < 7) ? cif->nargs : 7;
-
- cif->rstruct_flag = !0;
- }
- else
- cif->rstruct_flag = 0;
- }
- else
- cif->rstruct_flag = 0;
-
- while (count-- > 0)
- {
- switch ((cif->arg_types)[index]->type)
- {
- case FFI_TYPE_FLOAT:
- case FFI_TYPE_DOUBLE:
- cif->flags += ((cif->arg_types)[index]->type << shift);
- shift += FFI_FLAG_BITS;
- break;
-
- case FFI_TYPE_STRUCT:
- cif->flags += calc_n32_struct_flags((cif->arg_types)[index],
- &shift);
- break;
-
- default:
- shift += FFI_FLAG_BITS;
- }
-
- index++;
- }
-
- /* Set the return type flag */
- switch (cif->rtype->type)
- {
- case FFI_TYPE_STRUCT:
- {
- if (struct_flags == 0)
- {
- /* The structure is returned through a hidden
- first argument. Do nothing, 'cause FFI_TYPE_VOID
- is 0 */
- }
- else
- {
- /* The structure is returned via some tricky
- mechanism */
- cif->flags += FFI_TYPE_STRUCT << (FFI_FLAG_BITS * 8);
- cif->flags += struct_flags << (4 + (FFI_FLAG_BITS * 8));
- }
- break;
- }
-
- case FFI_TYPE_VOID:
- /* Do nothing, 'cause FFI_TYPE_VOID is 0 */
- break;
-
- case FFI_TYPE_FLOAT:
- case FFI_TYPE_DOUBLE:
- cif->flags += cif->rtype->type << (FFI_FLAG_BITS * 8);
- break;
-
- default:
- cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 8);
- break;
- }
- }
-#endif
-
- return FFI_OK;
-}
-
-/* Low level routine for calling O32 functions */
-extern int ffi_call_O32(void (*)(char *, extended_cif *, int, int),
- extended_cif *, unsigned,
- unsigned, unsigned *, void (*)());
-
-/* Low level routine for calling N32 functions */
-extern int ffi_call_N32(void (*)(char *, extended_cif *, int, int),
- extended_cif *, unsigned,
- unsigned, unsigned *, void (*)());
-
-void ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, 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))
- ecif.rvalue = alloca(cif->rtype->size);
- else
- ecif.rvalue = rvalue;
-
- switch (cif->abi)
- {
-#if _MIPS_SIM == _MIPS_SIM_ABI32
- case FFI_O32:
- ffi_call_O32(ffi_prep_args, &ecif, cif->bytes,
- cif->flags, ecif.rvalue, fn);
- break;
-#endif
-
-#if _MIPS_SIM == _MIPS_SIM_NABI32
- case FFI_N32:
- ffi_call_N32(ffi_prep_args, &ecif, cif->bytes,
- cif->flags, ecif.rvalue, fn);
- break;
-#endif
-
- default:
- FFI_ASSERT(0);
- break;
- }
-}
+++ /dev/null
-/* -----------------------------------------------------------------------
- n32.S - Copyright (c) 1996, 1998 Cygnus Solutions
-
- MIPS Foreign Function Interface
-
- 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.
- ----------------------------------------------------------------------- */
-
-#define LIBFFI_ASM
-#include <ffi.h>
-
-/* Only build this code if we are compiling for n32 */
-
-#if defined(FFI_MIPS_N32)
-
-#define callback a0
-#define bytes a2
-#define flags a3
-#define raddr a4
-#define fn a5
-
-#define SIZEOF_FRAME ( 8 * SIZEOF_ARG )
-
- .text
- .align 2
- .globl ffi_call_N32
- .ent ffi_call_N32
-ffi_call_N32:
-
- # Prologue
- SUBU $sp, SIZEOF_FRAME # Frame size
- REG_S $fp, SIZEOF_FRAME - 2*SIZEOF_ARG($sp) # Save frame pointer
- REG_S ra, SIZEOF_FRAME - 1*SIZEOF_ARG($sp) # Save return address
- move $fp, $sp
-
- move t9, callback # callback function pointer
- REG_S bytes, 2*SIZEOF_ARG($fp) # bytes
- REG_S flags, 3*SIZEOF_ARG($fp) # flags
- REG_S raddr, 4*SIZEOF_ARG($fp) # raddr
- REG_S fn, 5*SIZEOF_ARG($fp) # fn
-
- # Allocate at least 4 words in the argstack
- move v0, bytes
- bge bytes, 4 * SIZEOF_ARG, bigger
- LI v0, 4 * SIZEOF_ARG
- b sixteen
-
- bigger:
- ADDU t4, v0, 2 * SIZEOF_ARG -1 # make sure it is aligned
- and v0, t4, -2 * SIZEOF_ARG # to a proper boundry.
-
-sixteen:
- SUBU $sp, $sp, v0 # move the stack pointer to reflect the
- # arg space
-
- ADDU a0, $sp, 0 # 4 * SIZEOF_ARG
- ADDU a3, $fp, 3 * SIZEOF_ARG
-
- # Call ffi_prep_args
- jal t9
-
- # ADDU $sp, $sp, 4 * SIZEOF_ARG # adjust $sp to new args
-
- # Copy the stack pointer to t9
- move t9, $sp
-
- # Fix the stack if there are more than 8 64bit slots worth
- # of arguments.
-
- # Load the number of bytes
- REG_L t6, 2*SIZEOF_ARG($fp)
-
- # Is it bigger than 8 * SIZEOF_ARG?
- dadd t7, $0, 8 * SIZEOF_ARG
- dsub t8, t6, t7
- bltz t8, loadregs
-
- add t9, t9, t8
-
-loadregs:
-
- REG_L t4, 3*SIZEOF_ARG($fp) # load the flags word
- add t6, t4, 0 # and copy it into t6
-
- and t4, ((1<<FFI_FLAG_BITS)-1)
- bnez t4, arg1_floatp
- REG_L a0, 0*SIZEOF_ARG(t9)
- b arg1_next
-arg1_floatp:
- bne t4, FFI_TYPE_FLOAT, arg1_doublep
- l.s $f12, 0*SIZEOF_ARG(t9)
- b arg1_next
-arg1_doublep:
- l.d $f12, 0*SIZEOF_ARG(t9)
-arg1_next:
-
- add t4, t6, 0
- SRL t4, 1*FFI_FLAG_BITS
- and t4, ((1<<FFI_FLAG_BITS)-1)
- bnez t4, arg2_floatp
- REG_L a1, 1*SIZEOF_ARG(t9)
- b arg2_next
-arg2_floatp:
- bne t4, FFI_TYPE_FLOAT, arg2_doublep
- l.s $f13, 1*SIZEOF_ARG(t9)
- b arg2_next
-arg2_doublep:
- l.d $f13, 1*SIZEOF_ARG(t9)
-arg2_next:
-
- add t4, t6, 0
- SRL t4, 2*FFI_FLAG_BITS
- and t4, ((1<<FFI_FLAG_BITS)-1)
- bnez t4, arg3_floatp
- REG_L a2, 2*SIZEOF_ARG(t9)
- b arg3_next
-arg3_floatp:
- bne t4, FFI_TYPE_FLOAT, arg3_doublep
- l.s $f14, 2*SIZEOF_ARG(t9)
- b arg3_next
-arg3_doublep:
- l.d $f14, 2*SIZEOF_ARG(t9)
-arg3_next:
-
- add t4, t6, 0
- SRL t4, 3*FFI_FLAG_BITS
- and t4, ((1<<FFI_FLAG_BITS)-1)
- bnez t4, arg4_floatp
- REG_L a3, 3*SIZEOF_ARG(t9)
- b arg4_next
-arg4_floatp:
- bne t4, FFI_TYPE_FLOAT, arg4_doublep
- l.s $f15, 3*SIZEOF_ARG(t9)
- b arg4_next
-arg4_doublep:
- l.d $f15, 3*SIZEOF_ARG(t9)
-arg4_next:
-
- add t4, t6, 0
- SRL t4, 4*FFI_FLAG_BITS
- and t4, ((1<<FFI_FLAG_BITS)-1)
- bnez t4, arg5_floatp
- REG_L a4, 4*SIZEOF_ARG(t9)
- b arg5_next
-arg5_floatp:
- bne t4, FFI_TYPE_FLOAT, arg5_doublep
- l.s $f16, 4*SIZEOF_ARG(t9)
- b arg5_next
-arg5_doublep:
- l.d $f16, 4*SIZEOF_ARG(t9)
-arg5_next:
-
- add t4, t6, 0
- SRL t4, 5*FFI_FLAG_BITS
- and t4, ((1<<FFI_FLAG_BITS)-1)
- bnez t4, arg6_floatp
- REG_L a5, 5*SIZEOF_ARG(t9)
- b arg6_next
-arg6_floatp:
- bne t4, FFI_TYPE_FLOAT, arg6_doublep
- l.s $f17, 5*SIZEOF_ARG(t9)
- b arg6_next
-arg6_doublep:
- l.d $f17, 5*SIZEOF_ARG(t9)
-arg6_next:
-
- add t4, t6, 0
- SRL t4, 6*FFI_FLAG_BITS
- and t4, ((1<<FFI_FLAG_BITS)-1)
- bnez t4, arg7_floatp
- REG_L a6, 6*SIZEOF_ARG(t9)
- b arg7_next
-arg7_floatp:
- bne t4, FFI_TYPE_FLOAT, arg7_doublep
- l.s $f18, 6*SIZEOF_ARG(t9)
- b arg7_next
-arg7_doublep:
- l.d $f18, 6*SIZEOF_ARG(t9)
-arg7_next:
-
- add t4, t6, 0
- SRL t4, 7*FFI_FLAG_BITS
- and t4, ((1<<FFI_FLAG_BITS)-1)
- bnez t4, arg8_floatp
- REG_L a7, 7*SIZEOF_ARG(t9)
- b arg8_next
-arg8_floatp:
- bne t4, FFI_TYPE_FLOAT, arg8_doublep
- l.s $f19, 7*SIZEOF_ARG(t9)
- b arg8_next
-arg8_doublep:
- l.d $f19, 7*SIZEOF_ARG(t9)
-arg8_next:
-
-callit:
- # Load the function pointer
- REG_L t9, 5*SIZEOF_ARG($fp)
-
- # If the return value pointer is NULL, assume no return value.
- REG_L t5, 4*SIZEOF_ARG($fp)
- beqz t5, noretval
-
- # Shift the return type flag over
- SRL t6, 8*FFI_FLAG_BITS
-
- bne t6, FFI_TYPE_INT, retfloat
- jal t9
- REG_L t4, 4*SIZEOF_ARG($fp)
- REG_S v0, 0(t4)
- b epilogue
-
-retfloat:
- bne t6, FFI_TYPE_FLOAT, retdouble
- jal t9
- REG_L t4, 4*SIZEOF_ARG($fp)
- s.s $f0, 0(t4)
- b epilogue
-
-retdouble:
- bne t6, FFI_TYPE_DOUBLE, retstruct_d
- jal t9
- REG_L t4, 4*SIZEOF_ARG($fp)
- s.d $f0, 0(t4)
- b epilogue
-
-retstruct_d:
- bne t6, FFI_TYPE_STRUCT_D, retstruct_f
- jal t9
- REG_L t4, 4*SIZEOF_ARG($fp)
- s.d $f0, 0(t4)
- b epilogue
-
-retstruct_f:
- bne t6, FFI_TYPE_STRUCT_F, retstruct_d_d
- jal t9
- REG_L t4, 4*SIZEOF_ARG($fp)
- s.s $f0, 0(t4)
- b epilogue
-
-retstruct_d_d:
- bne t6, FFI_TYPE_STRUCT_DD, retstruct_f_f
- jal t9
- REG_L t4, 4*SIZEOF_ARG($fp)
- s.d $f0, 0(t4)
- s.d $f2, 8(t4)
- b epilogue
-
-retstruct_f_f:
- bne t6, FFI_TYPE_STRUCT_FF, retstruct_d_f
- jal t9
- REG_L t4, 4*SIZEOF_ARG($fp)
- s.s $f0, 0(t4)
- s.s $f2, 4(t4)
- b epilogue
-
-retstruct_d_f:
- bne t6, FFI_TYPE_STRUCT_DF, retstruct_f_d
- jal t9
- REG_L t4, 4*SIZEOF_ARG($fp)
- s.d $f0, 0(t4)
- s.s $f2, 8(t4)
- b epilogue
-
-retstruct_f_d:
- bne t6, FFI_TYPE_STRUCT_FD, retstruct_small
- jal t9
- REG_L t4, 4*SIZEOF_ARG($fp)
- s.s $f0, 0(t4)
- s.d $f2, 8(t4)
- b epilogue
-
-retstruct_small:
- bne t6, FFI_TYPE_STRUCT_SMALL, retstruct_small2
- jal t9
- REG_L t4, 4*SIZEOF_ARG($fp)
- REG_S v0, 0(t4)
- b epilogue
-
-retstruct_small2:
- bne t6, FFI_TYPE_STRUCT_SMALL2, retstruct
- jal t9
- REG_L t4, 4*SIZEOF_ARG($fp)
- REG_S v0, 0(t4)
- REG_S v1, 8(t4)
- b epilogue
-
-retstruct:
-noretval:
- jal t9
-
- # Epilogue
-epilogue:
- move $sp, $fp
- REG_L $fp, SIZEOF_FRAME - 2*SIZEOF_ARG($sp) # Restore frame pointer
- REG_L ra, SIZEOF_FRAME - 1*SIZEOF_ARG($sp) # Restore return address
- ADDU $sp, SIZEOF_FRAME # Fix stack pointer
- j ra
-
- .end ffi_call_N32
-
-#endif
+++ /dev/null
-/* -----------------------------------------------------------------------
- o32.S - Copyright (c) 1996, 1998 Cygnus Solutions
-
- MIPS Foreign Function Interface
-
- 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.
- ----------------------------------------------------------------------- */
-
-#define LIBFFI_ASM
-#include <ffi.h>
-
-/* Only build this code if we are compiling for o32 */
-
-#if defined(FFI_MIPS_O32)
-
-#define callback a0
-#define bytes a2
-#define flags a3
-
-#define SIZEOF_FRAME ( 4 * SIZEOF_ARG + 2 * SIZEOF_ARG )
-
- .text
- .align 2
- .globl ffi_call_O32
- .ent ffi_call_O32
-ffi_call_O32:
-
- # Prologue
- SUBU $sp, SIZEOF_FRAME # Frame size
- REG_S $fp, SIZEOF_FRAME - 2*SIZEOF_ARG($sp) # Save frame pointer
- REG_S ra, SIZEOF_FRAME - 1*SIZEOF_ARG($sp) # Save return address
- move $fp, $sp
-
- move t9, callback # callback function pointer
- REG_S flags, SIZEOF_FRAME + 3*SIZEOF_ARG($fp) # flags
-
- # Allocate at least 4 words in the argstack
- move v0, bytes
- bge bytes, 4 * SIZEOF_ARG, bigger
- LI v0, 4 * SIZEOF_ARG
- b sixteen
-
-bigger:
- ADDU t0, v0, 2 * SIZEOF_ARG -1 # make sure it is aligned
- and v0, t0, -2 * SIZEOF_ARG # to an 8 byte boundry
-
-sixteen:
- SUBU $sp, $sp, v0 # move the stack pointer to reflect the
- # arg space
-
- ADDU a0, $sp, 4 * SIZEOF_ARG
- ADDU a3, $fp, SIZEOF_FRAME + 3*SIZEOF_ARG
-
- jal t9
-
- REG_L t0, SIZEOF_FRAME + 3*SIZEOF_ARG($fp) # load the flags word
- add t2, t0, 0 # and copy it into t2
-
- and t0, ((1<<4)-1) # mask out the return type
- SRL t2, 4 # shift our arg info
-
- ADDU $sp, $sp, 4 * SIZEOF_ARG # adjust $sp to new args
-
- bnez t0, pass_d # make it quick for int
- REG_L a0, 0*SIZEOF_ARG($sp) # just go ahead and load the
- REG_L a1, 1*SIZEOF_ARG($sp) # four regs.
- REG_L a2, 2*SIZEOF_ARG($sp)
- REG_L a3, 3*SIZEOF_ARG($sp)
- b call_it
-
-pass_d:
- bne t0, FFI_ARGS_D, pass_f
- l.d $f12, 0*SIZEOF_ARG($sp) # load $fp regs from args
- REG_L a2, 2*SIZEOF_ARG($sp) # passing a double
- REG_L a3, 3*SIZEOF_ARG($sp)
- b call_it
-
-pass_f:
- bne t0, FFI_ARGS_F, pass_d_d
- l.s $f12, 0*SIZEOF_ARG($sp) # load $fp regs from args
- REG_L a1, 1*SIZEOF_ARG($sp) # passing a float
- REG_L a2, 2*SIZEOF_ARG($sp)
- REG_L a3, 3*SIZEOF_ARG($sp)
- b call_it
-
-pass_d_d:
- bne t0, FFI_ARGS_DD, pass_f_f
- l.d $f12, 0*SIZEOF_ARG($sp) # load $fp regs from args
- l.d $f14, 2*SIZEOF_ARG($sp) # passing two doubles
- b call_it
-
-pass_f_f:
- bne t0, FFI_ARGS_FF, pass_d_f
- l.s $f12, 0*SIZEOF_ARG($sp) # load $fp regs from args
- l.s $f14, 1*SIZEOF_ARG($sp) # passing two floats
- REG_L a2, 2*SIZEOF_ARG($sp)
- REG_L a3, 3*SIZEOF_ARG($sp)
- b call_it
-
-pass_d_f:
- bne t0, FFI_ARGS_DF, pass_f_d
- l.d $f12, 0*SIZEOF_ARG($sp) # load $fp regs from args
- l.s $f14, 2*SIZEOF_ARG($sp) # passing double and float
- REG_L a3, 3*SIZEOF_ARG($sp)
- b call_it
-
-pass_f_d:
- # assume that the only other combination must be float then double
- # bne t0, FFI_ARGS_F_D, call_it
- l.s $f12, 0*SIZEOF_ARG($sp) # load $fp regs from args
- l.d $f14, 2*SIZEOF_ARG($sp) # passing double and float
-
-call_it:
- # Load the function pointer
- REG_L t9, SIZEOF_FRAME + 5*SIZEOF_ARG($fp)
-
- # If the return value pointer is NULL, assume no return value.
- REG_L t1, SIZEOF_FRAME + 4*SIZEOF_ARG($fp)
- beqz t1, noretval
-
- bne t2, FFI_TYPE_INT, retfloat
- jal t9
- REG_L t0, SIZEOF_FRAME + 4*SIZEOF_ARG($fp)
- REG_S v0, 0(t0)
- b epilogue
-
-retfloat:
- bne t2, FFI_TYPE_FLOAT, retdouble
- jal t9
- REG_L t0, SIZEOF_FRAME + 4*SIZEOF_ARG($fp)
- s.s $f0, 0(t0)
- b epilogue
-
-retdouble:
- bne t2, FFI_TYPE_DOUBLE, noretval
- jal t9
- REG_L t0, SIZEOF_FRAME + 4*SIZEOF_ARG($fp)
- s.d $f0, 0(t0)
- b epilogue
-
-noretval:
- jal t9
-
- # Epilogue
-epilogue:
- move $sp, $fp
- REG_L $fp, SIZEOF_FRAME - 2*SIZEOF_ARG($sp) # Restore frame pointer
- REG_L ra, SIZEOF_FRAME - 1*SIZEOF_ARG($sp) # Restore return address
- ADDU $sp, SIZEOF_FRAME # Fix stack pointer
- j ra
-
- .end ffi_call_O32
-
-#endif
+++ /dev/null
-/* -----------------------------------------------------------------------
- asm.h - Copyright (c) 1998 Geoffrey Keating
-
- PowerPC Assembly glue.
-
- $Id: asm.h,v 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
-
+++ /dev/null
-/* -----------------------------------------------------------------------
- ffi.c - Copyright (c) 1998 Geoffrey Keating
-
- PowerPC Foreign Function Interface
-
- $Id: ffi.c,v 1.2 2001/04/09 00:58:37 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>
-
-extern void ffi_closure_SYSV(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 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(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));
-
- /* '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)(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:
- case FFI_TYPE_DOUBLE:
- if ((*ptr)->type == FFI_TYPE_FLOAT)
- double_tmp = *(float *)*p_argv;
- else
- 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)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);
-}
-
-/* Perform machine dependent cif processing */
-ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
-{
- /* All this is for the SYSV ABI. */
- int i;
- ffi_type **ptr;
- unsigned bytes;
- int fparg_count = 0, intarg_count = 0;
- unsigned flags = 0;
- unsigned struct_copy_size = 0;
-
- /* 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);
-
- /* 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;
- - Larger structures and long double (if not equivalent to double) values
- are allocated space and a pointer is passed as the first argument. */
- switch (cif->rtype->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)
- 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;
- }
-
- /* 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
- /* 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;
- }
- }
-
- 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;
-
- /* 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);
-
- /* 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)());
-/*@=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_SYSV:
- case FFI_GCC_SYSV:
- /*@-usedef@*/
- ffi_call_SYSV(&ecif, -cif->bytes,
- cif->flags, ecif.rvalue, fn);
- /*@=usedef@*/
- break;
- default:
- FFI_ASSERT(0);
- break;
- }
-}
-
-
-static void flush_icache(char *, int);
-
-ffi_status
-ffi_prep_closure (ffi_closure* closure,
- ffi_cif* cif,
- void (*fun)(ffi_cif*, void*, void**, void*),
- void *user_data)
-{
- 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 */
-
- closure->cif = cif;
- closure->fun = fun;
- closure->user_data = user_data;
-
- /* Flush the icache. */
- flush_icache(&closure->tramp[0],FFI_TRAMPOLINE_SIZE);
-
- return FFI_OK;
-}
-
-
-#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");
-}
-
-
-int ffi_closure_helper_SYSV (ffi_closure*, void*, unsigned long*,
- unsigned long*, 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, unsigned long * 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 = *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:
- case FFI_TYPE_STRUCT:
- /* 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_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). This is also true
- * of floats passed on the outgoing parameter stack.
- * Also, on the outgoing stack all values are aligned
- * to 8
- *
- * Don't you just love the simplicity of this ABI!
- */
-
- /* there are 8 64bit floating point registers */
-
- if (nf < 8) {
- temp = *(double*)pfr;
- *(float*)pfr = (float)temp;
- avalue[i] = pfr;
- nf++;
- pfr+=2;
- } 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...
- */
- if (((long)pst) & 4) pst++;
- temp = *(double*)pst;
- *(float*)pst = (float)temp;
- avalue[i] = pst;
- nf++;
- pst+=2;
- }
- 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+=2;
- } 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_osf how to perform return type promotions. */
- return cif->rtype->type;
-
-}
-
-
-
-
-
+++ /dev/null
-#define LIBFFI_ASM
-#include <powerpc/asm.h>
-
-.globl ffi_closure_helper_SYSV
-
-ENTRY(ffi_closure_SYSV)
- stwu %r1,-144(%r1)
- mflr %r0
- stw %r31,140(%r1)
- 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
- addis %r4,0,.L60@ha # get address of jump table
- addi %r4,%r4,.L60@l
- 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
- .align 2
-.L60:
- .long .L44-.L60 # FFI_TYPE_VOID
- .long .L50-.L60 # FFI_TYPE_INT
- .long .L47-.L60 # FFI_TYPE_FLOAT
- .long .L46-.L60 # FFI_TYPE_DOUBLE
- .long .L46-.L60 # FFI_TYPE_LONGDOUBLE
- .long .L56-.L60 # FFI_TYPE_UINT8
- .long .L55-.L60 # FFI_TYPE_SINT8
- .long .L58-.L60 # FFI_TYPE_UINT16
- .long .L57-.L60 # FFI_TYPE_SINT16
- .long .L50-.L60 # FFI_TYPE_UINT32
- .long .L50-.L60 # FFI_TYPE_SINT32
- .long .L48-.L60 # FFI_TYPE_UINT64
- .long .L48-.L60 # FFI_TYPE_SINT64
- .long .L44-.L60 # FFI_TYPE_STRUCT
- .long .L50-.L60 # FFI_TYPE_POINTER
-
-
-# case double
-.L46:
- lfd %f1,0(%r5)
- b .L44
-
-# case float
-.L47:
- lfs %f1,0(%r5)
- b .L44
-
-# case long long
-.L48:
- lwz %r3,0(%r5)
- lwz %r4,4(%r5)
- b .L44
-
-# case default / int32 / pointer
-.L50:
- lwz %r3,0(%r5)
- b .L44
-
-# case signed int8
-.L55:
- addi %r5,%r5,3
- lbz %r3,0(%r5)
- extsb %r3,%r3
- b .L44
-
-# case unsigned int8
-.L56:
- addi %r5,%r5,3
- lbz %r3,0(%r5)
- b .L44
-
-# case signed int16
-.L57:
- addi %r5,%r5,2
- lhz %r3,0(%r5)
- extsh %r3,%r3
- b .L44
-
-#case unsigned int16
-.L58:
- addi %r5,%r5,2
- lhz %r3,0(%r5)
-
-# case void / done
-.L44:
-
- lwz %r11,0(%r1)
- lwz %r0,4(%r11)
- mtlr %r0
- lwz %r31,-4(%r11)
- mr %r1,%r11
- blr
-END(ffi_closure_SYSV)
-
-
-
-
+++ /dev/null
-/* -----------------------------------------------------------------------
- sysv.h - Copyright (c) 1998 Geoffrey Keating
-
- PowerPC Assembly glue.
-
- $Id: sysv.S,v 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 <ffi.h>
-#include <powerpc/asm.h>
-
- .globl ffi_prep_args
-ENTRY(ffi_call_SYSV)
- /* 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, 4(%r8)
-
- /* 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
- bl JUMPTARGET(ffi_prep_args)
-
- /* 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)
-END(ffi_call_SYSV)
+++ /dev/null
-/* -----------------------------------------------------------------------
- prep_cif.c - Copyright (c) 1996, 1998 Cygnus Solutions
-
- 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 RED HAT 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>
-
-
-/* Round up to SIZEOF_ARG. */
-
-#define STACK_ARG_SIZE(x) ALIGN(x, SIZEOF_ARG)
-
-/* Perform machine independent initialization of aggregate type
- specifications. */
-
-static ffi_status initialize_aggregate(/*@out@*/ ffi_type *arg)
-{
- ffi_type **ptr;
-
- FFI_ASSERT(arg != NULL);
-
- /*@-usedef@*/
-
- FFI_ASSERT(arg->elements != NULL);
- FFI_ASSERT(arg->size == 0);
- FFI_ASSERT(arg->alignment == 0);
-
- ptr = &(arg->elements[0]);
-
- while ((*ptr) != NULL)
- {
- if (((*ptr)->size == 0) && (initialize_aggregate((*ptr)) != FFI_OK))
- return FFI_BAD_TYPEDEF;
-
- /* Perform a sanity check on the argument type */
- FFI_ASSERT(ffi_type_test((*ptr)));
-
- arg->size = ALIGN(arg->size, (*ptr)->alignment);
- arg->size += (*ptr)->size;
-
- arg->alignment = (arg->alignment > (*ptr)->alignment) ?
- arg->alignment : (*ptr)->alignment;
-
- ptr++;
- }
-
- if (arg->size == 0)
- return FFI_BAD_TYPEDEF;
- else
- return FFI_OK;
-
- /*@=usedef@*/
-}
-
-/* Perform machine independent ffi_cif preparation, then call
- machine dependent routine. */
-
-ffi_status ffi_prep_cif(/*@out@*/ /*@partial@*/ ffi_cif *cif,
- ffi_abi abi, unsigned int nargs,
- /*@dependent@*/ /*@out@*/ /*@partial@*/ ffi_type *rtype,
- /*@dependent@*/ ffi_type **atypes)
-{
- unsigned bytes = 0;
- unsigned int i;
- ffi_type **ptr;
-
- FFI_ASSERT(cif != NULL);
- FFI_ASSERT((abi > FFI_FIRST_ABI) && (abi < FFI_LAST_ABI));
-
- cif->abi = abi;
- cif->arg_types = atypes;
- cif->nargs = nargs;
- cif->rtype = rtype;
-
- cif->flags = 0;
-
- /* Initialize the return type if necessary */
- /*@-usedef@*/
- if ((cif->rtype->size == 0) && (initialize_aggregate(cif->rtype) != FFI_OK))
- return FFI_BAD_TYPEDEF;
- /*@=usedef@*/
-
- /* Perform a sanity check on the return type */
- FFI_ASSERT(ffi_type_test(cif->rtype));
-
-#ifndef M68K
- /* Make space for the return structure pointer */
- if (cif->rtype->type == FFI_TYPE_STRUCT
-#ifdef SPARC
- && (cif->abi != FFI_V9 || cif->rtype->size > 32)
-#endif
- )
- bytes = STACK_ARG_SIZE(sizeof(void*));
-#endif
-
- for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
- {
- /* Perform a sanity check on the argument type */
- FFI_ASSERT(ffi_type_test(*ptr));
-
- /* Initialize any uninitialized aggregate type definitions */
- if (((*ptr)->size == 0) && (initialize_aggregate((*ptr)) != FFI_OK))
- return FFI_BAD_TYPEDEF;
-
-#ifdef SPARC
- if (((*ptr)->type == FFI_TYPE_STRUCT
- && ((*ptr)->size > 16 || cif->abi != FFI_V9))
- || ((*ptr)->type == FFI_TYPE_LONGDOUBLE
- && cif->abi != FFI_V9))
- bytes += sizeof(void*);
- else
-#endif
- {
- /* Add any padding if necessary */
- if (((*ptr)->alignment - 1) & bytes)
- bytes = ALIGN(bytes, (*ptr)->alignment);
-
- bytes += STACK_ARG_SIZE((*ptr)->size);
- }
- }
-
- cif->bytes = bytes;
-
- /* Perform machine dependent cif processing */
- return ffi_prep_cif_machdep(cif);
-}
+++ /dev/null
-/* -----------------------------------------------------------------------
- raw_api.c - Copyright (c) 1999 Cygnus Solutions
-
- Author: Kresten Krab Thorup <krab@gnu.org>
-
- $Id $
-
- 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 RED HAT 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.
- ----------------------------------------------------------------------- */
-
-/* This file defines generic functions for use with the raw api. */
-
-#include <ffi.h>
-#include <ffi_common.h>
-
-#if !FFI_NO_RAW_API
-
-size_t
-ffi_raw_size (ffi_cif *cif)
-{
- size_t result = 0;
- int i;
-
- ffi_type **at = cif->arg_types;
-
- for (i = cif->nargs-1; i >= 0; i--, at++)
- {
-#if !FFI_NO_STRUCTS
- if ((*at)->type == FFI_TYPE_STRUCT)
- result += ALIGN (sizeof (void*), SIZEOF_ARG);
- else
-#endif
- result += ALIGN ((*at)->size, SIZEOF_ARG);
- }
-
- return result;
-}
-
-
-void
-ffi_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args)
-{
- unsigned i;
- ffi_type **tp = cif->arg_types;
-
-#if WORDS_BIGENDIAN
-
- for (i = 0; i < cif->nargs; i++, tp++, args++)
- {
- switch ((*tp)->type)
- {
- case FFI_TYPE_UINT8:
- case FFI_TYPE_SINT8:
- *args = (void*) ((char*)(raw++) + SIZEOF_ARG - 1);
- break;
-
- case FFI_TYPE_UINT16:
- case FFI_TYPE_SINT16:
- *args = (void*) ((char*)(raw++) + SIZEOF_ARG - 2);
- break;
-
-#if SIZEOF_ARG >= 4
- case FFI_TYPE_UINT32:
- case FFI_TYPE_SINT32:
- *args = (void*) ((char*)(raw++) + SIZEOF_ARG - 4);
- break;
-#endif
-
-#if !FFI_NO_STRUCTS
- case FFI_TYPE_STRUCT:
- *args = (raw++)->ptr;
- break;
-#endif
-
- case FFI_TYPE_POINTER:
- *args = (void*) &(raw++)->ptr;
- break;
-
- default:
- *args = raw;
- raw += ALIGN ((*tp)->size, SIZEOF_ARG) / SIZEOF_ARG;
- }
- }
-
-#else /* WORDS_BIGENDIAN */
-
-#if !PDP
-
- /* then assume little endian */
- for (i = 0; i < cif->nargs; i++, tp++, args++)
- {
-#if !FFI_NO_STRUCTS
- if ((*tp)->type == FFI_TYPE_STRUCT)
- {
- *args = (raw++)->ptr;
- }
- else
-#endif
- {
- *args = (void*) raw;
- raw += ALIGN ((*tp)->size, sizeof (void*)) / sizeof (void*);
- }
- }
-
-#else
-#error "pdp endian not supported"
-#endif /* ! PDP */
-
-#endif /* WORDS_BIGENDIAN */
-}
-
-void
-ffi_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw)
-{
- unsigned i;
- ffi_type **tp = cif->arg_types;
-
- for (i = 0; i < cif->nargs; i++, tp++, args++)
- {
- switch ((*tp)->type)
- {
- case FFI_TYPE_UINT8:
- (raw++)->uint = *(UINT8*) (*args);
- break;
-
- case FFI_TYPE_SINT8:
- (raw++)->sint = *(SINT8*) (*args);
- break;
-
- case FFI_TYPE_UINT16:
- (raw++)->uint = *(UINT16*) (*args);
- break;
-
- case FFI_TYPE_SINT16:
- (raw++)->sint = *(SINT16*) (*args);
- break;
-
-#if SIZEOF_ARG >= 4
- case FFI_TYPE_UINT32:
- (raw++)->uint = *(UINT32*) (*args);
- break;
-
- case FFI_TYPE_SINT32:
- (raw++)->sint = *(SINT32*) (*args);
- break;
-#endif
-
-#if !FFI_NO_STRUCTS
- case FFI_TYPE_STRUCT:
- (raw++)->ptr = *args;
- break;
-#endif
-
- case FFI_TYPE_POINTER:
- (raw++)->ptr = **(void***) args;
- break;
-
- default:
- memcpy ((void*) raw->data, (void*)*args, (*tp)->size);
- raw += ALIGN ((*tp)->size, SIZEOF_ARG) / SIZEOF_ARG;
- }
- }
-}
-
-#if !FFI_NATIVE_RAW_API
-
-
-/* This is a generic definition of ffi_raw_call, to be used if the
- * native system does not provide a machine-specific implementation.
- * Having this, allows code to be written for the raw API, without
- * the need for system-specific code to handle input in that format;
- * these following couple of functions will handle the translation forth
- * and back automatically. */
-
-void ffi_raw_call (/*@dependent@*/ ffi_cif *cif,
- void (*fn)(),
- /*@out@*/ void *rvalue,
- /*@dependent@*/ ffi_raw *raw)
-{
- void **avalue = (void**) alloca (cif->nargs * sizeof (void*));
- ffi_raw_to_ptrarray (cif, raw, avalue);
- ffi_call (cif, fn, rvalue, avalue);
-}
-
-#if FFI_CLOSURES /* base system provides closures */
-
-static void
-ffi_translate_args (ffi_cif *cif, void *rvalue,
- void **avalue, void *user_data)
-{
- ffi_raw *raw = (ffi_raw*)alloca (ffi_raw_size (cif));
- ffi_raw_closure *cl = (ffi_raw_closure*)user_data;
-
- ffi_ptrarray_to_raw (cif, avalue, raw);
- (*cl->fun) (cif, rvalue, raw, cl->user_data);
-}
-
-/* Again, here is the generic version of ffi_prep_raw_closure, which
- * will install an intermediate "hub" for translation of arguments from
- * the pointer-array format, to the raw format */
-
-ffi_status
-ffi_prep_raw_closure (ffi_raw_closure* cl,
- ffi_cif *cif,
- void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
- void *user_data)
-{
- ffi_status status;
-
- status = ffi_prep_closure ((ffi_closure*) cl,
- cif,
- &ffi_translate_args,
- (void*)cl);
- if (status == FFI_OK)
- {
- cl->fun = fun;
- cl->user_data = user_data;
- }
-
- return status;
-}
-
-#endif /* FFI_CLOSURES */
-#endif /* !FFI_NATIVE_RAW_API */
-#endif /* !FFI_NO_RAW_API */
+++ /dev/null
-/* -----------------------------------------------------------------------\r
- ffi.c - Copyright (c) 2000 Software AG\r
- \r
- S390 Foreign Function Interface\r
- \r
- Permission is hereby granted, free of charge, to any person obtaining\r
- a copy of this software and associated documentation files (the\r
- ``Software''), to deal in the Software without restriction, including\r
- without limitation the rights to use, copy, modify, merge, publish,\r
- distribute, sublicense, and/or sell copies of the Software, and to\r
- permit persons to whom the Software is furnished to do so, subject to\r
- the following conditions:\r
- \r
- The above copyright notice and this permission notice shall be included\r
- in all copies or substantial portions of the Software.\r
- \r
- THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS\r
- OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\r
- IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR\r
- OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\r
- ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\r
- OTHER DEALINGS IN THE SOFTWARE.\r
- ----------------------------------------------------------------------- */\r
-/*====================================================================*/\r
-/* Includes */\r
-/* -------- */\r
-/*====================================================================*/\r
- \r
-#include <ffi.h>\r
-#include <ffi_common.h>\r
- \r
-#include <stdlib.h>\r
-#include <stdio.h>\r
- \r
-/*====================== End of Includes =============================*/\r
- \r
-/*====================================================================*/\r
-/* Defines */\r
-/* ------- */\r
-/*====================================================================*/\r
- \r
-#define MAX_GPRARGS 5 /* Max. no. of GPR available */\r
-#define MAX_FPRARGS 2 /* Max. no. of FPR available */\r
- \r
-#define STR_GPR 1 /* Structure will fit in 1 or 2 GPR */\r
-#define STR_FPR 2 /* Structure will fit in a FPR */\r
-#define STR_STACK 3 /* Structure needs to go on stack */\r
- \r
-/*===================== End of Defines ===============================*/\r
- \r
-/*====================================================================*/\r
-/* Types */\r
-/* ----- */\r
-/*====================================================================*/\r
- \r
-typedef struct stackLayout\r
-{\r
- int *backChain;\r
- int *endOfStack;\r
- int glue[2];\r
- int scratch[2];\r
- int gprArgs[MAX_GPRARGS];\r
- int notUsed;\r
- union\r
- {\r
- float f;\r
- double d;\r
- } fprArgs[MAX_FPRARGS];\r
- int unUsed[8];\r
- int outArgs[100];\r
-} stackLayout;\r
- \r
-/*======================== End of Types ==============================*/\r
- \r
-/*====================================================================*/\r
-/* Prototypes */\r
-/* ---------- */\r
-/*====================================================================*/\r
- \r
-void ffi_prep_args(stackLayout *, extended_cif *);\r
-static int ffi_check_struct(ffi_type *, unsigned int *);\r
-static void ffi_insert_int(int, stackLayout *, int *, int *);\r
-static void ffi_insert_int64(long long, stackLayout *, int *, int *);\r
-static void ffi_insert_double(double, stackLayout *, int *, int *);\r
- \r
-/*====================== End of Prototypes ===========================*/\r
- \r
-/*====================================================================*/\r
-/* Externals */\r
-/* --------- */\r
-/*====================================================================*/\r
- \r
-extern void ffi_call_SYSV(void (*)(stackLayout *, extended_cif *),\r
- extended_cif *,\r
- unsigned, unsigned,\r
- unsigned *,\r
- void (*fn)());\r
- \r
-/*====================== End of Externals ============================*/\r
- \r
-/*====================================================================*/\r
-/* */\r
-/* Name - ffi_check_struct. */\r
-/* */\r
-/* Function - Determine if a structure can be passed within a */\r
-/* general or floating point register. */\r
-/* */\r
-/*====================================================================*/\r
- \r
-int\r
-ffi_check_struct(ffi_type *arg, unsigned int *strFlags)\r
-{\r
- ffi_type *element;\r
- int i_Element;\r
- \r
- for (i_Element = 0; arg->elements[i_Element]; i_Element++) {\r
- element = arg->elements[i_Element];\r
- switch (element->type) {\r
- case FFI_TYPE_DOUBLE :\r
- *strFlags |= STR_FPR;\r
- break;\r
- \r
- case FFI_TYPE_STRUCT :\r
- *strFlags |= ffi_check_struct(element, strFlags);\r
- break;\r
- \r
- default :\r
- *strFlags |= STR_GPR;\r
- }\r
- }\r
- return (*strFlags);\r
-}\r
- \r
-/*======================== End of Routine ============================*/\r
- \r
-/*====================================================================*/\r
-/* */\r
-/* Name - ffi_insert_int. */\r
-/* */\r
-/* Function - Insert an integer parameter in a register if there are */\r
-/* spares else on the stack. */\r
-/* */\r
-/*====================================================================*/\r
- \r
-void\r
-ffi_insert_int(int gprValue, stackLayout *stack,\r
- int *intArgC, int *outArgC)\r
-{\r
- if (*intArgC < MAX_GPRARGS) {\r
- stack->gprArgs[*intArgC] = gprValue;\r
- *intArgC += 1;\r
- }\r
- else {\r
- stack->outArgs[*outArgC++] = gprValue;\r
- *outArgC += 1;\r
- }\r
-}\r
- \r
-/*======================== End of Routine ============================*/\r
- \r
-/*====================================================================*/\r
-/* */\r
-/* Name - ffi_insert_int64. */\r
-/* */\r
-/* Function - Insert a long long parameter in registers if there are */\r
-/* spares else on the stack. */\r
-/* */\r
-/*====================================================================*/\r
- \r
-void\r
-ffi_insert_int64(long long llngValue, stackLayout *stack,\r
- int *intArgC, int *outArgC)\r
-{\r
- \r
- if (*intArgC < (MAX_GPRARGS-1)) {\r
- memcpy(&stack->gprArgs[*intArgC],\r
- &llngValue, sizeof(long long)); \r
- *intArgC += 2;\r
- }\r
- else {\r
- memcpy(&stack->outArgs[*outArgC],\r
- &llngValue, sizeof(long long));\r
- *outArgC += 2;\r
- }\r
- \r
-}\r
- \r
-/*======================== End of Routine ============================*/\r
- \r
-/*====================================================================*/\r
-/* */\r
-/* Name - ffi_insert_double. */\r
-/* */\r
-/* Function - Insert a double parameter in a FP register if there is */\r
-/* a spare else on the stack. */\r
-/* */\r
-/*====================================================================*/\r
- \r
-void\r
-ffi_insert_double(double dblValue, stackLayout *stack,\r
- int *fprArgC, int *outArgC)\r
-{\r
- \r
- if (*fprArgC < MAX_FPRARGS) {\r
- stack->fprArgs[*fprArgC].d = dblValue;\r
- *fprArgC += 1;\r
- }\r
- else {\r
- memcpy(&stack->outArgs[*outArgC],\r
- &dblValue,sizeof(double));\r
- *outArgC += 2;\r
- }\r
- \r
-}\r
- \r
-/*======================== End of Routine ============================*/\r
- \r
-/*====================================================================*/\r
-/* */\r
-/* Name - ffi_prep_args. */\r
-/* */\r
-/* Function - Prepare parameters for call to function. */\r
-/* */\r
-/* ffi_prep_args is called by the assembly routine once stack space */\r
-/* has been allocated for the function's arguments. */\r
-/* */\r
-/* The stack layout we want looks like this: */\r
-/* *------------------------------------------------------------* */\r
-/* | 0 | Back chain (a 0 here signifies end of back chain) | */\r
-/* +--------+---------------------------------------------------+ */\r
-/* | 4 | EOS (end of stack, not used on Linux for S390) | */\r
-/* +--------+---------------------------------------------------+ */\r
-/* | 8 | Glue used in other linkage formats | */\r
-/* +--------+---------------------------------------------------+ */\r
-/* | 12 | Glue used in other linkage formats | */\r
-/* +--------+---------------------------------------------------+ */\r
-/* | 16 | Scratch area | */\r
-/* +--------+---------------------------------------------------+ */\r
-/* | 20 | Scratch area | */\r
-/* +--------+---------------------------------------------------+ */\r
-/* | 24 | GPR parameter register 1 | */\r
-/* +--------+---------------------------------------------------+ */\r
-/* | 28 | GPR parameter register 2 | */\r
-/* +--------+---------------------------------------------------+ */\r
-/* | 32 | GPR parameter register 3 | */\r
-/* +--------+---------------------------------------------------+ */\r
-/* | 36 | GPR parameter register 4 | */\r
-/* +--------+---------------------------------------------------+ */\r
-/* | 40 | GPR parameter register 5 | */\r
-/* +--------+---------------------------------------------------+ */\r
-/* | 44 | Unused | */\r
-/* +--------+---------------------------------------------------+ */\r
-/* | 48 | FPR parameter register 1 | */\r
-/* +--------+---------------------------------------------------+ */\r
-/* | 56 | FPR parameter register 2 | */\r
-/* +--------+---------------------------------------------------+ */\r
-/* | 64 | Unused | */\r
-/* +--------+---------------------------------------------------+ */\r
-/* | 96 | Outgoing args (length x) | */\r
-/* +--------+---------------------------------------------------+ */\r
-/* | 96+x | Copy area for structures (length y) | */\r
-/* +--------+---------------------------------------------------+ */\r
-/* | 96+x+y | Possible stack alignment | */\r
-/* *------------------------------------------------------------* */\r
-/* */\r
-/*====================================================================*/\r
- \r
-void\r
-ffi_prep_args(stackLayout *stack, extended_cif *ecif)\r
-{\r
- const unsigned bytes = ecif->cif->bytes;\r
- const unsigned flags = ecif->cif->flags;\r
- \r
- /*----------------------------------------------------------*/\r
- /* Pointer to the copy area on stack for structures */\r
- /*----------------------------------------------------------*/\r
- char *copySpace = (char *) stack + bytes + sizeof(stackLayout);\r
- \r
- /*----------------------------------------------------------*/\r
- /* Count of general and floating point register usage */\r
- /*----------------------------------------------------------*/\r
- int intArgC = 0,\r
- fprArgC = 0,\r
- outArgC = 0;\r
- \r
- int i;\r
- ffi_type **ptr;\r
- void **p_argv;\r
- size_t structCopySize;\r
- unsigned gprValue, strFlags = 0;\r
- unsigned long long llngValue;\r
- double dblValue;\r
- \r
- /* Now for the arguments. */\r
- p_argv = ecif->avalue;\r
- \r
- /*----------------------------------------------------------------------*/\r
- /* If we returning a structure then we set the first parameter register */\r
- /* to the address of where we are returning this structure */\r
- /*----------------------------------------------------------------------*/\r
- if (flags == FFI_TYPE_STRUCT)\r
- stack->gprArgs[intArgC++] = (int) ecif->rvalue;\r
- \r
- for (ptr = ecif->cif->arg_types, i = ecif->cif->nargs;\r
- i > 0;\r
- i--, ptr++, p_argv++)\r
- {\r
- switch ((*ptr)->type) {\r
- \r
- case FFI_TYPE_FLOAT:\r
- if (fprArgC < MAX_FPRARGS)\r
- stack->fprArgs[fprArgC++].f = *(float *) *p_argv;\r
- else\r
- stack->outArgs[outArgC++] = *(int *) *p_argv;\r
- break;\r
- \r
- case FFI_TYPE_DOUBLE:\r
- dblValue = *(double *) *p_argv;\r
- ffi_insert_double(dblValue, stack, &fprArgC, &outArgC);\r
- break;\r
- \r
- case FFI_TYPE_UINT64:\r
- case FFI_TYPE_SINT64:\r
- llngValue = *(unsigned long long *) *p_argv;\r
- ffi_insert_int64(llngValue, stack, &intArgC, &outArgC);\r
- break;\r
- \r
- case FFI_TYPE_UINT8:\r
- gprValue = *(unsigned char *)*p_argv;\r
- ffi_insert_int(gprValue, stack, &intArgC, &outArgC);\r
- break;\r
- \r
- case FFI_TYPE_SINT8:\r
- gprValue = *(signed char *)*p_argv;\r
- ffi_insert_int(gprValue, stack, &intArgC, &outArgC);\r
- break;\r
- \r
- case FFI_TYPE_UINT16:\r
- gprValue = *(unsigned short *)*p_argv;\r
- ffi_insert_int(gprValue, stack, &intArgC, &outArgC);\r
- break;\r
- \r
- case FFI_TYPE_SINT16:\r
- gprValue = *(signed short *)*p_argv;\r
- ffi_insert_int(gprValue, stack, &intArgC, &outArgC);\r
- break;\r
- \r
- case FFI_TYPE_STRUCT:\r
- /*--------------------------------------------------*/\r
- /* If structure > 8 bytes then it goes on the stack */\r
- /*--------------------------------------------------*/\r
- if (((*ptr)->size > 8) ||\r
- ((*ptr)->size > 4 &&\r
- (*ptr)->size < 8))\r
- strFlags = STR_STACK;\r
- else\r
- strFlags = ffi_check_struct((ffi_type *) *ptr, &strFlags);\r
- \r
- switch (strFlags) {\r
- /*-------------------------------------------*/\r
- /* Structure that will fit in one or two GPR */\r
- /*-------------------------------------------*/\r
- case STR_GPR :\r
- if ((*ptr)->size <= 4) {\r
- gprValue = *(unsigned int *) *p_argv;\r
- gprValue = gprValue >> ((4 - (*ptr)->size) * 8);\r
- ffi_insert_int(gprValue, stack, &intArgC, &outArgC);\r
- }\r
- else {\r
- llngValue = *(unsigned long long *) *p_argv;\r
- ffi_insert_int64(llngValue, stack, &intArgC, &outArgC);\r
- }\r
- break;\r
- \r
- /*-------------------------------------------*/\r
- /* Structure that will fit in one FPR */\r
- /*-------------------------------------------*/\r
- case STR_FPR :\r
- dblValue = *(double *) *p_argv;\r
- ffi_insert_double(dblValue, stack, &fprArgC, &outArgC);\r
- break;\r
- \r
- /*-------------------------------------------*/\r
- /* Structure that must be copied to stack */\r
- /*-------------------------------------------*/\r
- default :\r
- structCopySize = (((*ptr)->size + 15) & ~0xF);\r
- copySpace -= structCopySize;\r
- memcpy(copySpace, (char *)*p_argv, (*ptr)->size);\r
- gprValue = (unsigned) copySpace;\r
- if (intArgC < MAX_GPRARGS)\r
- stack->gprArgs[intArgC++] = gprValue;\r
- else\r
- stack->outArgs[outArgC++] = gprValue;\r
- }\r
- break;\r
- \r
-#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE\r
- case FFI_TYPE_LONGDOUBLE:\r
- structCopySize = (((*ptr)->size + 15) & ~0xF);\r
- copySpace -= structCopySize;\r
- memcpy(copySpace, (char *)*p_argv, (*ptr)->size);\r
- gprValue = (unsigned) copySpace;\r
- if (intArgC < MAX_GPRARGS)\r
- stack->gprArgs[intArgC++] = gprValue;\r
- else\r
- stack->outArgs[outArgC++] = gprValue;\r
- break;\r
-#endif\r
- \r
- case FFI_TYPE_INT:\r
- case FFI_TYPE_UINT32:\r
- case FFI_TYPE_SINT32:\r
- case FFI_TYPE_POINTER:\r
- gprValue = *(unsigned *)*p_argv;\r
- if (intArgC < MAX_GPRARGS)\r
- stack->gprArgs[intArgC++] = gprValue;\r
- else\r
- stack->outArgs[outArgC++] = gprValue;\r
- break;\r
- \r
- }\r
- }\r
-}\r
- \r
-/*======================== End of Routine ============================*/\r
- \r
-/*====================================================================*/\r
-/* */\r
-/* Name - ffi_prep_cif_machdep. */\r
-/* */\r
-/* Function - Perform machine dependent CIF processing. */\r
-/* */\r
-/*====================================================================*/\r
- \r
-ffi_status\r
-ffi_prep_cif_machdep(ffi_cif *cif)\r
-{\r
- int i;\r
- ffi_type **ptr;\r
- unsigned bytes;\r
- int fpArgC = 0,\r
- intArgC = 0;\r
- unsigned flags = 0;\r
- unsigned structCopySize = 0;\r
- \r
- /*-----------------------------------------------------------------*/\r
- /* Extra space required in stack for overflow parameters. */\r
- /*-----------------------------------------------------------------*/\r
- bytes = 0;\r
- \r
- /*--------------------------------------------------------*/\r
- /* Return value handling. The rules are as follows: */\r
- /* - 32-bit (or less) integer values are returned in gpr2 */\r
- /* - Structures are returned as pointers in gpr2 */\r
- /* - 64-bit integer values are returned in gpr2 and 3 */\r
- /* - Single/double FP values are returned in fpr0 */\r
- /*--------------------------------------------------------*/\r
- flags = cif->rtype->type;\r
- \r
- /*------------------------------------------------------------------------*/\r
- /* The first MAX_GPRARGS words of integer arguments, and the */\r
- /* first MAX_FPRARGS floating point arguments, go in registers; the rest */\r
- /* goes on the stack. Structures and long doubles (if not equivalent */\r
- /* to double) are passed as a pointer to a copy of the structure. */\r
- /* Stuff on the stack needs to keep proper alignment. */\r
- /*------------------------------------------------------------------------*/\r
- for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)\r
- {\r
- switch ((*ptr)->type)\r
- {\r
- case FFI_TYPE_FLOAT:\r
- case FFI_TYPE_DOUBLE:\r
- fpArgC++;\r
- if (fpArgC > MAX_FPRARGS && intArgC%2 != 0)\r
- intArgC++;\r
- break;\r
- \r
- case FFI_TYPE_UINT64:\r
- case FFI_TYPE_SINT64:\r
- /*----------------------------------------------------*/\r
- /* 'long long' arguments are passed as two words, but */\r
- /* either both words must fit in registers or both go */\r
- /* on the stack. If they go on the stack, they must */\r
- /* be 8-byte-aligned. */\r
- /*----------------------------------------------------*/\r
- if ((intArgC == MAX_GPRARGS-1) ||\r
- (intArgC >= MAX_GPRARGS) &&\r
- (intArgC%2 != 0))\r
- intArgC++;\r
- intArgC += 2;\r
- break;\r
- \r
- case FFI_TYPE_STRUCT:\r
-#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE\r
- case FFI_TYPE_LONGDOUBLE:\r
-#endif\r
- /*----------------------------------------------------*/\r
- /* We must allocate space for a copy of these to */\r
- /* enforce pass-by-value. Pad the space up to a */\r
- /* multiple of 16 bytes (the maximum alignment */\r
- /* required for anything under the SYSV ABI). */\r
- /*----------------------------------------------------*/\r
- structCopySize += ((*ptr)->size + 15) & ~0xF;\r
- /*----------------------------------------------------*/\r
- /* Fall through (allocate space for the pointer). */\r
- /*----------------------------------------------------*/\r
- \r
- default:\r
- /*----------------------------------------------------*/\r
- /* Everything else is passed as a 4-byte word in a */\r
- /* GPR either the object itself or a pointer to it. */\r
- /*----------------------------------------------------*/\r
- intArgC++;\r
- break;\r
- }\r
- }\r
- \r
- /*-----------------------------------------------------------------*/\r
- /* Stack space. */\r
- /*-----------------------------------------------------------------*/\r
- if (intArgC > MAX_GPRARGS)\r
- bytes += (intArgC - MAX_GPRARGS) * sizeof(int);\r
- if (fpArgC > MAX_FPRARGS)\r
- bytes += (fpArgC - MAX_FPRARGS) * sizeof(double);\r
- \r
- /*-----------------------------------------------------------------*/\r
- /* The stack space allocated needs to be a multiple of 16 bytes. */\r
- /*-----------------------------------------------------------------*/\r
- bytes = (bytes + 15) & ~0xF;\r
- \r
- /*-----------------------------------------------------------------*/\r
- /* Add in the space for the copied structures. */\r
- /*-----------------------------------------------------------------*/\r
- bytes += structCopySize;\r
- \r
- cif->flags = flags;\r
- cif->bytes = bytes;\r
- \r
- return FFI_OK;\r
-}\r
- \r
-/*======================== End of Routine ============================*/\r
- \r
-/*====================================================================*/\r
-/* */\r
-/* Name - ffi_call. */\r
-/* */\r
-/* Function - Call the FFI routine. */\r
-/* */\r
-/*====================================================================*/\r
- \r
-void\r
-ffi_call(ffi_cif *cif,\r
- void (*fn)(),\r
- void *rvalue,\r
- void **avalue)\r
-{\r
- extended_cif ecif;\r
- \r
- ecif.cif = cif;\r
- ecif.avalue = avalue;\r
- \r
- /*-----------------------------------------------------------------*/\r
- /* If the return value is a struct and we don't have a return */\r
- /* value address then we need to make one */\r
- /*-----------------------------------------------------------------*/\r
- if ((rvalue == NULL) &&\r
- (cif->rtype->type == FFI_TYPE_STRUCT))\r
- ecif.rvalue = alloca(cif->rtype->size);\r
- else\r
- ecif.rvalue = rvalue;\r
- \r
- switch (cif->abi)\r
- {\r
- case FFI_SYSV:\r
- ffi_call_SYSV(ffi_prep_args,\r
- &ecif, cif->bytes,\r
- cif->flags, ecif.rvalue, fn);\r
- break;\r
- \r
- default:\r
- FFI_ASSERT(0);\r
- break;\r
- }\r
-}\r
- \r
-/*======================== End of Routine ============================*/\r
+++ /dev/null
-/* -----------------------------------------------------------------------
- sysv.S - Copyright (c) 2000 Software AG
-
- S390 Foreign Function Interface
-
- 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.
- ----------------------------------------------------------------------- */
-
-#define LIBFFI_ASM
-#include <ffi.h>
-#ifdef HAVE_MACHINE_ASM_H
-#include <machine/asm.h>
-#endif
-
-.text
-
- # r2: ffi_prep_args
- # r3: &ecif
- # r4: cif->bytes
- # r5: fig->flags
- # r6: ecif.rvalue
- # sp+0: fn
-
- # This assumes we are using gas.
- .globl ffi_call_SYSV
- .type ffi_call_SYSV,%function
-ffi_call_SYSV:
- # Save registers
- stm %r7,%r15,28(%r15)
- l %r7,96(%r15) # Get A(fn)
- lr %r0,%r15
- ahi %r15,-128 # Make room for my args
- st %r0,0(%r15) # Set backchain
- lr %r11,%r15 # Establish my stack register
- sr %r15,%r4 # Make room for fn args
- ahi %r15,-96 # Make room for new frame
- lr %r10,%r15 # Establish stack build area
- ahi %r15,-96 # Stack for next call
- lr %r1,%r7
- stm %r2,%r7,96(%r11) # Save args on my stack
-
-#------------------------------------------------------------------
-# move first 3 parameters in registers
-#------------------------------------------------------------------
- lr %r9,%r2 # r9: &ffi_prep_args
- lr %r2,%r10 # Parm 1: &stack Parm 2: &ecif
- basr %r14,%r9 # call ffi_prep_args
-
-#------------------------------------------------------------------
-# load first 5 parameter registers
-#------------------------------------------------------------------
- lm %r2,%r6,24(%r10)
-
-#------------------------------------------------------------------
-# load fp parameter registers
-#------------------------------------------------------------------
- ld %f0,48(%r10)
- ld %f2,56(%r10)
-
-#------------------------------------------------------------------
-# call function
-#------------------------------------------------------------------
- lr %r15,%r10 # Set new stack
- l %r9,116(%r11) # Get &fn
- basr %r14,%r9 # Call function
-
-#------------------------------------------------------------------
-# On return:
-# r2: Return value (r3: Return value + 4 for long long)
-#------------------------------------------------------------------
-
-#------------------------------------------------------------------
-# If the return value pointer is NULL, assume no return value.
-#------------------------------------------------------------------
- icm %r6,15,112(%r11)
- jz .Lepilogue
-
- l %r5,108(%r11) # Get return type
-#------------------------------------------------------------------
-# return INT
-#------------------------------------------------------------------
- chi %r5,FFI_TYPE_INT
- jne .Lchk64
-
- st %r2,0(%r6)
- j .Lepilogue
-
-.Lchk64:
-#------------------------------------------------------------------
-# return LONG LONG (signed/unsigned)
-#------------------------------------------------------------------
- chi %r5,FFI_TYPE_UINT64
- je .LdoLongLong
-
- chi %r5,FFI_TYPE_SINT64
- jne .LchkFloat
-
-.LdoLongLong:
- stm %r2,%r3,0(%r6)
- j .Lepilogue
-
-.LchkFloat:
-#------------------------------------------------------------------
-# return FLOAT
-#------------------------------------------------------------------
- chi %r5,FFI_TYPE_FLOAT
- jne .LchkDouble
-
- std %f0,0(%r6)
- j .Lepilogue
-
-.LchkDouble:
-#------------------------------------------------------------------
-# return DOUBLE or LONGDOUBLE
-#------------------------------------------------------------------
- chi %r5,FFI_TYPE_DOUBLE
- jne .LchkStruct
-
- std %f0,0(%r6)
- std %f2,8(%r6)
- j .Lepilogue
-
-.LchkStruct:
-#------------------------------------------------------------------
-# Structure - rvalue already set as sent as 1st parm to routine
-#------------------------------------------------------------------
- chi %r5,FFI_TYPE_STRUCT
- je .Lepilogue
-
-.Ldefault:
-#------------------------------------------------------------------
-# return a pointer
-#------------------------------------------------------------------
- st %r2,0(%r6)
- j .Lepilogue
-
-.Lepilogue:
- l %r15,0(%r11)
- l %r4,56(%r15)
- lm %r7,%r15,28(%r15)
- br %r4
-
-.ffi_call_SYSV_end:
- .size ffi_call_SYSV,.ffi_call_SYSV_end-ffi_call_SYSV
+++ /dev/null
-/* -----------------------------------------------------------------------
- ffi.c - Copyright (c) 1996 Cygnus Solutions
-
- Sparc Foreign Function Interface
-
- 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.
- ----------------------------------------------------------------------- */
-
-#include <ffi.h>
-#include <ffi_common.h>
-
-#include <stdlib.h>
-
-/* ffi_prep_args is called by the assembly routine once stack space
- has been allocated for the function's arguments */
-
-void ffi_prep_args_v8(char *stack, extended_cif *ecif)
-{
- int i;
- int tmp;
- int avn;
- void **p_argv;
- char *argp;
- ffi_type **p_arg;
-
- tmp = 0;
-
- /* Skip 16 words for the window save area */
- argp = stack + 16*sizeof(int);
-
- /* This should only really be done when we are returning a structure,
- however, it's faster just to do it all the time...
-
- if ( ecif->cif->rtype->type == FFI_TYPE_STRUCT ) */
- *(int *) argp = (long)ecif->rvalue;
-
- /* And 1 word for the structure return value. */
- argp += sizeof(int);
-
-#ifdef USING_PURIFY
- /* Purify will probably complain in our assembly routine, unless we
- zero out this memory. */
-
- ((int*)argp)[0] = 0;
- ((int*)argp)[1] = 0;
- ((int*)argp)[2] = 0;
- ((int*)argp)[3] = 0;
- ((int*)argp)[4] = 0;
- ((int*)argp)[5] = 0;
-#endif
-
- avn = ecif->cif->nargs;
- p_argv = ecif->avalue;
-
- for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
- i && avn;
- i--, p_arg++)
- {
- size_t z;
-
- if (avn)
- {
- avn--;
- if ((*p_arg)->type == FFI_TYPE_STRUCT
-#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
- || (*p_arg)->type == FFI_TYPE_LONGDOUBLE
-#endif
- )
- {
- *(unsigned int *) argp = (unsigned long)(* p_argv);
- z = sizeof(int);
- }
- else
- {
- z = (*p_arg)->size;
- if (z < sizeof(int))
- {
- z = sizeof(int);
- switch ((*p_arg)->type)
- {
- case FFI_TYPE_SINT8:
- *(signed int *) argp = *(SINT8 *)(* p_argv);
- break;
-
- case FFI_TYPE_UINT8:
- *(unsigned int *) argp = *(UINT8 *)(* p_argv);
- break;
-
- case FFI_TYPE_SINT16:
- *(signed int *) argp = *(SINT16 *)(* p_argv);
- break;
-
- case FFI_TYPE_UINT16:
- *(unsigned int *) argp = *(UINT16 *)(* p_argv);
- break;
-
- default:
- FFI_ASSERT(0);
- }
- }
- else
- {
- memcpy(argp, *p_argv, z);
- }
- }
- p_argv++;
- argp += z;
- }
- }
-
- return;
-}
-
-int ffi_prep_args_v9(char *stack, extended_cif *ecif)
-{
- int i, ret = 0;
- int tmp;
- void **p_argv;
- char *argp;
- ffi_type **p_arg;
-
- tmp = 0;
-
- /* Skip 16 words for the window save area */
- argp = stack + 16*sizeof(long long);
-
-#ifdef USING_PURIFY
- /* Purify will probably complain in our assembly routine, unless we
- zero out this memory. */
-
- ((long long*)argp)[0] = 0;
- ((long long*)argp)[1] = 0;
- ((long long*)argp)[2] = 0;
- ((long long*)argp)[3] = 0;
- ((long long*)argp)[4] = 0;
- ((long long*)argp)[5] = 0;
-#endif
-
- p_argv = ecif->avalue;
-
- if (ecif->cif->rtype->type == FFI_TYPE_STRUCT &&
- ecif->cif->rtype->size > 32)
- {
- *(unsigned long long *) argp = (unsigned long)ecif->rvalue;
- tmp = 1;
- }
-
- for (i = 0, p_arg = ecif->cif->arg_types; i < ecif->cif->nargs;
- i++, p_arg++)
- {
- size_t z;
-
- z = (*p_arg)->size;
- switch ((*p_arg)->type)
- {
- case FFI_TYPE_STRUCT:
- if (z > 16)
- {
- /* For structures larger than 16 bytes we pass reference. */
- *(unsigned long long *) argp = (unsigned long)* p_argv;
- argp += sizeof(long long);
- tmp++;
- p_argv++;
- continue;
- }
- /* FALLTHROUGH */
- case FFI_TYPE_FLOAT:
- case FFI_TYPE_DOUBLE:
-#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
- case FFI_TYPE_LONGDOUBLE:
-#endif
- ret = 1; /* We should promote into FP regs as well as integer. */
- break;
- }
- if (z < sizeof(long long))
- {
- switch ((*p_arg)->type)
- {
- case FFI_TYPE_SINT8:
- *(signed long long *) argp = *(SINT8 *)(* p_argv);
- break;
-
- case FFI_TYPE_UINT8:
- *(unsigned long long *) argp = *(UINT8 *)(* p_argv);
- break;
-
- case FFI_TYPE_SINT16:
- *(signed long long *) argp = *(SINT16 *)(* p_argv);
- break;
-
- case FFI_TYPE_UINT16:
- *(unsigned long long *) argp = *(UINT16 *)(* p_argv);
- break;
-
- case FFI_TYPE_SINT32:
- *(signed long long *) argp = *(SINT32 *)(* p_argv);
- break;
-
- case FFI_TYPE_UINT32:
- *(unsigned long long *) argp = *(UINT32 *)(* p_argv);
- break;
-
- case FFI_TYPE_FLOAT:
- *(float *) (argp + 4) = *(FLOAT32 *)(* p_argv); /* Right justify */
- break;
-
- case FFI_TYPE_STRUCT:
- memcpy(argp, *p_argv, z);
- break;
-
- default:
- FFI_ASSERT(0);
- }
- z = sizeof(long long);
- tmp++;
- }
- else if (z == sizeof(long long))
- {
- memcpy(argp, *p_argv, z);
- z = sizeof(long long);
- tmp++;
- }
- else
- {
- if ((tmp & 1) && (*p_arg)->alignment > 8)
- {
- tmp++;
- argp += sizeof(long long);
- }
- memcpy(argp, *p_argv, z);
- z = 2 * sizeof(long long);
- tmp += 2;
- }
- p_argv++;
- argp += z;
- }
-
- return ret;
-}
-
-/* Perform machine dependent cif processing */
-ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
-{
- int wordsize;
-
- if (cif->abi != FFI_V9)
- {
- wordsize = 4;
-
- /* If we are returning a struct, this will already have been added.
- Otherwise we need to add it because it's always got to be there! */
-
- if (cif->rtype->type != FFI_TYPE_STRUCT)
- cif->bytes += wordsize;
-
- /* sparc call frames require that space is allocated for 6 args,
- even if they aren't used. Make that space if necessary. */
-
- if (cif->bytes < 4*6+4)
- cif->bytes = 4*6+4;
- }
- else
- {
- wordsize = 8;
-
- /* sparc call frames require that space is allocated for 6 args,
- even if they aren't used. Make that space if necessary. */
-
- if (cif->bytes < 8*6)
- cif->bytes = 8*6;
- }
-
- /* Adjust cif->bytes. to include 16 words for the window save area,
- and maybe the struct/union return pointer area, */
-
- cif->bytes += 16 * wordsize;
-
- /* The stack must be 2 word aligned, so round bytes up
- appropriately. */
-
- cif->bytes = ALIGN(cif->bytes, 2 * wordsize);
-
- /* Set the return type flag */
- switch (cif->rtype->type)
- {
- case FFI_TYPE_VOID:
- case FFI_TYPE_FLOAT:
- case FFI_TYPE_DOUBLE:
-#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
- case FFI_TYPE_LONGDOUBLE:
-#endif
- cif->flags = cif->rtype->type;
- break;
-
- case FFI_TYPE_STRUCT:
- if (cif->abi == FFI_V9 && cif->rtype->size > 32)
- cif->flags = FFI_TYPE_VOID;
- else
- cif->flags = FFI_TYPE_STRUCT;
- break;
-
- case FFI_TYPE_SINT64:
- case FFI_TYPE_UINT64:
- if (cif->abi != FFI_V9)
- {
- cif->flags = FFI_TYPE_SINT64;
- break;
- }
- /* FALLTHROUGH */
- default:
- cif->flags = FFI_TYPE_INT;
- break;
- }
- return FFI_OK;
-}
-
-int ffi_V9_return_struct(ffi_type *arg, int off, char *ret, char *intg, char *flt)
-{
- ffi_type **ptr = &arg->elements[0];
-
- while (*ptr != NULL)
- {
- if (off & ((*ptr)->alignment - 1))
- off = ALIGN(off, (*ptr)->alignment);
-
- switch ((*ptr)->type)
- {
- case FFI_TYPE_STRUCT:
- off = ffi_V9_return_struct(*ptr, off, ret, intg, flt);
- break;
- case FFI_TYPE_FLOAT:
- case FFI_TYPE_DOUBLE:
-#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
- case FFI_TYPE_LONGDOUBLE:
-#endif
- memcpy(ret + off, flt + off, (*ptr)->size);
- off += (*ptr)->size;
- break;
- default:
- memcpy(ret + off, intg + off, (*ptr)->size);
- off += (*ptr)->size;
- break;
- }
- ptr++;
- }
- return off;
-}
-
-extern int ffi_call_V8(void *, extended_cif *, unsigned,
- unsigned, unsigned *, void (*fn)());
-extern int ffi_call_V9(void *, extended_cif *, unsigned,
- unsigned, unsigned *, void (*fn)());
-
-void ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
-{
- extended_cif ecif;
- void *rval = rvalue;
-
- 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 */
-
- ecif.rvalue = rvalue;
- if (cif->rtype->type == FFI_TYPE_STRUCT)
- {
- if (cif->rtype->size <= 32)
- rval = alloca(64);
- else
- {
- rval = NULL;
- if (rvalue == NULL)
- ecif.rvalue = alloca(cif->rtype->size);
- }
- }
-
- switch (cif->abi)
- {
- case FFI_V8:
-#ifdef SPARC64
- /* We don't yet support calling 32bit code from 64bit */
- FFI_ASSERT(0);
-#else
- ffi_call_V8(ffi_prep_args_v8, &ecif, cif->bytes,
- cif->flags, rvalue, fn);
-#endif
- break;
- case FFI_V9:
-#ifdef SPARC64
- ffi_call_V9(ffi_prep_args_v9, &ecif, cif->bytes,
- cif->flags, rval, fn);
- if (rvalue && rval && cif->rtype->type == FFI_TYPE_STRUCT)
- ffi_V9_return_struct(cif->rtype, 0, (char *)rvalue, (char *)rval, ((char *)rval)+32);
-#else
- /* And vice versa */
- FFI_ASSERT(0);
-#endif
- break;
- default:
- FFI_ASSERT(0);
- break;
- }
-
-}
+++ /dev/null
-/* -----------------------------------------------------------------------
- v8.S - Copyright (c) 1996, 1997 Cygnus Solutions
-
- Sparc Foreign Function Interface
-
- 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.
- ----------------------------------------------------------------------- */
-
-#define LIBFFI_ASM
-#include <ffi.h>
-
-#define STACKFRAME 96 /* Minimum stack framesize for SPARC */
-#define ARGS (64+4) /* Offset of register area in frame */
-
-.text
- .align 8
-.globl ffi_call_V8
-.globl _ffi_call_V8
-
-ffi_call_V8:
-_ffi_call_V8:
- save %sp, -STACKFRAME, %sp
-
- sub %sp, %i2, %sp ! alloca() space in stack for frame to set up
- add %sp, STACKFRAME, %l0 ! %l0 has start of
- ! frame to set up
-
- mov %l0, %o0 ! call routine to set up frame
- call %i0
- mov %i1, %o1 ! (delay)
-
- ld [%l0+ARGS], %o0 ! call foreign function
- ld [%l0+ARGS+4], %o1
- ld [%l0+ARGS+8], %o2
- ld [%l0+ARGS+12], %o3
- ld [%l0+ARGS+16], %o4
- ld [%l0+ARGS+20], %o5
- call %i5
- mov %l0, %sp ! (delay) switch to frame
- nop ! STRUCT returning functions skip 12 instead of 8 bytes
-
- ! If the return value pointer is NULL, assume no return value.
- tst %i4
- bz done
- nop
-
- cmp %i3, FFI_TYPE_INT
- be,a done
- st %o0, [%i4] ! (delay)
-
- cmp %i3, FFI_TYPE_FLOAT
- be,a done
- st %f0, [%i4+0] ! (delay)
-
- cmp %i3, FFI_TYPE_SINT64
- be longlong
-
- cmp %i3, FFI_TYPE_DOUBLE
- bne done
- nop
- st %f0, [%i4+0]
- st %f1, [%i4+4]
-
-done:
- ret
- restore
-
-longlong:
- st %o0, [%i4+0]
- st %o1, [%i4+4]
- ret
- restore
-
-.ffi_call_V8_end:
- .size ffi_call_V8,.ffi_call_V8_end-ffi_call_V8
-
+++ /dev/null
-/* -----------------------------------------------------------------------
- v9.S - Copyright (c) 2000 Cygnus Solutions
-
- Sparc 64bit Foreign Function Interface
-
- 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.
- ----------------------------------------------------------------------- */
-
-#define LIBFFI_ASM
-#include <ffi.h>
-
-#ifdef SPARC64
-/* Only compile this in for 64bit builds, because otherwise the object file
- will have inproper architecture due to used instructions. */
-
-#define STACKFRAME 128 /* Minimum stack framesize for SPARC */
-#define STACK_BIAS 2047
-#define ARGS (128) /* Offset of register area in frame */
-
-.text
- .align 8
-.globl ffi_call_V9
-.globl _ffi_call_V9
-
-ffi_call_V9:
-_ffi_call_V9:
- save %sp, -STACKFRAME, %sp
-
- sub %sp, %i2, %sp ! alloca() space in stack for frame to set up
- add %sp, STACKFRAME+STACK_BIAS, %l0 ! %l0 has start of
- ! frame to set up
-
- mov %l0, %o0 ! call routine to set up frame
- call %i0
- mov %i1, %o1 ! (delay)
- brz,pt %o0, 1f
- ldx [%l0+ARGS], %o0 ! call foreign function
-
- ldd [%l0+ARGS], %f0
- ldd [%l0+ARGS+8], %f2
- ldd [%l0+ARGS+16], %f4
- ldd [%l0+ARGS+24], %f6
- ldd [%l0+ARGS+32], %f8
- ldd [%l0+ARGS+40], %f10
- ldd [%l0+ARGS+48], %f12
- ldd [%l0+ARGS+56], %f14
- ldd [%l0+ARGS+64], %f16
- ldd [%l0+ARGS+72], %f18
- ldd [%l0+ARGS+80], %f20
- ldd [%l0+ARGS+88], %f22
- ldd [%l0+ARGS+96], %f24
- ldd [%l0+ARGS+104], %f26
- ldd [%l0+ARGS+112], %f28
- ldd [%l0+ARGS+120], %f30
-
-1: ldx [%l0+ARGS+8], %o1
- ldx [%l0+ARGS+16], %o2
- ldx [%l0+ARGS+24], %o3
- ldx [%l0+ARGS+32], %o4
- ldx [%l0+ARGS+40], %o5
- call %i5
- sub %l0, STACK_BIAS, %sp ! (delay) switch to frame
-
- ! If the return value pointer is NULL, assume no return value.
- brz,pn %i4, done
- nop
-
- cmp %i3, FFI_TYPE_INT
- be,a,pt %icc, done
- stx %o0, [%i4] ! (delay)
-
- cmp %i3, FFI_TYPE_FLOAT
- be,a,pn %icc, done
- st %f0, [%i4+0] ! (delay)
-
- cmp %i3, FFI_TYPE_DOUBLE
- be,a,pn %icc, done
- std %f0, [%i4+0] ! (delay)
-
- cmp %i3, FFI_TYPE_STRUCT
- be,pn %icc, dostruct
-
- cmp %i3, FFI_TYPE_LONGDOUBLE
- bne,pt %icc, done
- nop
- std %f0, [%i4+0]
- std %f2, [%i4+8]
-
-done: ret
- restore
-
-dostruct:
- /* This will not work correctly for unions. */
- stx %o0, [%i4+0]
- stx %o1, [%i4+8]
- stx %o2, [%i4+16]
- stx %o3, [%i4+24]
- std %f0, [%i4+32]
- std %f2, [%i4+40]
- std %f4, [%i4+48]
- std %f6, [%i4+56]
- ret
- restore
-
-.ffi_call_V9_end:
- .size ffi_call_V9,.ffi_call_V9_end-ffi_call_V9
-
-#endif
+++ /dev/null
-/* -----------------------------------------------------------------------
- types.c - Copyright (c) 1996, 1998 Cygnus Solutions
-
- Predefined ffi_types needed by libffi.
-
- 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 RED HAT 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>
-
-/* Type definitions */
-
-#define FFI_INTEGRAL_TYPEDEF(n, s, a, t) ffi_type ffi_type_##n = { s, a, t, NULL }
-#define FFI_AGGREGATE_TYPEDEF(n, e) ffi_type ffi_type_##n = { 0, 0, FFI_TYPE_STRUCT, e }
-
-/* Size and alignment are fake here. They must not be 0. */
-FFI_INTEGRAL_TYPEDEF(void, 1, 1, FFI_TYPE_VOID);
-
-FFI_INTEGRAL_TYPEDEF(uint8, 1, 1, FFI_TYPE_UINT8);
-FFI_INTEGRAL_TYPEDEF(sint8, 1, 1, FFI_TYPE_SINT8);
-FFI_INTEGRAL_TYPEDEF(uint16, 2, 2, FFI_TYPE_UINT16);
-FFI_INTEGRAL_TYPEDEF(sint16, 2, 2, FFI_TYPE_SINT16);
-FFI_INTEGRAL_TYPEDEF(uint32, 4, 4, FFI_TYPE_UINT32);
-FFI_INTEGRAL_TYPEDEF(sint32, 4, 4, FFI_TYPE_SINT32);
-FFI_INTEGRAL_TYPEDEF(float, 4, 4, FFI_TYPE_FLOAT);
-
-#if defined ALPHA || defined SPARC64
-
-FFI_INTEGRAL_TYPEDEF(pointer, 8, 8, FFI_TYPE_POINTER);
-
-#else
-
-FFI_INTEGRAL_TYPEDEF(pointer, 4, 4, FFI_TYPE_POINTER);
-
-#endif
-
-#ifdef X86
-
-FFI_INTEGRAL_TYPEDEF(uint64, 8, 4, FFI_TYPE_UINT64);
-FFI_INTEGRAL_TYPEDEF(sint64, 8, 4, FFI_TYPE_SINT64);
-
-#elif defined X86_WIN32
-
-FFI_INTEGRAL_TYPEDEF(uint64, 8, 4, FFI_TYPE_UINT64);
-FFI_INTEGRAL_TYPEDEF(sint64, 8, 4, FFI_TYPE_SINT64);
-
-#elif defined ARM
-
-FFI_INTEGRAL_TYPEDEF(uint64, 8, 4, FFI_TYPE_UINT64);
-FFI_INTEGRAL_TYPEDEF(sint64, 8, 4, FFI_TYPE_SINT64);
-
-#elif defined M68K
-
-FFI_INTEGRAL_TYPEDEF(uint64, 8, 4, FFI_TYPE_UINT64);
-FFI_INTEGRAL_TYPEDEF(sint64, 8, 4, FFI_TYPE_SINT64);
-
-#else
-
-FFI_INTEGRAL_TYPEDEF(uint64, 8, 8, FFI_TYPE_UINT64);
-FFI_INTEGRAL_TYPEDEF(sint64, 8, 8, FFI_TYPE_SINT64);
-
-#endif
-
-
-#ifdef X86
-
-FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE);
-FFI_INTEGRAL_TYPEDEF(longdouble, 12, 4, FFI_TYPE_LONGDOUBLE);
-
-#elif defined X86_WIN32
-
-FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE);
-FFI_INTEGRAL_TYPEDEF(longdouble, 12, 4, FFI_TYPE_LONGDOUBLE);
-
-#elif defined ARM
-
-FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE);
-FFI_INTEGRAL_TYPEDEF(longdouble, 8, 4, FFI_TYPE_LONGDOUBLE);
-
-#elif defined M68K
-
-FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE);
-FFI_INTEGRAL_TYPEDEF(longdouble, 12, 4, FFI_TYPE_LONGDOUBLE);
-
-#elif defined SPARC
-
-FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE);
-
-#ifdef SPARC64
-
-FFI_INTEGRAL_TYPEDEF(longdouble, 16, 16, FFI_TYPE_LONGDOUBLE);
-
-#else
-
-FFI_INTEGRAL_TYPEDEF(longdouble, 16, 8, FFI_TYPE_LONGDOUBLE);
-
-#endif
-
-#else
-
-FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE);
-FFI_INTEGRAL_TYPEDEF(longdouble, 8, 8, FFI_TYPE_LONGDOUBLE);
-
-#endif
-
+++ /dev/null
-/* -----------------------------------------------------------------------
- ffi.c - Copyright (c) 1996, 1998, 1999 Cygnus Solutions
-
- x86 Foreign Function Interface
-
- 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.
- ----------------------------------------------------------------------- */
-
-#include <ffi.h>
-#include <ffi_common.h>
-
-#include <stdlib.h>
-
-/* ffi_prep_args is called by the assembly routine once stack space
- has been allocated for the function's arguments */
-
-/*@-exportheader@*/
-void ffi_prep_args(char *stack, extended_cif *ecif)
-/*@=exportheader@*/
-{
- register unsigned int i;
- register int tmp;
- register unsigned int avn;
- register void **p_argv;
- register char *argp;
- register ffi_type **p_arg;
-
- tmp = 0;
- argp = stack;
-
- if ( ecif->cif->rtype->type == FFI_TYPE_STRUCT ) {
- *(void **) argp = ecif->rvalue;
- argp += 4;
- }
-
- avn = ecif->cif->nargs;
- p_argv = ecif->avalue;
-
- for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
- (i != 0) && (avn != 0);
- i--, p_arg++)
- {
- size_t z;
-
- /* Align if necessary */
- if (((*p_arg)->alignment - 1) & (unsigned) argp) {
- argp = (char *) ALIGN(argp, (*p_arg)->alignment);
- }
-
- if (avn != 0)
- {
- avn--;
- z = (*p_arg)->size;
- if (z < sizeof(int))
- {
- z = sizeof(int);
- switch ((*p_arg)->type)
- {
- case FFI_TYPE_SINT8:
- *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
- break;
-
- case FFI_TYPE_UINT8:
- *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
- break;
-
- case FFI_TYPE_SINT16:
- *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
- break;
-
- case FFI_TYPE_UINT16:
- *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
- break;
-
- case FFI_TYPE_SINT32:
- *(signed int *) argp = (signed int)*(SINT32 *)(* p_argv);
- break;
-
- case FFI_TYPE_UINT32:
- *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
- break;
-
- case FFI_TYPE_STRUCT:
- *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
- break;
-
- default:
- FFI_ASSERT(0);
- }
- }
- else
- {
- memcpy(argp, *p_argv, z);
- }
- p_argv++;
- argp += z;
- }
- }
-
- return;
-}
-
-/* Perform machine dependent cif processing */
-ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
-{
- /* Set the return type flag */
- switch (cif->rtype->type)
- {
- case FFI_TYPE_VOID:
- case FFI_TYPE_STRUCT:
- case FFI_TYPE_SINT64:
- case FFI_TYPE_FLOAT:
- case FFI_TYPE_DOUBLE:
- case FFI_TYPE_LONGDOUBLE:
- cif->flags = (unsigned) cif->rtype->type;
- break;
-
- case FFI_TYPE_UINT64:
- cif->flags = FFI_TYPE_SINT64;
- break;
-
- default:
- cif->flags = FFI_TYPE_INT;
- break;
- }
-
- return FFI_OK;
-}
-
-/*@-declundef@*/
-/*@-exportheader@*/
-extern void ffi_call_SYSV(void (*)(char *, extended_cif *),
- /*@out@*/ extended_cif *,
- unsigned, unsigned,
- /*@out@*/ unsigned *,
- 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)
- {
- case FFI_SYSV:
- /*@-usedef@*/
- ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes,
- cif->flags, ecif.rvalue, fn);
- /*@=usedef@*/
- break;
- default:
- FFI_ASSERT(0);
- break;
- }
-}
-
-
-/** private members **/
-
-static void ffi_prep_incoming_args_SYSV (char *stack, void **ret,
- void** args, ffi_cif* cif);
-static void ffi_closure_SYSV ();
-static void ffi_closure_raw_SYSV ();
-
-/* This function is jumped to by the trampoline, on entry, %ecx (a
- * caller-save register) holds the address of the closure.
- * Clearly, this requires __GNUC__, so perhaps we should translate this
- * into an assembly file if this is to be distributed with ffi.
- */
-
-static void
-ffi_closure_SYSV ()
-{
- // this is our return value storage
- long double res;
-
- // our various things...
- void *args;
- ffi_cif *cif;
- void **arg_area;
- ffi_closure *closure;
- unsigned short rtype;
- void *resp = (void*)&res;
-
- /* grab the trampoline context pointer */
- asm ("movl %%ecx,%0" : "=r" (closure));
-
- cif = closure->cif;
- arg_area = (void**) alloca (cif->nargs * sizeof (void*));
- asm ("leal 8(%%ebp),%0" : "=q" (args));
-
- /* this call will initialize ARG_AREA, such that each
- * element in that array points to the corresponding
- * value on the stack; and if the function returns
- * a structure, it will re-set RESP to point to the
- * structure return address. */
-
- ffi_prep_incoming_args_SYSV(args, (void**)&resp, arg_area, cif);
-
- (closure->fun) (cif, resp, arg_area, closure->user_data);
-
- rtype = cif->flags;
-
- /* now, do a generic return based on the value of rtype */
- if (rtype == FFI_TYPE_INT)
- {
- asm ("movl (%0),%%eax" : : "r" (resp) : "eax");
- }
- else if (rtype == FFI_TYPE_FLOAT)
- {
- asm ("flds (%0)" : : "r" (resp) : "st" );
- }
- else if (rtype == FFI_TYPE_DOUBLE)
- {
- asm ("fldl (%0)" : : "r" (resp) : "st", "st(1)" );
- }
- else if (rtype == FFI_TYPE_LONGDOUBLE)
- {
- asm ("fldt (%0)" : : "r" (resp) : "st", "st(1)" );
- }
- else if (rtype == FFI_TYPE_SINT64)
- {
- asm ("movl 0(%0),%%eax;"
- "movl 4(%0),%%edx"
- : : "r"(resp)
- : "eax", "edx");
- }
-}
-
-/*@-exportheader@*/
-static void
-ffi_prep_incoming_args_SYSV(char *stack, void **rvalue,
- void **avalue, ffi_cif *cif)
-/*@=exportheader@*/
-{
- register unsigned int i;
- register int tmp;
- register unsigned int avn;
- register void **p_argv;
- register char *argp;
- register ffi_type **p_arg;
-
- tmp = 0;
- argp = stack;
-
- if ( cif->rtype->type == FFI_TYPE_STRUCT ) {
- *rvalue = *(void **) argp;
- argp += 4;
- }
-
- avn = cif->nargs;
- p_argv = avalue;
-
- for (i = cif->nargs, p_arg = cif->arg_types;
- (i != 0) && (avn != 0);
- i--, p_arg++)
- {
- size_t z;
-
- /* Align if necessary */
- if (((*p_arg)->alignment - 1) & (unsigned) argp) {
- argp = (char *) ALIGN(argp, (*p_arg)->alignment);
- }
-
- if (avn != 0)
- {
- avn--;
- z = (*p_arg)->size;
-
- /* because we're little endian, this is
- what it turns into. */
-
- *p_argv = (void*) argp;
-
- p_argv++;
- argp += z;
- }
- }
-
- return;
-}
-
-/* How to make a trampoline. Derived from gcc/config/i386/i386.c. */
-
-#define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX) \
-({ unsigned char *__tramp = (unsigned char*)(TRAMP); \
- unsigned int __fun = (unsigned int)(FUN); \
- unsigned int __ctx = (unsigned int)(CTX); \
- unsigned int __dis = __fun - ((unsigned int) __tramp + 10); \
- *(unsigned char*) &__tramp[0] = 0xb9; \
- *(unsigned int*) &__tramp[1] = __ctx; \
- *(unsigned char*) &__tramp[5] = 0xe9; \
- *(unsigned int*) &__tramp[6] = __dis; \
- })
-
-
-/* the cif must already be prep'ed */
-
-ffi_status
-ffi_prep_closure (ffi_closure* closure,
- ffi_cif* cif,
- void (*fun)(ffi_cif*,void*,void**,void*),
- void *user_data)
-{
- FFI_ASSERT (cif->abi == FFI_SYSV);
-
- FFI_INIT_TRAMPOLINE (&closure->tramp[0], \
- &ffi_closure_SYSV, \
- (void*)closure);
-
- closure->cif = cif;
- closure->user_data = user_data;
- closure->fun = fun;
-
- return FFI_OK;
-}
-
-/* ------- Native raw API support -------------------------------- */
-
-#if !FFI_NO_RAW_API
-
-static void
-ffi_closure_raw_SYSV ()
-{
- // this is our return value storage
- long double res;
-
- // our various things...
- void *args;
- ffi_raw *raw_args;
- ffi_cif *cif;
- ffi_raw_closure *closure;
- unsigned short rtype;
- void *resp = (void*)&res;
-
- /* grab the trampoline context pointer */
- asm ("movl %%ecx,%0" : "=r" (closure));
-
- /* take the argument pointer */
- asm ("leal 8(%%ebp),%0" : "=q" (args));
-
- /* get the cif */
- cif = closure->cif;
-
- /* the SYSV/X86 abi matches the RAW API exactly, well.. almost */
- raw_args = (ffi_raw*) args;
-
- (closure->fun) (cif, resp, raw_args, closure->user_data);
-
- rtype = cif->flags;
-
- /* now, do a generic return based on the value of rtype */
- if (rtype == FFI_TYPE_INT)
- {
- asm ("movl (%0),%%eax" : : "r" (resp) : "eax");
- }
- else if (rtype == FFI_TYPE_FLOAT)
- {
- asm ("flds (%0)" : : "r" (resp) : "st" );
- }
- else if (rtype == FFI_TYPE_DOUBLE)
- {
- asm ("fldl (%0)" : : "r" (resp) : "st", "st(1)" );
- }
- else if (rtype == FFI_TYPE_LONGDOUBLE)
- {
- asm ("fldt (%0)" : : "r" (resp) : "st", "st(1)" );
- }
- else if (rtype == FFI_TYPE_SINT64)
- {
- asm ("movl 0(%0),%%eax; movl 4(%0),%%edx"
- : : "r"(resp)
- : "eax", "edx");
- }
-}
-
-
-
-
-ffi_status
-ffi_prep_raw_closure (ffi_raw_closure* closure,
- ffi_cif* cif,
- void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
- void *user_data)
-{
- int i;
-
- FFI_ASSERT (cif->abi == FFI_SYSV);
-
- // we currently don't support certain kinds of arguments for raw
- // closures. This should be implemented by a seperate assembly language
- // routine, since it would require argument processing, something we
- // don't do now for performance.
-
- for (i = cif->nargs-1; i >= 0; i--)
- {
- FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_STRUCT);
- FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_LONGDOUBLE);
- }
-
-
- FFI_INIT_TRAMPOLINE (&closure->tramp[0], &ffi_closure_raw_SYSV,
- (void*)closure);
-
- closure->cif = cif;
- closure->user_data = user_data;
- closure->fun = fun;
-
- return FFI_OK;
-}
-
-static void
-ffi_prep_args_raw(char *stack, extended_cif *ecif)
-{
- memcpy (stack, ecif->avalue, ecif->cif->bytes);
-}
-
-/* we borrow this routine from libffi (it must be changed, though, to
- * actually call the function passed in the first argument. as of
- * libffi-1.20, this is not the case.)
- */
-
-extern void
-ffi_call_SYSV(void (*)(char *, extended_cif *),
- /*@out@*/ extended_cif *,
- unsigned, unsigned,
- /*@out@*/ unsigned *,
- void (*fn)());
-
-void
-ffi_raw_call(/*@dependent@*/ ffi_cif *cif,
- void (*fn)(),
- /*@out@*/ void *rvalue,
- /*@dependent@*/ ffi_raw *fake_avalue)
-{
- extended_cif ecif;
- void **avalue = (void **)fake_avalue;
-
- 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_SYSV:
- /*@-usedef@*/
- ffi_call_SYSV(ffi_prep_args_raw, &ecif, cif->bytes,
- cif->flags, ecif.rvalue, fn);
- /*@=usedef@*/
- break;
- default:
- FFI_ASSERT(0);
- break;
- }
-}
-
-#endif
+++ /dev/null
-/* -----------------------------------------------------------------------
- sysv.S - Copyright (c) 1996, 1998 Cygnus Solutions
-
- X86 Foreign Function Interface
-
- 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.
- ----------------------------------------------------------------------- */
-
-#define LIBFFI_ASM
-#include <ffi.h>
-
-.text
-
-.globl ffi_prep_args
-
- # This assumes we are using gas.
- .balign 16
-.globl ffi_call_SYSV
- .type ffi_call_SYSV,@function
-
-ffi_call_SYSV:
-.LFB1:
- pushl %ebp
-.LCFI0:
- movl %esp,%ebp
-.LCFI1:
- # Make room for all of the new args.
- movl 16(%ebp),%ecx
- subl %ecx,%esp
-
- movl %esp,%eax
-
- # Place all of the ffi_prep_args in position
- pushl 12(%ebp)
- pushl %eax
- call *8(%ebp)
-
- # Return stack to previous state and call the function
- addl $8,%esp
-
- call *28(%ebp)
-
- # Remove the space we pushed for the args
- movl 16(%ebp),%ecx
- addl %ecx,%esp
-
- # Load %ecx with the return type code
- movl 20(%ebp),%ecx
-
- # If the return value pointer is NULL, assume no return value.
- cmpl $0,24(%ebp)
- jne retint
-
- # Even if there is no space for the return value, we are
- # obliged to handle floating-point values.
- cmpl $FFI_TYPE_FLOAT,%ecx
- jne noretval
- fstp %st(0)
-
- jmp epilogue
-
-retint:
- cmpl $FFI_TYPE_INT,%ecx
- jne retfloat
- # Load %ecx with the pointer to storage for the return value
- movl 24(%ebp),%ecx
- movl %eax,0(%ecx)
- jmp epilogue
-
-retfloat:
- cmpl $FFI_TYPE_FLOAT,%ecx
- jne retdouble
- # Load %ecx with the pointer to storage for the return value
- movl 24(%ebp),%ecx
- fstps (%ecx)
- jmp epilogue
-
-retdouble:
- cmpl $FFI_TYPE_DOUBLE,%ecx
- jne retlongdouble
- # Load %ecx with the pointer to storage for the return value
- movl 24(%ebp),%ecx
- fstpl (%ecx)
- jmp epilogue
-
-retlongdouble:
- cmpl $FFI_TYPE_LONGDOUBLE,%ecx
- jne retint64
- # Load %ecx with the pointer to storage for the return value
- movl 24(%ebp),%ecx
- fstpt (%ecx)
- jmp epilogue
-
-retint64:
- cmpl $FFI_TYPE_SINT64,%ecx
- jne retstruct
- # Load %ecx with the pointer to storage for the return value
- movl 24(%ebp),%ecx
- movl %eax,0(%ecx)
- movl %edx,4(%ecx)
-
-retstruct:
- # Nothing to do!
-
-noretval:
-epilogue:
- movl %ebp,%esp
- popl %ebp
- ret
-.LFE1:
-.ffi_call_SYSV_end:
- .size ffi_call_SYSV,.ffi_call_SYSV_end-ffi_call_SYSV
-
-.section .eh_frame,"aw",@progbits
-__FRAME_BEGIN__:
- .4byte .LLCIE1
-.LSCIE1:
- .4byte 0x0
- .byte 0x1
- .byte 0x0
- .byte 0x1
- .byte 0x7c
- .byte 0x8
- .byte 0xc
- .byte 0x4
- .byte 0x4
- .byte 0x88
- .byte 0x1
- .align 4
-.LECIE1:
- .set .LLCIE1,.LECIE1-.LSCIE1
- .4byte .LLFDE1
-.LSFDE1:
- .4byte .LSFDE1-__FRAME_BEGIN__
- .4byte .LFB1
- .4byte .LFE1-.LFB1
- .byte 0x4
- .4byte .LCFI0-.LFB1
- .byte 0xe
- .byte 0x8
- .byte 0x85
- .byte 0x2
- .byte 0x4
- .4byte .LCFI1-.LCFI0
- .byte 0xd
- .byte 0x5
- .align 4
-.LEFDE1:
- .set .LLFDE1,.LEFDE1-.LSFDE1
+++ /dev/null
-/* -----------------------------------------------------------------------
- win32.S - Copyright (c) 1996, 1998, 2001 Cygnus Solutions
-
- X86 Foreign Function Interface
-
- 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.
- ----------------------------------------------------------------------- */
-
-#define LIBFFI_ASM
-#include <ffi.h>
-
-.text
-
-.globl ffi_prep_args
-
- # This assumes we are using gas.
- .balign 16
-.globl _ffi_call_SYSV
-
-_ffi_call_SYSV:
- pushl %ebp
- movl %esp,%ebp
-
- # Make room for all of the new args.
- movl 16(%ebp),%ecx
- subl %ecx,%esp
-
- movl %esp,%eax
-
- # Place all of the ffi_prep_args in position
- pushl 12(%ebp)
- pushl %eax
- call *8(%ebp)
-
- # Return stack to previous state and call the function
- addl $8,%esp
-
- call *28(%ebp)
-
- # Remove the space we pushed for the args
- movl 16(%ebp),%ecx
- addl %ecx,%esp
-
- # Load %ecx with the return type code
- movl 20(%ebp),%ecx
-
- # If the return value pointer is NULL, assume no return value.
- cmpl $0,24(%ebp)
- jne retint
-
- # Even if there is no space for the return value, we are
- # obliged to handle floating-point values.
- cmpl $FFI_TYPE_FLOAT,%ecx
- jne noretval
- fstp %st(0)
-
- jmp epilogue
-
-retint:
- cmpl $FFI_TYPE_INT,%ecx
- jne retfloat
- # Load %ecx with the pointer to storage for the return value
- movl 24(%ebp),%ecx
- movl %eax,0(%ecx)
- jmp epilogue
-
-retfloat:
- cmpl $FFI_TYPE_FLOAT,%ecx
- jne retdouble
- # Load %ecx with the pointer to storage for the return value
- movl 24(%ebp),%ecx
- fstps (%ecx)
- jmp epilogue
-
-retdouble:
- cmpl $FFI_TYPE_DOUBLE,%ecx
- jne retlongdouble
- # Load %ecx with the pointer to storage for the return value
- movl 24(%ebp),%ecx
- fstpl (%ecx)
- jmp epilogue
-
-retlongdouble:
- cmpl $FFI_TYPE_LONGDOUBLE,%ecx
- jne retint64
- # Load %ecx with the pointer to storage for the return value
- movl 24(%ebp),%ecx
- fstpt (%ecx)
- jmp epilogue
-
-retint64:
- cmpl $FFI_TYPE_SINT64,%ecx
- jne retstruct
- # Load %ecx with the pointer to storage for the return value
- movl 24(%ebp),%ecx
- movl %eax,0(%ecx)
- movl %edx,4(%ecx)
-
-retstruct:
- # Nothing to do!
-
-noretval:
-epilogue:
- movl %ebp,%esp
- popl %ebp
- ret
-
-.ffi_call_SYSV_end: