[prev in list] [next in list] [prev in thread] [next in thread]
List: mono-list
Subject: [Mono-list] S390 patch
From: "Ferguson, Neale" <Neale.Ferguson () SoftwareAG-USA ! com>
Date: 2002-09-30 12:54:37
[Download RAW message or body]
Hi,
Here's my first effort at the S390 port.
["mono-s390.diffs" (application/octet-stream)]
Index: mono/configure.in
===================================================================
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=M68K;;
macppc-*-openbsd* | powerpc-*-linux* | powerpc-*-openbsd* | powerpc-*-sysv*) \
TARGET=POWERPC; arch_target=ppc;; arm-*-linux-* | armv4l-*-linux-*) TARGET=ARM; \
arch_target=arm; ACCESS_UNALIGNED="no";; +s390-*-linux*) TARGET=S390; \
arch_target=s390; ACCESS_UNALIGNED="no";; esac
if test ${TARGET} = unknown; then
@@ -489,6 +490,7 @@
AM_CONDITIONAL(M68K, test x$TARGET = xM68K)
AM_CONDITIONAL(POWERPC, test x$TARGET = xPOWERPC)
AM_CONDITIONAL(ARM, test x$TARGET = xARM)
+AM_CONDITIONAL(S390, test x$TARGET = xS390)
LIBC="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
===================================================================
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);
}
+#elif __s390__
+
+#define WAPI_ATOMIC_ASM
+
+static inline gint32
+InterlockedCompareExchange(volatile gint32 *dest,
+ gint32 exch, gint32 comp)
+{
+ gint32 old;
+
+ __asm__ __volatile__ ("\tL\t%1,%0\n"
+ "\tCS\t%3,%2,%0\n"
+ : "=m" (*dest), "=r" (old)
+ : "r" (exch), "r" (comp)
+ : "cc");
+ return(old);
+}
+
+#define InterlockedCompareExchangePointer InterlockedCompareExchange
+
+static inline gint32
+InterlockedIncrement(volatile gint32 *val)
+{
+ gint32 tmp;
+
+ __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"
+ : "=r" (tmp), "+m" (*val)
+ : : "1", "cc");
+
+ return(tmp+1);
+}
+
+static inline gint32
+InterlockedDecrement(volatile gint32 *val)
+{
+ gint32 tmp;
+
+ __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"
+ : "=r" (tmp), "+m" (*val)
+ : : "1", "cc");
+
+ return(tmp-1);
+}
+
+
+static inline gint32
+InterlockedExchange(volatile gint32 *val, gint32 new_val)
+{
+ gint32 ret;
+
+ __asm__ __volatile__ ("0:\tL\t%1,%0\n"
+ "\tCS\t%1,%2,%0\n"
+ "\tJNZ\t0b"
+ : "+m" (*val), "=r" (ret)
+ : "r" (new_val)
+ : "cc");
+
+ return(ret);
+}
+
+#define InterlockedExchangePointer InterlockedExchange
+
+static inline gint32
+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"
+ : "=r" (ret), "+m" (*val)
+ : "r" (add)
+ : "1", "cc");
+
+ return(ret);
+}
+
#else
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 = $(GLIB_CFLAGS) -I$(top_srcdir)
+
+noinst_LTLIBRARIES = libmonoarch-s390.la
+
+libmonoarch_s390_la_SOURCES = 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 = @SHELL@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @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@ $(AM_INSTALL_PROGRAM_FLAGS)
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+transform = @program_transform_name@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_alias = @build_alias@
+build_triplet = @build@
+host_alias = @host_alias@
+host_triplet = @host@
+target_alias = @target_alias@
+target_triplet = @target@
+AS = @AS@
+BISON = @BISON@
+BUILD_EXEEXT = @BUILD_EXEEXT@
+BUILD_GLIB_CFLAGS = @BUILD_GLIB_CFLAGS@
+BUILD_GLIB_LIBS = @BUILD_GLIB_LIBS@
+CC = @CC@
+CC_FOR_BUILD = @CC_FOR_BUILD@
+CFLAGS = @CFLAGS@
+CPPFLAGS = @CPPFLAGS@
+DISABLE_SHARED_HANDLES = @DISABLE_SHARED_HANDLES@
+DLLTOOL = @DLLTOOL@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GMODULE_CFLAGS = @GMODULE_CFLAGS@
+GMODULE_LIBS = @GMODULE_LIBS@
+HAVE_BOEHM_GC = @HAVE_BOEHM_GC@
+HOST_CC = @HOST_CC@
+LIBC = @LIBC@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+OBJDUMP = @OBJDUMP@
+PACKAGE = @PACKAGE@
+PKG_CONFIG = @PKG_CONFIG@
+RANLIB = @RANLIB@
+VERSION = @VERSION@
+arch_target = @arch_target@
+
+INCLUDES = $(GLIB_CFLAGS) -I$(top_srcdir)
+
+noinst_LTLIBRARIES = libmonoarch-s390.la
+
+libmonoarch_s390_la_SOURCES = tramp.c s390-codegen.h
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = ../../../config.h
+CONFIG_CLEAN_FILES =
+LTLIBRARIES = $(noinst_LTLIBRARIES)
+
+
+DEFS = @DEFS@ -I. -I$(srcdir) -I../../..
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+libmonoarch_s390_la_LDFLAGS =
+libmonoarch_s390_la_LIBADD =
+libmonoarch_s390_la_OBJECTS = tramp.lo
+COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) \
$(CFLAGS) +LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) \
$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC)
+LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
+DIST_COMMON = Makefile.am Makefile.in
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+TAR = tar
+GZIP_ENV = --best
+DEP_FILES = .deps/tramp.P
+SOURCES = $(libmonoarch_s390_la_SOURCES)
+OBJECTS = $(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) + cd $(top_srcdir) && $(AUTOMAKE) --gnu mono/arch/s390/Makefile
+
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES)
+ cd $(top_builddir) \
+ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(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=compile $(COMPILE) -c $<
+
+.S.lo:
+ $(LIBTOOL) --mode=compile $(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='$(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)
+
+subdir = mono/arch/s390
+
+distdir: $(DISTFILES)
+ here=`cd $(top_builddir) && pwd`; \
+ top_distdir=`cd $(top_distdir) && pwd`; \
+ distdir=`cd $(distdir) && pwd`; \
+ cd $(top_srcdir) \
+ && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) \
--output-dir=$$top_distdir --gnu mono/arch/s390/Makefile + @for file in $(DISTFILES); \
do \ + d=$(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 := $(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=-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 = 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 = 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 = 256,
+} S390SpecialRegister;
+
+#define s390_word(addr, value) *((guint32 *) addr) = (guint32) (value); ((guint32 \
*) addr)++ +#define s390_emit16(c, x) *((guint16 *) c) = x; ((guint16 *) c)++
+#define s390_emit32(c, x) *((guint32 *) c) = 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.
+ *
+ * Copyright (C) Radek Doulik
+ *
+ */
+
+#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 >= GENERAL_REGS) {
+ *stack_size += 4;
+ *code_size += 8; /* load from stack, save on stack */
+ } else {
+ *code_size += 4; /* load from stack */
+ }
+ } else {
+ if (*gr >= GENERAL_REGS - 1) {
+ *stack_size += 8 + (*stack_size % 8);
+ *code_size += 8; /* 2x load from stack, 2x save to stack */
+ } else {
+ *code_size += 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 = 0;
+ gr = 2;
+ *stack_size = MIN_STACK_SIZE;
+ *code_size = (PROLOG_INS + CALL_INS + EPILOG_INS);
+
+ if (sig->hasthis) {
+ add_general (&gr, stack_size, code_size, TRUE);
+ }
+
+ for (i = 0; i < sig->param_count; ++i) {
+ if (sig->params [i]->byref) {
+ add_general (&gr, stack_size, code_size, TRUE);
+ continue;
+ }
+ simpletype = 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 += 4;
+ break;
+ case MONO_TYPE_VALUETYPE:
+ if (sig->params [i]->data.klass->enumtype) {
+ simpletype = sig->params [i]->data.klass->enum_basetype->type;
+ goto enum_calc_size;
+ }
+ if (mono_class_value_size (sig->params [i]->data.klass, NULL) != 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 += 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 += 4;
+ fr++;
+ }
+ else {
+ *code_size += 4;
+ *stack_size += 8;
+ }
+ break;
+ case MONO_TYPE_R8:
+ if (fr < FLOAT_REGS) {
+ *code_size += 4;
+ fr ++;
+ } else {
+ *code_size += 4;
+ *stack_size += 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 += 8;
+ } else {
+ simpletype = 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 += 8;
+ break;
+ case MONO_TYPE_I8:
+ *code_size += 12;
+ break;
+ case MONO_TYPE_VALUETYPE:
+ if (sig->ret->data.klass->enumtype) {
+ simpletype = 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 = (*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 = fr = 0;
+ act_strs = 0;
+ stack_par_pos = MIN_STACK_SIZE;
+
+ if (sig->hasthis) {
+ s390_lr (p, s390_r2, s390_r4);
+ gr++;
+ }
+
+ DEBUG (printf (" count: %d\n",sig->param_count));
+ act_strs = 0;
+ for (i = 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 += sizeof(long);
+ }
+ continue;
+ }
+ simpletype = 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 += sizeof(long);
+ }
+ break;
+ case MONO_TYPE_VALUETYPE:
+ if (sig->params [i]->data.klass->enumtype) {
+ simpletype = sig->params [i]->data.klass->enum_basetype->type;
+ goto enum_calc_size;
+ }
+ if (mono_class_value_size (sig->params [i]->data.klass, NULL) != 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 += 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);
+ gr += 2;
+ } else {
+ *(guint32 *) p += 7;
+ *(guint32 *) p &= ~7;
+ s390_mvc (p, sizeof(long long), STK_BASE, stack_par_pos, ARG_BASE, STKARG);
+ stack_par_pos += 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 += sizeof(float);
+ }
+ break;
+ case MONO_TYPE_R8:
+ if (fr < FLOAT_REGS) {
+ s390_ld (p, s390_r0 + fr, ARG_BASE, STKARG);
+ fr++;
+ } else {
+ *(guint32 *) p += 7;
+ *(guint32 *) p &= ~7;
+ s390_mvc (p, sizeof(double), STK_BASE, stack_par_pos, ARG_BASE, STKARG);
+ stack_par_pos += 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 = g_malloc (code_size + PAGESIZE - 1);
+
+ /* Align to a multiple of PAGESIZE, assumed to be a power of two */
+ p = (char *)(((int) p + PAGESIZE-1) & ~(PAGESIZE-1));
+#else
+ p = 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);
+
+ /* get return value */
+ if (sig->ret->byref || string_ctor) {
+ s390_st (p, s390_r2, s390_r8, 0);
+ } else {
+ simpletype = 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 = 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 = code_buffer = alloc_code_memory (code_size);
+ p = emit_prolog (p, sig, stack_size);
+ p = emit_save_parameters (p, sig, stack_size);
+ p = emit_call_and_store_retval (p, sig, stack_size, string_ctor);
+ p = 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.
+ *
+ * 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
+ *
+ */
+void *
+mono_create_method_pointer (MonoMethod *method)
+{
+ MonoMethodSignature *sig;
+ MonoJitInfo *ji;
+ guint8 *p, *code_buffer;
+ guint i, align = 0, code_size, stack_size,
+ stackval_arg_pos, local_pos,
+ local_start, reg_param, stack_param,
+ this_flag;
+ guint32 simpletype;
+ int *vtbuf, cpos, vt_cur;
+
+ code_size = 1024;
+ stack_size = 1024;
+ stack_param = 0;
+
+ sig = method->signature;
+
+ p = code_buffer = 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 = local_pos = MINV_POS +
+ 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 = 1;
+ } else if (sig->param_count) {
+ DEBUG (printf ("save r%d\n", 3));
+ s390_st (p, s390_r2, s390_r15, local_pos);
+ local_pos += sizeof(int);
+ reg_param = 0;
+ }
+
+ this_flag = (sig->hasthis ? 1 : 0);
+ if (sig->param_count) {
+ gint save_count = MAX (3, MIN (6, sig->param_count - 1));
+ for (i = reg_param; i < save_count; i ++) {
+ s390_st (p, s390_r3 + i, s390_r15, local_pos);
+ local_pos += sizeof(int);
+ DEBUG (printf ("save r%d\n", 4 + i));
+ }
+ }
+
+ /* prepare space for valuetypes */
+ vt_cur = local_pos;
+ vtbuf = alloca (sizeof(int)*sig->param_count);
+ cpos = 0;
+ for (i = 0; i < sig->param_count; i++) {
+ MonoType *type = sig->params [i];
+ vtbuf [i] = -1;
+ if (type->type == MONO_TYPE_VALUETYPE) {
+ MonoClass *klass = type->data.klass;
+ gint size;
+
+ if (klass->enumtype)
+ continue;
+ size = mono_class_native_size (klass, &align);
+ cpos += align - 1;
+ cpos &= ~(align - 1);
+ vtbuf [i] = cpos;
+ cpos += size;
+ }
+ }
+ cpos += 3;
+ cpos &= ~3;
+
+ local_pos += cpos;
+
+ /* set MonoInvocation::stack_args */
+ stackval_arg_pos = 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 = 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 += 4*mono_type_native_stack_size (sig->params [i], &align);
+ else
+ stackval_arg_pos += 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 = 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 = g_new0 (MonoJitInfo, 1);
+ ji->method = method;
+ ji->code_size = p - code_buffer;
+ ji->code_start = code_buffer;
+
+ mono_jit_info_table_add (mono_root_domain, ji);
+
+ return ji->code_start;
+}
_______________________________________________
Mono-list maillist - Mono-list@ximian.com
http://lists.ximian.com/mailman/listinfo/mono-list
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic