[Mono-list] S390 patch

Ferguson, Neale Neale.Ferguson@SoftwareAG-USA.com
Mon, 30 Sep 2002 08:54:37 -0400


This message is in MIME format. Since your mail reader does not understand
this format, some or all of this message may not be legible.

------_=_NextPart_000_01C26880.8868B020
Content-Type: text/plain;
	charset="iso-8859-1"

Hi,
 Here's my first effort at the S390 port. 


------_=_NextPart_000_01C26880.8868B020
Content-Type: application/octet-stream;
	name="mono-s390.diffs"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
	filename="mono-s390.diffs"

Index: mono/configure.in
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /mono/mono/configure.in,v
retrieving revision 1.105
diff -u -r1.105 configure.in
--- mono/configure.in	27 Sep 2002 13:54:16 -0000	1.105
+++ mono/configure.in	30 Sep 2002 12:43:59 -0000
@@ -470,6 +470,7 @@
 #m68k-*-linux*) TARGET=3DM68K;;
 macppc-*-openbsd* | powerpc-*-linux* | powerpc-*-openbsd* | =
powerpc-*-sysv*) TARGET=3DPOWERPC; arch_target=3Dppc;;
 arm-*-linux-* | armv4l-*-linux-*) TARGET=3DARM; arch_target=3Darm; =
ACCESS_UNALIGNED=3D"no";;
+s390-*-linux*) TARGET=3DS390; arch_target=3Ds390; =
ACCESS_UNALIGNED=3D"no";;
 esac
=20
 if test ${TARGET} =3D unknown; then
@@ -489,6 +490,7 @@
 AM_CONDITIONAL(M68K, test x$TARGET =3D xM68K)
 AM_CONDITIONAL(POWERPC, test x$TARGET =3D xPOWERPC)
 AM_CONDITIONAL(ARM, test x$TARGET =3D xARM)
+AM_CONDITIONAL(S390, test x$TARGET =3D xS390)
=20
 LIBC=3D"libc.so.6"
 AC_SUBST(LIBC)
@@ -512,6 +514,7 @@
 mono/arch/x86/Makefile
 mono/arch/ppc/Makefile
 mono/arch/sparc/Makefile
+mono/arch/s390/Makefile
 mono/arch/arm/Makefile
 mono/interpreter/Makefile
 mono/tests/Makefile
Index: mono/mono/io-layer/atomic.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /mono/mono/mono/io-layer/atomic.h,v
retrieving revision 1.9
diff -u -r1.9 atomic.h
--- mono/mono/io-layer/atomic.h	27 Sep 2002 12:02:56 -0000	1.9
+++ mono/mono/io-layer/atomic.h	30 Sep 2002 12:43:59 -0000
@@ -246,6 +246,93 @@
         return(ret);
 }
=20
+#elif __s390__
+
+#define WAPI_ATOMIC_ASM
+
+static inline gint32=20
+InterlockedCompareExchange(volatile gint32 *dest,
+			   gint32 exch, gint32 comp)
+{
+	gint32 old;
+
+	__asm__ __volatile__ ("\tL\t%1,%0\n"
+			      "\tCS\t%3,%2,%0\n"
+			      : "=3Dm" (*dest), "=3Dr" (old)
+			      : "r" (exch), "r" (comp)
+			      : "cc");=09
+	return(old);
+}
+
+#define InterlockedCompareExchangePointer InterlockedCompareExchange
+
+static inline gint32=20
+InterlockedIncrement(volatile gint32 *val)
+{
+	gint32 tmp;
+=09
+	__asm__ __volatile__ ("0:\tL\t%0,%1\n"
+			      "\tLR\t1,%0\n"
+			      "\tAHI\t1,1\n"
+			      "0:\tCS\t%0,1,%1\n"
+			      "\tJNZ\t0b"
+			      : "=3Dr" (tmp), "+m" (*val)
+			      : : "1", "cc");
+
+	return(tmp+1);
+}
+
+static inline gint32=20
+InterlockedDecrement(volatile gint32 *val)
+{
+	gint32 tmp;
+=09
+	__asm__ __volatile__ ("0:\tL\t%0,%1\n"
+			      "\tLR\t1,%0\n"
+			      "\tAHI\t1,-1\n"
+			      "0:\tCS\t%0,1,%1\n"
+			      "\tJNZ\t0b"
+			      : "=3Dr" (tmp), "+m" (*val)
+			      : : "1", "cc");
+
+	return(tmp-1);
+}
+
+
+static inline gint32=20
+InterlockedExchange(volatile gint32 *val, gint32 new_val)
+{
+	gint32 ret;
+=09
+	__asm__ __volatile__ ("0:\tL\t%1,%0\n"
+			      "\tCS\t%1,%2,%0\n"
+			      "\tJNZ\t0b"
+			      : "+m" (*val), "=3Dr" (ret)
+			      : "r" (new_val)
+			      : "cc");
+
+	return(ret);
+}
+
+#define InterlockedExchangePointer InterlockedExchange
+
+static inline gint32=20
+InterlockedExchangeAdd(volatile gint32 *val, gint32 add)
+{
+	gint32 ret;
+
+	__asm__ __volatile__ ("0:\tL\t%0,%1\n"
+			      "\tLR\t1,%0\n"
+			      "\tAR\t1,%2\n"
+			      "0:\tCS\t%0,1,%1\n"
+			      "\tJNZ\t0b"
+			      : "=3Dr" (ret), "+m" (*val)
+			      : "r" (add)=20
+			      : "1", "cc");
+=09
+	return(ret);
+}
+
 #else
=20
 extern gint32 InterlockedCompareExchange(volatile gint32 *dest, gint32 =
exch, gint32 comp);
--- /dev/null	Thu Sep 26 21:58:57 2002
+++ mono/mono/arch/s390/Makefile.am	Fri Sep 27 12:06:53 2002
@@ -0,0 +1,7 @@
+
+INCLUDES =3D $(GLIB_CFLAGS) -I$(top_srcdir)
+
+noinst_LTLIBRARIES =3D libmonoarch-s390.la
+
+libmonoarch_s390_la_SOURCES =3D tramp.c s390-codegen.h
+
--- /dev/null	Thu Sep 26 21:58:57 2002
+++ mono/mono/arch/s390/Makefile.in	Fri Sep 27 12:43:41 2002
@@ -0,0 +1,342 @@
+# Makefile.in generated automatically by automake 1.4 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 =3D @SHELL@
+
+srcdir =3D @srcdir@
+top_srcdir =3D @top_srcdir@
+VPATH =3D @srcdir@
+prefix =3D @prefix@
+exec_prefix =3D @exec_prefix@
+
+bindir =3D @bindir@
+sbindir =3D @sbindir@
+libexecdir =3D @libexecdir@
+datadir =3D @datadir@
+sysconfdir =3D @sysconfdir@
+sharedstatedir =3D @sharedstatedir@
+localstatedir =3D @localstatedir@
+libdir =3D @libdir@
+infodir =3D @infodir@
+mandir =3D @mandir@
+includedir =3D @includedir@
+oldincludedir =3D /usr/include
+
+DESTDIR =3D
+
+pkgdatadir =3D $(datadir)/@PACKAGE@
+pkglibdir =3D $(libdir)/@PACKAGE@
+pkgincludedir =3D $(includedir)/@PACKAGE@
+
+top_builddir =3D ../../..
+
+ACLOCAL =3D @ACLOCAL@
+AUTOCONF =3D @AUTOCONF@
+AUTOMAKE =3D @AUTOMAKE@
+AUTOHEADER =3D @AUTOHEADER@
+
+INSTALL =3D @INSTALL@
+INSTALL_PROGRAM =3D @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
+INSTALL_DATA =3D @INSTALL_DATA@
+INSTALL_SCRIPT =3D @INSTALL_SCRIPT@
+transform =3D @program_transform_name@
+
+NORMAL_INSTALL =3D :
+PRE_INSTALL =3D :
+POST_INSTALL =3D :
+NORMAL_UNINSTALL =3D :
+PRE_UNINSTALL =3D :
+POST_UNINSTALL =3D :
+build_alias =3D @build_alias@
+build_triplet =3D @build@
+host_alias =3D @host_alias@
+host_triplet =3D @host@
+target_alias =3D @target_alias@
+target_triplet =3D @target@
+AS =3D @AS@
+BISON =3D @BISON@
+BUILD_EXEEXT =3D @BUILD_EXEEXT@
+BUILD_GLIB_CFLAGS =3D @BUILD_GLIB_CFLAGS@
+BUILD_GLIB_LIBS =3D @BUILD_GLIB_LIBS@
+CC =3D @CC@
+CC_FOR_BUILD =3D @CC_FOR_BUILD@
+CFLAGS =3D @CFLAGS@
+CPPFLAGS =3D @CPPFLAGS@
+DISABLE_SHARED_HANDLES =3D @DISABLE_SHARED_HANDLES@
+DLLTOOL =3D @DLLTOOL@
+GLIB_CFLAGS =3D @GLIB_CFLAGS@
+GLIB_LIBS =3D @GLIB_LIBS@
+GMODULE_CFLAGS =3D @GMODULE_CFLAGS@
+GMODULE_LIBS =3D @GMODULE_LIBS@
+HAVE_BOEHM_GC =3D @HAVE_BOEHM_GC@
+HOST_CC =3D @HOST_CC@
+LIBC =3D @LIBC@
+LIBTOOL =3D @LIBTOOL@
+LN_S =3D @LN_S@
+MAINT =3D @MAINT@
+MAKEINFO =3D @MAKEINFO@
+OBJDUMP =3D @OBJDUMP@
+PACKAGE =3D @PACKAGE@
+PKG_CONFIG =3D @PKG_CONFIG@
+RANLIB =3D @RANLIB@
+VERSION =3D @VERSION@
+arch_target =3D @arch_target@
+
+INCLUDES =3D $(GLIB_CFLAGS) -I$(top_srcdir)
+
+noinst_LTLIBRARIES =3D libmonoarch-s390.la
+
+libmonoarch_s390_la_SOURCES =3D tramp.c s390-codegen.h
+mkinstalldirs =3D $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER =3D ../../../config.h
+CONFIG_CLEAN_FILES =3D=20
+LTLIBRARIES =3D  $(noinst_LTLIBRARIES)
+
+
+DEFS =3D @DEFS@ -I. -I$(srcdir) -I../../..
+LDFLAGS =3D @LDFLAGS@
+LIBS =3D @LIBS@
+libmonoarch_s390_la_LDFLAGS =3D=20
+libmonoarch_s390_la_LIBADD =3D=20
+libmonoarch_s390_la_OBJECTS =3D  tramp.lo
+COMPILE =3D $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) =
$(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE =3D $(LIBTOOL) --mode=3Dcompile $(CC) $(DEFS) $(INCLUDES) =
$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD =3D $(CC)
+LINK =3D $(LIBTOOL) --mode=3Dlink $(CCLD) $(AM_CFLAGS) $(CFLAGS) =
$(LDFLAGS) -o $@
+DIST_COMMON =3D  Makefile.am Makefile.in
+
+
+DISTFILES =3D $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) =
$(EXTRA_DIST)
+
+TAR =3D tar
+GZIP_ENV =3D --best
+DEP_FILES =3D  .deps/tramp.P
+SOURCES =3D $(libmonoarch_s390_la_SOURCES)
+OBJECTS =3D $(libmonoarch_s390_la_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)=20
+	cd $(top_srcdir) && $(AUTOMAKE) --gnu mono/arch/s390/Makefile
+
+Makefile: $(srcdir)/Makefile.in  $(top_builddir)/config.status =
$(BUILT_SOURCES)
+	cd $(top_builddir) \
+	  && CONFIG_FILES=3D$(subdir)/$@ CONFIG_HEADERS=3D $(SHELL) =
./config.status
+
+
+mostlyclean-noinstLTLIBRARIES:
+
+clean-noinstLTLIBRARIES:
+	-test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+
+distclean-noinstLTLIBRARIES:
+
+maintainer-clean-noinstLTLIBRARIES:
+
+.s.o:
+	$(COMPILE) -c $<
+
+.S.o:
+	$(COMPILE) -c $<
+
+mostlyclean-compile:
+	-rm -f *.o core *.core
+
+clean-compile:
+
+distclean-compile:
+	-rm -f *.tab.c
+
+maintainer-clean-compile:
+
+.s.lo:
+	$(LIBTOOL) --mode=3Dcompile $(COMPILE) -c $<
+
+.S.lo:
+	$(LIBTOOL) --mode=3Dcompile $(COMPILE) -c $<
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+
+distclean-libtool:
+
+maintainer-clean-libtool:
+
+libmonoarch-s390.la: $(libmonoarch_s390_la_OBJECTS) =
$(libmonoarch_s390_la_DEPENDENCIES)
+	$(LINK)  $(libmonoarch_s390_la_LDFLAGS) =
$(libmonoarch_s390_la_OBJECTS) $(libmonoarch_s390_la_LIBADD) $(LIBS)
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP)
+	list=3D'$(SOURCES) $(HEADERS)'; \
+	unique=3D`for i in $$list; do echo $$i; done | \
+	  awk '    { files[$$0] =3D 1; } \
+	       END { for (i in files) print i; }'`; \
+	here=3D`pwd` && cd $(srcdir) \
+	  && mkid -f$$here/ID $$unique $(LISP)
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) $(LISP)
+	tags=3D; \
+	here=3D`pwd`; \
+	list=3D'$(SOURCES) $(HEADERS)'; \
+	unique=3D`for i in $$list; do echo $$i; done | \
+	  awk '    { files[$$0] =3D 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 =3D $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
+
+subdir =3D mono/arch/s390
+
+distdir: $(DISTFILES)
+	here=3D`cd $(top_builddir) && pwd`; \
+	top_distdir=3D`cd $(top_distdir) && pwd`; \
+	distdir=3D`cd $(distdir) && pwd`; \
+	cd $(top_srcdir) \
+	  && $(AUTOMAKE) --include-deps --build-dir=3D$$here =
--srcdir-name=3D$(top_srcdir) --output-dir=3D$$top_distdir --gnu =
mono/arch/s390/Makefile
+	@for file in $(DISTFILES); do \
+	  d=3D$(srcdir); \
+	  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
+
+DEPS_MAGIC :=3D $(shell mkdir .deps > /dev/null 2>&1 || :)
+
+-include $(DEP_FILES)
+
+mostlyclean-depend:
+
+clean-depend:
+
+distclean-depend:
+	-rm -rf .deps
+
+maintainer-clean-depend:
+
+%.o: %.c
+	@echo '$(COMPILE) -c $<'; \
+	$(COMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
+	@-cp .deps/$(*F).pp .deps/$(*F).P; \
+	tr ' ' '\012' < .deps/$(*F).pp \
+	  | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
+	    >> .deps/$(*F).P; \
+	rm .deps/$(*F).pp
+
+%.lo: %.c
+	@echo '$(LTCOMPILE) -c $<'; \
+	$(LTCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
+	@-sed -e 's/^\([^:]*\)\.o[ 	]*:/\1.lo \1.o :/' \
+	  < .deps/$(*F).pp > .deps/$(*F).P; \
+	tr ' ' '\012' < .deps/$(*F).pp \
+	  | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
+	    >> .deps/$(*F).P; \
+	rm -f .deps/$(*F).pp
+info-am:
+info: info-am
+dvi-am:
+dvi: dvi-am
+check-am: all-am
+check: check-am
+installcheck-am:
+installcheck: installcheck-am
+install-exec-am:
+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: uninstall-am
+all-am: Makefile $(LTLIBRARIES)
+all-redirect: all-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=3D-s install
+installdirs:
+
+
+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-noinstLTLIBRARIES mostlyclean-compile \
+		mostlyclean-libtool mostlyclean-tags mostlyclean-depend \
+		mostlyclean-generic
+
+mostlyclean: mostlyclean-am
+
+clean-am:  clean-noinstLTLIBRARIES clean-compile clean-libtool \
+		clean-tags clean-depend clean-generic mostlyclean-am
+
+clean: clean-am
+
+distclean-am:  distclean-noinstLTLIBRARIES distclean-compile \
+		distclean-libtool distclean-tags distclean-depend \
+		distclean-generic clean-am
+	-rm -f libtool
+
+distclean: distclean-am
+
+maintainer-clean-am:  maintainer-clean-noinstLTLIBRARIES \
+		maintainer-clean-compile maintainer-clean-libtool \
+		maintainer-clean-tags maintainer-clean-depend \
+		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-noinstLTLIBRARIES distclean-noinstLTLIBRARIES \
+clean-noinstLTLIBRARIES maintainer-clean-noinstLTLIBRARIES \
+mostlyclean-compile distclean-compile clean-compile \
+maintainer-clean-compile mostlyclean-libtool distclean-libtool \
+clean-libtool maintainer-clean-libtool tags mostlyclean-tags \
+distclean-tags clean-tags maintainer-clean-tags distdir \
+mostlyclean-depend distclean-depend clean-depend \
+maintainer-clean-depend info-am info dvi-am dvi check check-am \
+installcheck-am installcheck install-exec-am install-exec \
+install-data-am install-data install-am install uninstall-am uninstall =
\
+all-redirect all-am all installdirs mostlyclean-generic \
+distclean-generic clean-generic maintainer-clean-generic clean \
+mostlyclean distclean maintainer-clean
+
+
+# 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	Thu Sep 26 21:58:57 2002
+++ mono/mono/arch/s390/s390-codegen.h	Fri Sep 27 12:06:43 2002
@@ -0,0 +1,80 @@
+/*
+   Copyright (C)  2001 Radek Doulik
+*/
+
+#ifndef S390_H
+#define S390_H
+#include <glib.h>
+#include <assert.h>
+
+typedef enum {
+	s390_r0 =3D 0,
+	s390_r1,
+	s390_r2,
+	s390_r3,
+	s390_r4,
+	s390_r5,
+	s390_r6,
+	s390_r7,
+	s390_r8,
+	s390_r9,
+	s390_r10,
+	s390_r11,
+	s390_r12,
+	s390_r13,
+	s390_r14,
+	s390_r15,
+} S390IntRegister;
+
+typedef enum {
+	s390_f0 =3D 0,
+	s390_f1,
+	s390_f2,
+	s390_f3,
+	s390_f4,
+	s390_f5,
+	s390_f6,
+	s390_f7,
+	s390_f8,
+	s390_f9,
+	s390_f10,
+	s390_f11,
+	s390_f12,
+	s390_f13,
+	s390_f14,
+	s390_f15,
+} S390FloatRegister;
+
+typedef enum {
+	s390_fpc =3D 256,
+} S390SpecialRegister;
+
+#define s390_word(addr, value)		*((guint32 *) addr) =3D (guint32) =
(value); ((guint32 *) addr)++
+#define s390_emit16(c, x)		*((guint16 *) c) =3D x; ((guint16 *) c)++
+#define s390_emit32(c, x)		*((guint32 *) c) =3D x; ((guint32 *) c)++
+#define s390_basr(code, r1, r2)		s390_emit16 (code, (13 << 8 | (r1) << =
4 | (r2)))
+#define s390_bras(code, r, o)		s390_emit32 (code, (167 << 24 | (r) << =
20 | 5 << 16 | (o)))
+#define s390_ahi(code, r, v)		s390_emit32 (code, (167 << 24 | (r) << =
20 | 10 << 16 | ((v) & 0xffff)))
+#define s390_br(code, r)		s390_emit16 (code, (7 << 8 | 15 << 4 | (r)))
+#define s390_lr(code, r1, r2)		s390_emit16 (code, (24 << 8 | (r1) << 4 =
| (r2)))
+#define s390_l(code, r, b, d)		s390_emit32 (code, (88 << 24 | (r) << =
20 | (b) << 12 | ((d) & 0xfff)))
+#define s390_lm(code, r1, r2, b, d)	s390_emit32 (code, (152 << 24 | =
(r1) << 20 | (r2) << 16 \
+						    | (b) << 12 | ((d) & 0xfff)))
+#define s390_lh(code, r, b, d)		s390_emit32 (code, (72 << 24 | (r) << =
20 | (b) << 12 | ((d) & 0xfff)))
+#define s390_lhi(code, r, v)		s390_emit32 (code, (167 << 24 | (r) << =
20 | 8 << 16 | ((v) & 0xffff)))
+#define s390_ic(code, r, b, d)		s390_emit32 (code, (67 << 24 | (r) << =
20 | (b) << 12 | ((d) & 0xfff)))
+#define s390_st(code, r, b, d)		s390_emit32 (code, (80 << 24 | (r) << =
20 | (b) << 12 | ((d) & 0xfff)))
+#define s390_stm(code, r1, r2, b, d)	s390_emit32 (code, (144 << 24 | =
(r1) << 20 | (r2) << 16 \
+						    | (b) << 12 | ((d) & 0xfff)))
+#define s390_sth(code, r, b, d)		s390_emit32 (code, (64 << 24 | (r) << =
20 | (b) << 12 | ((d) & 0xfff)))
+#define s390_stc(code, r, b, d)		s390_emit32 (code, (66 << 24 | (r) << =
20 | (b) << 12 | ((d) & 0xfff)))
+#define s390_la(code, r, b, d)		s390_emit32 (code, (65 << 24 | (r) << =
20 | (b) << 12 | ((d) & 0xfff)))
+#define s390_ld(code, f, b, d)		s390_emit32 (code, (104 << 24 | (f) << =
20 | (b) << 12 | ((d) & 0xfff)))
+#define s390_le(code, f, b, d)		s390_emit32 (code, (120 << 24 | (f) << =
20 | (b) << 12 | ((d) & 0xfff)))
+#define s390_std(code, f, b, d)		s390_emit32 (code, (96 << 24 | (f) << =
20 | (b) << 12 | ((d) & 0xfff)))
+#define s390_ste(code, f, b, d)		s390_emit32 (code, (112 << 24 | (f) =
<< 20 | (b) << 12 | ((d) & 0xfff)))
+#define s390_mvc(c, l, b1, d1, b2, d2)	s390_emit32 (c, (210 << 24 | =
(((l) << 16) & 0x00ff0000) | \
+							(b1) << 12 | ((d1) & 0xfff))); 		  \
+					s390_emit16 (c, ((b2) << 12 | ((d2) & 0xfff)))
+
+#endif
--- /dev/null	Thu Sep 26 21:58:57 2002
+++ mono/mono/arch/s390/tramp.c	Fri Sep 27 12:20:08 2002
@@ -0,0 +1,729 @@
+/*
+ * Create trampolines to invoke arbitrary functions.
+ *=20
+ * Copyright (C) Radek Doulik
+ *=20
+ */
+
+#include "config.h"
+#include <stdlib.h>
+#include <string.h>
+#include "s390-codegen.h"
+#include "mono/metadata/class.h"
+#include "mono/metadata/tabledefs.h"
+#include "mono/interpreter/interp.h"
+#include "mono/metadata/appdomain.h"
+
+#ifdef NEED_MPROTECT
+# include <sys/mman.h>
+# include <limits.h>    /* for PAGESIZE */
+# ifndef PAGESIZE
+#  define PAGESIZE 4096
+# endif
+#endif
+
+#define DEBUG(x) (x)
+
+#define MIN_CACHE_LINE 256
+
+#define NOT_IMPLEMENTED(x) \
+                g_error ("FIXME: %s is not yet implemented. =
(trampoline)", x);
+
+#define PROLOG_INS 	20
+#define CALL_INS   	4
+#define EPILOG_INS 	18
+#define MIN_STACK_SIZE 	96
+#define FLOAT_REGS 	2
+#define GENERAL_REGS 	5
+
+static void inline
+add_general (guint *gr, guint *stack_size, guint *code_size, gboolean =
simple)
+{
+	if (simple) {
+		if (*gr >=3D GENERAL_REGS) {
+			*stack_size +=3D 4;
+			*code_size +=3D 8;    /* load from stack, save on stack */
+		} else {
+			*code_size +=3D 4;    /* load from stack */
+		}
+	} else {
+		if (*gr >=3D GENERAL_REGS - 1) {
+			*stack_size +=3D 8 + (*stack_size % 8);
+			*code_size +=3D 8;   /* 2x load from stack, 2x save to stack */
+		} else {
+			*code_size +=3D 8;   /* 2x load from stack */
+		}
+		(*gr) ++;
+	}
+	(*gr) ++;
+}
+
+static void inline
+calculate_sizes (MonoMethodSignature *sig, guint *stack_size, guint =
*code_size, gboolean string_ctor)
+{
+	guint i, fr, gr;
+	guint32 simpletype;
+
+	fr          =3D 0;
+	gr          =3D 2;
+	*stack_size =3D MIN_STACK_SIZE;
+	*code_size  =3D (PROLOG_INS + CALL_INS + EPILOG_INS);
+
+	if (sig->hasthis) {
+		add_general (&gr, stack_size, code_size, TRUE);
+	}
+
+	for (i =3D 0; i < sig->param_count; ++i) {
+		if (sig->params [i]->byref) {
+			add_general (&gr, stack_size, code_size, TRUE);
+			continue;
+		}
+		simpletype =3D sig->params [i]->type;
+	enum_calc_size:
+		switch (simpletype) {
+		case MONO_TYPE_BOOLEAN:
+		case MONO_TYPE_CHAR:
+		case MONO_TYPE_I1:
+		case MONO_TYPE_U1:
+		case MONO_TYPE_I2:
+		case MONO_TYPE_U2:
+		case MONO_TYPE_I4:
+		case MONO_TYPE_U4:
+		case MONO_TYPE_I:
+		case MONO_TYPE_U:
+		case MONO_TYPE_PTR:
+		case MONO_TYPE_CLASS:
+		case MONO_TYPE_OBJECT:
+		case MONO_TYPE_STRING:
+			add_general (&gr, stack_size, code_size, TRUE);
+			break;
+		case MONO_TYPE_SZARRAY:
+			add_general (&gr, stack_size, code_size, TRUE);
+			*code_size +=3D 4;
+			break;
+		case MONO_TYPE_VALUETYPE:
+			if (sig->params [i]->data.klass->enumtype) {
+				simpletype =3D sig->params [i]->data.klass->enum_basetype->type;
+				goto enum_calc_size;
+			}
+			if (mono_class_value_size (sig->params [i]->data.klass, NULL) !=3D =
4)
+				g_error ("can only marshal enums, not generic structures (size: =
%d)",
+					 mono_class_value_size (sig->params [i]->data.klass, NULL));
+			add_general (&gr, stack_size, code_size, TRUE);
+			*code_size +=3D 4;
+			break;
+		case MONO_TYPE_I8:
+			add_general (&gr, stack_size, code_size, FALSE);
+			break;
+		case MONO_TYPE_R4:
+			if (fr < FLOAT_REGS) {
+				*code_size +=3D 4;
+				fr++;
+			}
+			else {
+				*code_size  +=3D 4;
+				*stack_size +=3D 8;
+			}
+			break;
+		case MONO_TYPE_R8:
+			if (fr < FLOAT_REGS) {
+				*code_size +=3D 4;
+				fr ++;
+			} else {
+				*code_size  +=3D 4;
+				*stack_size +=3D 8 + (*stack_size % 8);
+			}
+			break;
+		default:
+			g_error ("Can't trampoline 0x%x", sig->params [i]->type);
+		}
+	}
+
+	if (sig->ret->byref || string_ctor) {
+		*code_size +=3D 8;
+	} else {
+		simpletype =3D sig->ret->type;
+enum_retvalue:
+		switch (simpletype) {
+		case MONO_TYPE_BOOLEAN:
+		case MONO_TYPE_I1:
+		case MONO_TYPE_U1:
+		case MONO_TYPE_I2:
+		case MONO_TYPE_U2:
+		case MONO_TYPE_CHAR:
+		case MONO_TYPE_I4:
+		case MONO_TYPE_U4:
+		case MONO_TYPE_I:
+		case MONO_TYPE_U:
+		case MONO_TYPE_CLASS:
+		case MONO_TYPE_OBJECT:
+		case MONO_TYPE_R4:
+		case MONO_TYPE_R8:
+		case MONO_TYPE_SZARRAY:
+		case MONO_TYPE_ARRAY:
+		case MONO_TYPE_STRING:
+			*code_size +=3D 8;
+			break;
+		case MONO_TYPE_I8:
+			*code_size +=3D 12;
+			break;
+		case MONO_TYPE_VALUETYPE:
+			if (sig->ret->data.klass->enumtype) {
+				simpletype =3D sig->ret->data.klass->enum_basetype->type;
+				goto enum_retvalue;
+			}
+			NOT_IMPLEMENTED ("valuetype");
+			break;
+		case MONO_TYPE_VOID:
+			break;
+		default:
+			g_error ("Can't handle as return value 0x%x", sig->ret->type);
+		}
+	}
+
+	/* align stack size to 16 */
+	DEBUG (printf ("      stack size: %d (%d)\n       code size: %d\n", =
(*stack_size + 15) & ~15, *stack_size, *code_size));
+	*stack_size =3D (*stack_size + 15) & ~15;
+
+}
+
+static inline guint8 *
+emit_prolog (guint8 *p, MonoMethodSignature *sig, guint stack_size)
+{
+	/* function prolog */
+	s390_stm (p, s390_r6, s390_r15, s390_r15, 24);
+	s390_l	 (p, s390_r7, s390_r15, 96);
+	s390_lr  (p, s390_r11, s390_r15);
+	s390_ahi (p, s390_r15, -(stack_size+96));
+	s390_st	 (p, s390_r11, s390_r15, 0);
+
+	/*-----------------------------------------*/
+	/* Save:				   */
+	/* - address of "callme"                   */
+	/* - address of "retval"		   */
+	/* - address of "arguments"		   */
+	/*-----------------------------------------*/
+	s390_lr	 (p, s390_r9, s390_r2);
+	s390_lr  (p, s390_r8, s390_r3);
+	s390_lr  (p, s390_r10, s390_r5);
+
+	return p;
+}
+
+#define ARG_BASE s390_r10
+#define STK_BASE s390_r15
+#define STKARG (i*(sizeof(stackval)))
+/*
+ * The resulting function takes the form:
+ * void func (void (*callme)(), void *retval, void *this_obj, stackval =
*arguments);
+ */
+
+
+inline static guint8*
+emit_save_parameters (guint8 *p, MonoMethodSignature *sig, guint =
stack_size)
+{
+	guint i, fr, gr, act_strs, stack_par_pos;
+	guint32 simpletype;
+
+	gr =3D fr       =3D 0;
+	act_strs      =3D 0;
+	stack_par_pos =3D MIN_STACK_SIZE;
+
+	if (sig->hasthis) {
+		s390_lr (p, s390_r2, s390_r4);
+		gr++;
+	}
+
+	DEBUG (printf ("           count: %d\n",sig->param_count));
+	act_strs =3D 0;
+	for (i =3D 0; i < sig->param_count; ++i) {
+		if (sig->params [i]->byref) {
+			if (gr < GENERAL_REGS) {
+				s390_l  (p, s390_r2 + gr, ARG_BASE, STKARG);
+				gr ++;
+			} else {
+				s390_l  (p, s390_r0, ARG_BASE, STKARG);
+				s390_st (p, s390_r0, STK_BASE, stack_par_pos);
+				stack_par_pos +=3D sizeof(long);
+			}
+			continue;
+		}
+		simpletype =3D sig->params [i]->type;
+	enum_calc_size:
+		switch (simpletype) {
+		case MONO_TYPE_BOOLEAN:
+		case MONO_TYPE_I1:
+		case MONO_TYPE_U1:
+		case MONO_TYPE_I2:
+		case MONO_TYPE_U2:
+		case MONO_TYPE_CHAR:
+		case MONO_TYPE_I4:
+		case MONO_TYPE_U4:
+		case MONO_TYPE_I:
+		case MONO_TYPE_U:
+		case MONO_TYPE_PTR:
+		case MONO_TYPE_CLASS:
+		case MONO_TYPE_OBJECT:
+		case MONO_TYPE_STRING:
+		case MONO_TYPE_SZARRAY:
+			if (gr < GENERAL_REGS) {
+				s390_l  (p, s390_r2 + gr, ARG_BASE, STKARG);
+				gr ++;
+			} else {
+				s390_l  (p, s390_r0, ARG_BASE, STKARG);
+				s390_st (p, s390_r0, STK_BASE, stack_par_pos);
+			        stack_par_pos +=3D sizeof(long);
+			}
+			break;
+		case MONO_TYPE_VALUETYPE:
+			if (sig->params [i]->data.klass->enumtype) {
+				simpletype =3D sig->params [i]->data.klass->enum_basetype->type;
+				goto enum_calc_size;
+			}
+			if (mono_class_value_size (sig->params [i]->data.klass, NULL) !=3D =
4)
+				g_error ("can only marshal enums, not generic structures (size: =
%d)",
+					 mono_class_value_size (sig->params [i]->data.klass, NULL));
+			if (gr < GENERAL_REGS) {
+				s390_l  (p, s390_r2 + gr, ARG_BASE, STKARG);
+				s390_l  (p, s390_r2 + gr, s390_r2 + gr, 0);
+				gr++;
+			} else {
+				s390_l  (p, s390_r10, ARG_BASE, STKARG);
+				s390_l  (p, s390_r10, s390_r10, 0);
+				s390_st (p, s390_r10, STK_BASE, stack_par_pos);
+				stack_par_pos +=3D sizeof(long);
+			}
+			break;
+		case MONO_TYPE_I8:
+			if (gr < GENERAL_REGS-1) {
+				s390_lm  (p, s390_r2 + gr, s390_r2 + gr + 1, ARG_BASE, STKARG);=20
+				gr +=3D 2;
+			} else {
+				*(guint32 *) p +=3D 7;
+				*(guint32 *) p &=3D ~7;
+				s390_mvc (p, sizeof(long long), STK_BASE, stack_par_pos, ARG_BASE, =
STKARG);=20
+				stack_par_pos +=3D sizeof(long long) + (stack_par_pos % =
sizeof(long long));
+			}
+			break;
+		case MONO_TYPE_R4:
+			if (fr < FLOAT_REGS) {
+				s390_le  (p, s390_r0 + fr, ARG_BASE, STKARG);
+				fr++;
+			} else {
+				s390_mvc  (p, sizeof(float), STK_BASE, stack_par_pos, ARG_BASE, =
STKARG);
+				stack_par_pos +=3D sizeof(float);
+			}
+			break;
+		case MONO_TYPE_R8:
+			if (fr < FLOAT_REGS) {
+				s390_ld  (p, s390_r0 + fr, ARG_BASE, STKARG);
+				fr++;
+			} else {
+				*(guint32 *) p +=3D 7;
+				*(guint32 *) p &=3D ~7;
+				s390_mvc  (p, sizeof(double), STK_BASE, stack_par_pos, ARG_BASE, =
STKARG);
+				stack_par_pos +=3D sizeof(long long) + (stack_par_pos % =
sizeof(long long));
+			}
+			break;
+		default:
+			g_error ("Can't trampoline 0x%x", sig->params [i]->type);
+		}
+	}
+
+	return p;
+}
+
+static inline guint8 *
+alloc_code_memory (guint code_size)
+{
+	guint8 *p;
+
+#ifdef NEED_MPROTECT
+	p =3D g_malloc (code_size + PAGESIZE - 1);
+
+	/* Align to a multiple of PAGESIZE, assumed to be a power of two */
+	p =3D (char *)(((int) p + PAGESIZE-1) & ~(PAGESIZE-1));
+#else
+	p =3D g_malloc (code_size);
+#endif
+	DEBUG (printf ("           align: %p (%d)\n", p, (guint)p % 4));
+
+	return p;
+}
+
+static inline guint8 *
+emit_call_and_store_retval (guint8 *p, MonoMethodSignature *sig, guint =
stack_size, gboolean string_ctor)
+{
+	guint32 simpletype;
+
+	/* call "callme" */
+	s390_basr (p, s390_r14, s390_r9);=20
+
+	/* get return value */
+	if (sig->ret->byref || string_ctor) {
+		s390_st (p, s390_r2, s390_r8, 0);
+	} else {
+		simpletype =3D sig->ret->type;
+enum_retvalue:
+		switch (simpletype) {
+		case MONO_TYPE_BOOLEAN:
+		case MONO_TYPE_I1:
+		case MONO_TYPE_U1:
+			s390_stc (p, s390_r2, s390_r8, 0);
+			break;
+		case MONO_TYPE_I2:
+		case MONO_TYPE_U2:
+		case MONO_TYPE_CHAR:
+			s390_sth (p, s390_r2, s390_r8, 0);
+			break;
+		case MONO_TYPE_I4:
+		case MONO_TYPE_U4:
+		case MONO_TYPE_I:
+		case MONO_TYPE_U:
+		case MONO_TYPE_CLASS:
+		case MONO_TYPE_OBJECT:
+		case MONO_TYPE_SZARRAY:
+		case MONO_TYPE_ARRAY:
+		case MONO_TYPE_STRING:
+			s390_st (p, s390_r2, s390_r8, 0);
+			break;
+		case MONO_TYPE_R4:
+			s390_ste (p, s390_f0, s390_r8, 0);
+			break;
+		case MONO_TYPE_R8:
+			s390_std (p, s390_f0, s390_r8, 0);
+			break;
+		case MONO_TYPE_I8:
+			s390_stm (p, s390_r2, s390_r3, s390_r8, 0);
+			break;
+		case MONO_TYPE_VALUETYPE:
+			if (sig->ret->data.klass->enumtype) {
+				simpletype =3D sig->ret->data.klass->enum_basetype->type;
+				goto enum_retvalue;
+			}
+			s390_st (p, s390_r2, s390_r8, 0);
+			break;
+		case MONO_TYPE_VOID:
+			break;
+		default:
+			g_error ("Can't handle as return value 0x%x", sig->ret->type);
+		}
+	}
+
+	return p;
+}
+
+static inline guint8 *
+emit_epilog (guint8 *p, MonoMethodSignature *sig, guint stack_size)
+{
+	/* function epilog */
+	s390_l   (p, s390_r15, s390_r15, 0);
+	s390_l   (p, s390_r4, s390_r15, 56);
+	s390_lm  (p, s390_r6, s390_r15, s390_r15, 24);
+	s390_br  (p, s390_r4);
+
+	return p;
+}
+
+MonoPIFunc
+mono_create_trampoline (MonoMethodSignature *sig, gboolean =
string_ctor)
+{
+	guint8 *p, *code_buffer;
+	guint stack_size, code_size;
+
+	DEBUG (printf ("\nPInvoke [start emiting]\n"));
+	calculate_sizes (sig, &stack_size, &code_size, string_ctor);
+
+	p =3D code_buffer =3D alloc_code_memory (code_size);
+	p =3D emit_prolog (p, sig, stack_size);
+	p =3D emit_save_parameters (p, sig, stack_size);
+	p =3D emit_call_and_store_retval (p, sig, stack_size, string_ctor);
+	p =3D emit_epilog (p, sig, stack_size);
+
+#ifdef NEED_MPROTECT
+	if (mprotect (code_buffer, 1024, PROT_READ | PROT_WRITE | PROT_EXEC)) =
{
+		g_error ("Cannot mprotect trampoline\n");
+	}
+#endif
+
+	DEBUG (printf ("emited code size: %d\n", p - code_buffer));
+
+	DEBUG (printf ("PInvoke [end emiting]\n"));
+
+	return (MonoPIFunc) code_buffer;
+	/* return fake_func; */
+}
+
+
+#define MINV_POS  	96  /* MonoInvocation structure offset on stack */
+#define STACK_POS 	(MINV_POS - sizeof (stackval) * sig->param_count)
+#define OBJ_POS   	8
+#define TYPE_OFFSET 	(G_STRUCT_OFFSET (stackval, type))
+
+/*
+ * Returns a pointer to a native function that can be used to
+ * call the specified method.
+ * The function created will receive the arguments according
+ * to the call convention specified in the method.
+ * This function works by creating a MonoInvocation structure,
+ * filling the fields in and calling ves_exec_method on it.
+ * Still need to figure out how to handle the exception stuff
+ * across the managed/unmanaged boundary.
+ *
+ * Logic:
+ * ------
+ * mono_create_method_pointer (MonoMethod *method)
+ * 	create the unmanaged->managed wrapper for method
+ * 	register it with mono_jit_info_table_add ()
+ * 	return the pointer to the code.
+ *=20
+ * What does the unmanaged->managed wrapper do?
+ * 	allocate a MonoInvocation structure (inv) on the stack
+ * 	allocate an array of stackval on the stack with length
+ * 		method->signature->param_count + 1 (call it stack_args)
+ * 	set inv->ex, inv->ex_handler, inv->child, inv->parent to NULL
+ * 	set inv->method to method
+ * 	if method is an instance method, set inv->obj to the 'this' =
argument
+ * 		(the first argument) otherwise set it to NULL
+ * 	for each argument to the method, call:
+ * 		stackval_from_data (sig->params [i], &stack_args [i], arg, =
sig->pinvoke);
+ * 		where sig is method->signature, arg is a pointer to the
+ * 		argument received by the function according to the call
+ * 		convention (if it gets passed in a reg, you need to save
+ * 		it on the stack first), &stack_args [i] is the pointer
+ * 		to the i element in the stackval array we allocated on
+ * 		the stack
+ * 	set inv->retval to the address of the last element of stack_args
+ * 		(we allocated param_count + 1, remember)
+ * 	call ves_exec_method (inv)
+ * 	copy the return value from inv->retval where the calling
+ * 		convention expects to find it on return from the wrapper
+ * 		(if it's a structure, use stackval_to_data)
+ * 	return
+ *=20
+ */
+void *
+mono_create_method_pointer (MonoMethod *method)
+{
+	MonoMethodSignature *sig;
+	MonoJitInfo *ji;
+	guint8 *p, *code_buffer;
+	guint i, align =3D 0, code_size, stack_size,=20
+		stackval_arg_pos, local_pos,=20
+		local_start, reg_param, stack_param,
+		this_flag;
+	guint32 simpletype;
+	int *vtbuf, cpos, vt_cur;
+
+	code_size   =3D 1024;
+	stack_size  =3D 1024;
+	stack_param =3D 0;
+
+	sig =3D method->signature;
+
+	p =3D code_buffer =3D g_malloc (code_size);
+
+	DEBUG (printf ("\nDelegate [start emiting] %s at 0x%08x\n", =
method->name,p));
+
+	/* prolog */
+	s390_stm (p, s390_r6, s390_r15, s390_r15, 24);
+	s390_l   (p, s390_r7, s390_r15, 96);
+	s390_lr  (p, s390_r0, s390_r15);
+	s390_ahi (p, s390_r15, -(stack_size+96));
+	s390_st  (p, s390_r0, s390_r15, 0);
+
+	/* let's fill MonoInvocation */
+	/* first zero some fields */
+	s390_lhi (p, s390_r0, 0);
+	s390_st  (p, s390_r0, s390_r15, (MINV_POS + G_STRUCT_OFFSET =
(MonoInvocation, ex)));
+	s390_st  (p, s390_r0, s390_r15, (MINV_POS + G_STRUCT_OFFSET =
(MonoInvocation, ex_handler)));
+	s390_st  (p, s390_r0, s390_r15, (MINV_POS + G_STRUCT_OFFSET =
(MonoInvocation, child)));
+	s390_st  (p, s390_r0, s390_r15, (MINV_POS + G_STRUCT_OFFSET =
(MonoInvocation, parent)));
+
+	/* set method pointer */
+	s390_bras (p, s390_r13, 4);
+	s390_word (p, method);
+	s390_l	  (p, s390_r0, s390_r13, 0);
+	s390_st (p, s390_r0, s390_r15, (MINV_POS + G_STRUCT_OFFSET =
(MonoInvocation, method)));
+
+	local_start =3D local_pos =3D MINV_POS +=20
+		      sizeof (MonoInvocation) + (sig->param_count + 1) * sizeof =
(stackval);
+
+	if (sig->hasthis) {
+		s390_st  (p, s390_r2, s390_r15, (MINV_POS + G_STRUCT_OFFSET =
(MonoInvocation, obj)));
+		reg_param =3D 1;
+	} else if (sig->param_count) {
+		DEBUG (printf ("save r%d\n", 3));
+		s390_st (p, s390_r2, s390_r15, local_pos);
+		local_pos +=3D sizeof(int);
+		reg_param =3D 0;
+	}
+
+	this_flag =3D (sig->hasthis ? 1 : 0);
+	if (sig->param_count) {
+		gint save_count =3D MAX (3, MIN (6, sig->param_count - 1));
+		for (i =3D reg_param; i < save_count; i ++) {
+			s390_st (p, s390_r3 + i, s390_r15, local_pos);
+			local_pos +=3D sizeof(int);
+			DEBUG (printf ("save r%d\n", 4 + i));
+		}
+	}
+
+	/* prepare space for valuetypes */
+	vt_cur =3D local_pos;
+	vtbuf  =3D alloca (sizeof(int)*sig->param_count);
+	cpos   =3D 0;
+	for (i =3D 0; i < sig->param_count; i++) {
+		MonoType *type =3D sig->params [i];
+		vtbuf [i] =3D -1;
+		if (type->type =3D=3D MONO_TYPE_VALUETYPE) {
+			MonoClass *klass =3D type->data.klass;
+			gint size;
+
+			if (klass->enumtype)
+				continue;
+			size =3D mono_class_native_size (klass, &align);
+			cpos +=3D align - 1;
+			cpos &=3D ~(align - 1);
+			vtbuf [i] =3D cpos;
+			cpos +=3D size;
+		}
+	}
+	cpos +=3D 3;
+	cpos &=3D ~3;
+
+	local_pos +=3D cpos;
+
+	/* set MonoInvocation::stack_args */
+	stackval_arg_pos =3D MINV_POS + sizeof (MonoInvocation);
+	s390_la  (p, s390_r0, s390_r15, stackval_arg_pos);
+	s390_st  (p, s390_r0, s390_r15, (MINV_POS + G_STRUCT_OFFSET =
(MonoInvocation, stack_args)));
+
+	/* add stackval arguments */
+	for (i =3D 0; i < sig->param_count; ++i) {
+		if (reg_param < GENERAL_REGS) {
+			s390_la (p, s390_r4, s390_r15, local_start + (reg_param - =
this_flag)*4);
+			reg_param ++;
+		} else {
+			s390_la (p, s390_r4, s390_r15, stack_size + 8 + stack_param);
+			stack_param ++;
+		}
+		/*--------------------------------------*/
+		/* Load the parameter registers for the */
+		/* call to stackval_from_data		*/
+		/*--------------------------------------*/
+		s390_bras (p, s390_r13, 8);
+		s390_word (p, sig->params [i]);
+		s390_word (p, sig->pinvoke);
+		s390_word (p, stackval_from_data);
+		s390_l	  (p, s390_r2, s390_r13, 0);
+
+		s390_la   (p, s390_r3, s390_r15, stackval_arg_pos);
+
+		s390_l	  (p, s390_r5, s390_r13, 4);
+
+		s390_l	  (p, s390_r9, s390_r13, 8);
+		s390_basr (p, s390_r14, s390_r9);
+
+		/* fixme: alignment */
+		DEBUG (printf ("arg_pos %d --> ", stackval_arg_pos));
+		if (sig->pinvoke)
+			stackval_arg_pos +=3D 4*mono_type_native_stack_size (sig->params =
[i], &align);
+		else
+			stackval_arg_pos +=3D 4*mono_type_stack_size (sig->params [i], =
&align);
+		DEBUG (printf ("%d\n", stackval_arg_pos));
+	}
+
+	/* return value storage */
+	s390_la (p, s390_r10, s390_r15, stackval_arg_pos);
+	s390_st (p, s390_r10, s390_r15, (MINV_POS + G_STRUCT_OFFSET =
(MonoInvocation, retval)));
+
+	/* call ves_exec_method */
+	s390_bras (p, s390_r13, 4);
+	s390_word (p, ves_exec_method);
+	s390_l	  (p, s390_r9, s390_r13, 0);
+	s390_la	  (p, s390_r2, s390_r15, MINV_POS);
+	s390_basr (p, s390_r14, s390_r9);
+
+	/* move retval from stackval to proper place (r3/r4/...) */
+	if (sig->ret->byref) {
+		DEBUG (printf ("ret by ref\n"));
+		s390_st (p, s390_r2, s390_r10, 0);
+	} else {
+	enum_retvalue:
+		switch (sig->ret->type) {
+		case MONO_TYPE_VOID:
+			break;
+		case MONO_TYPE_BOOLEAN:
+		case MONO_TYPE_I1:
+		case MONO_TYPE_U1:
+			s390_lhi (p, s390_r2, 0);
+			s390_ic  (p, s390_r2, s390_r10, 0);
+			break;
+		case MONO_TYPE_I2:
+		case MONO_TYPE_U2:
+			s390_lh (p, s390_r2, s390_r10, 0);
+			break;
+		case MONO_TYPE_I4:
+		case MONO_TYPE_U4:
+		case MONO_TYPE_I:
+		case MONO_TYPE_U:
+		case MONO_TYPE_OBJECT:
+		case MONO_TYPE_STRING:
+		case MONO_TYPE_CLASS:
+			s390_l (p, s390_r2, s390_r10, 0);
+			break;
+		case MONO_TYPE_I8:
+			s390_lm (p, s390_r2, s390_r3, s390_r10, 0);
+			break;
+		case MONO_TYPE_R4:
+			s390_le (p, s390_f0, s390_r10, 0);
+			break;
+		case MONO_TYPE_R8:
+			s390_ld (p, s390_f0, s390_r10, 0);
+			break;
+		case MONO_TYPE_VALUETYPE:
+			if (sig->ret->data.klass->enumtype) {
+				simpletype =3D sig->ret->data.klass->enum_basetype->type;
+				goto enum_retvalue;
+			}
+			/*---------------------------------*/
+			/* Call stackval_to_data to return */
+			/* the structure		   */
+			/*---------------------------------*/
+			s390_bras (p, s390_r13, 8);
+			s390_word (p, sig->ret);
+			s390_word (p, sig->pinvoke);
+			s390_word (p, stackval_to_data);
+			s390_l	  (p, s390_r2, s390_r13, 0);
+			s390_l	  (p, s390_r3, s390_r15, stackval_arg_pos);
+			s390_la	  (p, s390_r4, s390_r10, 0);
+			s390_l	  (p, s390_r5, s390_r13, 4);
+			s390_l    (p, s390_r9, s390_r13, 8);
+			s390_basr (p, s390_r14, s390_r9);
+			break;
+		default:
+			g_error ("Type 0x%x not handled yet in thunk creation", =
sig->ret->type);
+			break;
+		}
+	}
+
+	/* epilog */
+	s390_l   (p, s390_r15, s390_r11, 0);
+	s390_l   (p, s390_r4, s390_r15, 56);
+	s390_lm  (p, s390_r6, s390_r15, s390_r15, 24);
+	s390_br  (p, s390_r4);
+
+	DEBUG (printf ("emited code size: %d\n", p - code_buffer));
+
+	DEBUG (printf ("Delegate [end emiting]\n"));
+
+	ji =3D g_new0 (MonoJitInfo, 1);
+	ji->method =3D method;
+	ji->code_size =3D p - code_buffer;
+	ji->code_start =3D code_buffer;
+
+	mono_jit_info_table_add (mono_root_domain, ji);
+
+	return ji->code_start;
+}

------_=_NextPart_000_01C26880.8868B020--