Architectural level set to z10 instruction set
authorNeale Ferguson <neale@sinenomine.net>
Tue, 3 Jun 2014 15:52:00 +0000 (11:52 -0400)
committerNeale Ferguson <neale@sinenomine.net>
Wed, 4 Jun 2014 14:48:43 +0000 (10:48 -0400)
mono/arch/s390x/s390x-codegen.h
mono/mini/cpu-s390x.md
mono/mini/mini-s390x.c
mono/mini/mini-s390x.h
mono/mini/support-s390x.h [new file with mode: 0644]
mono/mini/tramp-s390x.c
mono/utils/mono-hwcap-s390x.c
mono/utils/mono-hwcap-s390x.h

index 3677b2d95b1b8f0f91b0d4517e71590e98bd901a..47e656422ee35c7ad5ab68b519ae43ef1e05ba63 100644 (file)
@@ -6,6 +6,7 @@
 #define S390X_H
 #include <glib.h>
 #include <assert.h>
+#include <limits.h>
 
 #define FLOAT_REGS     2       /* No. float registers for parms    */
 #define GENERAL_REGS   5       /* No. general registers for parms  */
@@ -136,13 +137,16 @@ typedef enum {
        s390_fpc = 256,
 } S390SpecialRegister;
 
-#define s390_is_imm16(val)             ((glong)val >= (glong)-(1<<15) && \
-                                        (glong)val <= (glong)((1<<15)-1))
-#define s390_is_uimm16(val)            ((glong)val >= 0 && (glong)val <= 65535)
+#define s390_is_imm16(val)             ((glong)val >= (glong) SHRT_MIN && \
+                                        (glong)val <= (glong) SHRT_MAX)
+#define s390_is_imm32(val)             ((glong)val >= (glong) INT_MIN && \
+                                        (glong)val <= (glong) INT_MAX)
+#define s390_is_uimm16(val)            ((glong)val >= 0 && (glong)val <= (glong) USHRT_MAX)
+#define s390_is_uimm32(val)            ((glong)val >= 0 && (glong)val <= (glong) UINT_MAX)
 #define s390_is_uimm20(val)            ((glong)val >= 0 && (glong)val <= 1048575)
 #define s390_is_imm20(val)             ((glong)val >= -524288 && (glong)val <= 524287)
-#define s390_is_imm12(val)             ((glong)val >= (glong)-(1<<11) && \
-                                        (glong)val <= (glong)((1<<11)-1))
+#define s390_is_imm12(val)             ((glong)val >= (glong)-4096 && \
+                                        (glong)val <= (glong)4095)
 #define s390_is_uimm12(val)            ((glong)val >= 0 && (glong)val <= 4095)
 
 #define STK_BASE                       s390_r15
@@ -349,7 +353,36 @@ typedef struct {
        short   i2;
        char    xx;
        char    op2;
-} RIE_Format;
+} RIE_Format_1;
+
+typedef struct {
+       char    op1;
+       char    r1 : 4;
+       char    r3 : 4;
+       short   i2;
+       char    m2 : 4;
+       char    xx : 4;
+       char    op2;
+} RIE_Format_2;
+
+typedef struct {
+       char    op1;
+       char    r1 : 4;
+       char    r3 : 4;
+       short   d;
+       char    i;
+       char    op2;
+} RIE_Format_3;
+
+typedef struct {
+       char    op1;
+       char    r1 : 4;
+       char    yy : 4;
+       short   i2;
+       char    m3 : 4;
+       char    xx : 4;
+       char    op2;
+} RIE_Format_4;
 
 typedef struct {
        char    op1;
@@ -427,12 +460,22 @@ typedef struct {
 
 typedef struct {
        short   op;
-       char    b1 : 4;
+       short   tb1 : 4;
        short   d1 : 12;
-       char    b2 : 4;
+       short   b2 : 4;
        short   d2 : 12;
 } __attribute__ ((packed)) SSE_Format;
 
+typedef struct {
+       short   op;
+       char    r3 : 4;
+       char    o2 : 4;
+       short   b1 : 4;
+       short   d1 : 12;
+       short   b2 : 4;
+       short   d2 : 12;
+} __attribute__ ((packed)) SSF_Format;
+
 #define s390_emit16(c, x) do                   \
 {                                              \
        *((guint16 *) c) = (guint16) x;         \
@@ -509,12 +552,33 @@ typedef struct {
 
 #define S390_RI(c,opc,g1,m2)           s390_emit32(c, ((opc >> 4) << 24 | (g1) << 20 | (opc & 0x0f) << 16 | (m2 & 0xffff)))
 
-#define S390_RIE(c,opc,g1,g3,m2) do                            \
+#define S390_RIE_1(c,opc,g1,g3,m2) do                          \
 {                                                              \
        s390_emit16(c, ((opc & 0xff00) | (g1) << 4 | g3));      \
        s390_emit32(c, ((m2) << 16 | (opc & 0xff)));            \
 } while (0)
 
+#define S390_RIE_2(c,opc,g1,g2,m3,v) do                                \
+{                                                              \
+       s390_emit16(c, ((opc & 0xff00) | (g1) << 4 | g3));      \
+       s390_emit16(c, (v));                                    \
+       s390_emit16(c, ((m2) << 12 | (opc & 0xff)));            \
+} while (0)
+
+#define S390_RIE_3(c,opc,g1,i,m3,d) do                         \
+{                                                              \
+       s390_emit16(c, ((opc & 0xff00) | (g1) << 4 | m3));      \
+       s390_emit16(c, (d));                                    \
+       s390_emit16(c, ((i) << 8 | (opc & 0xff)));              \
+} while (0)
+
+#define S390_RIE_4(c,opc,g1,i2,m3) do                          \
+{                                                              \
+       s390_emit16(c, ((opc & 0xff00) | (g1) << 4);            \
+       s390_emit16(c, (i2));                                   \
+       s390_emit16(c, ((m3) << 12 | (opc & 0xff)));            \
+} while (0)
+
 #define S390_RIL_1(c,opc,g1,m2) do                                     \
 {                                                                      \
        s390_emit16(c, ((opc >> 4) << 8 | (g1) << 4 | (opc & 0xf)));    \
@@ -527,6 +591,20 @@ typedef struct {
        s390_emit32(c, m2);                                             \
 } while (0)
 
+#define S390_RIS(c,opc,r,i,m3,b,d) do                          \
+{                                                              \
+       s390_emit16(c, ((opc, & 0xff00) | (r1) << 4) | (r2));   \
+       s390_emit16(c, ((b) << 12) | (d));                      \
+       s390_emit16(c, ((i) << 4) | ((opc) & 0xff));            \
+}
+
+#define S390_RRS(c,opc,r1,r2,m3,b,d) do                                \
+{                                                              \
+       s390_emit16(c, ((opc, & 0xff00) | (r1) << 4) | (r2));   \
+       s390_emit16(c, ((b) << 12) | (d));                      \
+       s390_emit16(c, ((m3) << 12) | ((opc) & 0xff));          \
+}
+
 #define S390_SI(c,opc,s1,p1,m2)                s390_emit32(c, (opc << 24 | (m2) << 16 | (s1) << 12 | ((p1) & 0xfff)));
 
 #define S390_SIY(c,opc,s1,p1,m2) do                            \
@@ -573,23 +651,60 @@ typedef struct {
        s390_emit16(c, ((s2) << 12 | ((p2) & 0xfff)));  \
 } while (0)
 
+#define S390_SSF(c,opc,r3,s1,p1,s2,p2) do                              \
+{                                                                      \
+       s390_emit16(c, (((opc) & 0xff00) << 8) | ((r3) << 4) |          \
+                       ((opc) & 0xf));                                 \
+       s390_emit16(c, ((s1) << 12 | ((p1) & 0xfff)));                  \
+       s390_emit16(c, ((s2) << 12 | ((p2) & 0xfff)));                  \
+} while (0)
+
 #define s390_a(c, r, x, b, d)          S390_RX(c, 0x5a, r, x, b, d)
 #define s390_adb(c, r, x, b, d)                S390_RXE(c, 0xed1a, r, x, b, d)
 #define s390_adbr(c, r1, r2)           S390_RRE(c, 0xb31a, r1, r2)
 #define s390_aebr(c, r1, r2)           S390_RRE(c, 0xb30a, r1, r2)
+#define s390_afi(c, r, v)              S390_RIL_1(c, 0xc29, r, v);
 #define s390_ag(c, r, x, b, d)         S390_RXY(c, 0xe308, r, x, b, d)
 #define s390_agf(c, r, x, b, d)                S390_RXY(c, 0xe318, r, x, b, d)
+#define s390_agfi(c, r, v)             S390_RIL_1(c, 0xc28, r, v)
+#define s390_afgr(c, r1, r2)           S390_RRE(c, 0xb918, r1, r2)
 #define s390_aghi(c, r, v)             S390_RI(c, 0xa7b, r, v)
+#define s390_aghik(c, r, v)            S390_RIE_1(c, 0xecd9, r, v)
 #define s390_agr(c, r1, r2)            S390_RRE(c, 0xb908, r1, r2)
+#define s390_agrk(c, r1, r2, r3)       S390_RRF_1(c, 0xb9e8, r1, r2, r3)
+#define s390_agsi(c, r, v)             S390_SIY(c, 0xeb7a, r v)
+#define s390_ahhhr(c, r1, r2, r3)      S390_RRF_1(c, 0xb9c8, r1, r2, r3)
+#define s390_ahhlr(c, r1, r2, r3)      S390_RRF_1(c, 0xb9d8, r1, r2, r3)
 #define s390_ahi(c, r, v)              S390_RI(c, 0xa7a, r, v)
+#define s390_ahik(c, r, v)             S390_RIE_1(c, 0xecd8, r, v)
+#define s390_ahy(c, r, x, b, d)                S390_RXY(c, 0xe37a, r, b, d)
+#define s390_aih(c, r, v)              S390_RIL_1(c, 0xcc8, r, v)
+#define s390_al(c, r, x, b, d)         S390_RX(c, 0x5e, r, x, b, d)
+#define s390_alc(c, r, x, b, d)                S390_RXY(c, 0xe398, r, x, b, d)
+#define s390_alcg(c, r, x, b, d)       S390_RXY(c, 0xe388, r, x, b, d)
 #define s390_alcgr(c, r1, r2)          S390_RRE(c, 0xb988, r1, r2)
 #define s390_alcr(c, r1, r2)           S390_RRE(c, 0xb998, r1, r2)
-#define s390_al(c, r, x, b, d)         S390_RX(c, 0x5e, r, x, b, d)
+#define s390_alfi(c, r, v)             S390_RIL_1(c, 0xc2b, r, v)
 #define s390_alg(c, r, x, b, d)                S390_RXY(c, 0xe30a, r, x, b, d)
 #define s390_algf(c, r, x, b, d)       S390_RXY(c, 0xe31a, r, x, b, d)
+#define s390_algfi(c, r, v)            S390_RIL_1(c, 0xc2a, r, v)
+#define s390_algfr(c, r1, r2)          S390_RRE(c, 0xb91a, r1, r2)
+#define s390_alghsik(c, r, v)          S390_RIE_1(c, 0xecd8, r, v)
 #define s390_algr(c, r1, r2)           S390_RRE(c, 0xb90a, r1, r2)
+#define s390_algsi(c, r, v)            S390_SIY(c, 0xeb7e, r, v)
+#define s390_alhhhr(c, r1, r2, r3)     S390_RRF_1(c, 0xb9ca, r1, r2, r3)
+#define s390_alhhlr(c, r1, r2, r3)     S390_RRF_1(c, 0xb9da, r1, r2, r3)
+#define s390_alhsik(c, r, v)           S390_RIE_1(c, 0xecda, r, v)
 #define s390_alr(c, r1, r2)            S390_RR(c, 0x1e, r1, r2)
+#define s390_alrk(c, r1, r2)           S390_RRF(c, 0xb9fa, r1, r2)
+#define s390_alsi(c, r, v)             S390_SIY(c, 0xeb6e, r, v)
+#define s390_alsih(c, r, v)            S390_RIL_1(c, 0xcca, r, v)
+#define s390_alsihn(c, r, v)           S390_RIL_1(c, 0xccb, r, v)
+#define s390_aly(c, r, x, b, d)                S390_RXY(c, 0xe35e, r, x, b, d)
 #define s390_ar(c, r1, r2)             S390_RR(c, 0x1a, r1, r2)
+#define s390_ark(c, r1, r2, r3)                S390_RRF_1(c, 0xb9f8, r1, r2, r3)
+#define s390_asi(c, r, v)              S390_SIY(c, 0xeb6a, r, v)
+#define s390_ay(c, r, x, b, d)         S390_RXY(c, 0xe35a, r, x, b, d)
 #define s390_basr(c, r1, r2)           S390_RR(c, 0x0d, r1, r2)
 #define s390_bctr(c, r1, r2)           S390_RR(c, 0x06, r1, r2)
 #define s390_bctrg(c, r1, r2)          S390_RRE(c, 0xb946, r1, r2)
@@ -610,19 +725,46 @@ typedef struct {
 #define s390_cdsg(c, r1, r2, b, d)     S390_RSY_1(c, 0xeb3e, r1, r2, b, d)
 #define s390_cdsy(c, r1, r2, b, d)     S390_RSY_1(c, 0xeb31, r1, r2, b, d)
 #define s390_cebr(c, r1, r2)           S390_RRE(c, 0xb309, r1, r2)
+#define s390_cegbr(c, r1, r2)          S390_RRE(c, 0xb3a4, r1, r2)
 #define s390_cfdbr(c, r1, m, r2)       S390_RRF_2(c, 0xb399, r1, m, r2)
+#define s390_cfi(c, r, v)              S390_RIL_1(c, 0xc2d, r, v)
 #define s390_cgdbr(c, r1, m, r2)       S390_RRF_2(c, 0xb3a9, r1, m, r2)
 #define s390_cg(c, r, x, b, d)         S390_RXY(c, 0xe320, r, x, b, d)
+#define s390_cgfi(c, r, v)             S390_RIL_1(c, 0xc2c, r, v)
+#define s390_cgfrl(c, r, v)            S390_RIL_1(c, 0xc6c, r, v)
 #define s390_cghi(c, r, i)             S390_RI(c, 0xa7f, r, i)
+#define s390_cgib(c, r, i, m, b, d)    S390_RIS(c, 0xecfc, r, i, m, b, d)
+#define s390_cgij(c, r, i, m, d)       S390_RIE_3(c, 0xec7c, r, i, m, d)
+#define s390_cgit(c, r, i, m)          S390_RIE_4(c, 0xec70, r, i m);
 #define s390_cgr(c, r1, r2)            S390_RRE(c, 0xb920, r1, r2)
+#define s390_cgrb(c, r1, r2, m3, b, d) S390_RRS(c, 0xece4, r1, r2, m3, b, d)
+#define s390_cgrj(c, r1, r2, m3, v)    S390_RIE_2(c, 0xec64, r1, r2, m3, v)
+#define s390_cgrl(c, r, v)             S390_RIL_1(c, 0xc68, r, v)
 #define s390_chi(c, r, i)              S390_RI(c, 0xa7e, r, i)
+#define s390_cib(c, r, i, m, b, d)     S390_RIS(c, 0xecfe, r, i, m, b, d)
+#define s390_cij(c, r, i, m, d)                S390_RIE_3(c, 0xec7e, r, i, m, d)
+#define s390_cit(c, r, i, m)           S390_RIE_4(c, 0xec72, r, i m);
 #define s390_cl(c, r, x, b, d)         S390_RX(c, 0x55, r, x, b, d)
 #define s390_clg(c, r, x, b, d)                S390_RXY(c, 0xe321, r, x, b, d)
+#define s390_clgib(c, r, i, m, b, d)   S390_RIS(c, 0xecfd, r, i, m, b, d)
+#define s390_clgij(c, r, i, b)         S390_RIE_3(c, 0xec7d, r, i, m, d)
 #define s390_clgr(c, r1, r2)           S390_RRE(c, 0xb921, r1, r2)
+#define s390_clgrj(c, r1, r2, m, v)    S390_RIE_2(c, 0xec65, r1, r2, m, v)
+#define s390_clgrb(c, r1, r2, m3, b, d)        S390_RRS(c, 0xece5, r1, r2, m3, b, d)
+#define s390_clib(c, r, i, m, b, d)    S390_RIS(c, 0xecff, r, i, m, b, d)
+#define s390_clij(c, r, i, b)          S390_RIE_3(c, 0xec7f, r, i, m, d)
 #define s390_clr(c, r1, r2)            S390_RR(c, 0x15, r1, r2)
+#define s390_clrb(c, r1, r2, m3, b, d) S390_RRS(c, 0xecf7, r1, r2, m3, b, d)
+#define s390_clrj(c, r1, r2, m, v)     S390_RIE_2(c, 0xec77, r1, r2, m, v)
 #define s390_cr(c, r1, r2)             S390_RR(c, 0x19, r1, r2)
+#define s390_crb(c, r1, r2, m3, b, d)  S390_RRS(c, 0xecf6, r1, r2, m3, b, d)
+#define s390_crj(c, r1, r2, m3, v)     S390_RIE_2(c, 0xec76, r1, r2, m3, v)
+#define s390_crl(c, r, v)              S390_RIL_1(c, 0xc6d, r, v)
+#define s390_crt(c, r1, r2, m3)                S390_RRF_2(c, 0xb972, r1, r2, m3);
+#define s390_cgrt(c, r1, r2, m3)       S390_RRF_2(c, 0xb960, r1, r2, m3);
 #define s390_cs(c, r1, r2, b, d)       S390_RX(c, 0xba, r1, r2, b, d)
 #define s390_csg(c, r1, r2, b, d)      S390_RSY_1(c, 0xeb30, r1, r2, b, d)
+#define s390_csst(c, d1, b1, d2, b2, r)        S390_SSF(c, 0xc82, b1, d1, b2, d2, r)
 #define s390_csy(c, r1, r2, b, d)      S390_RSY_1(c, 0xeb14, r1, r2, b, d)
 #define s390_ddbr(c, r1, r2)           S390_RRE(c, 0xb31d, r1, r2)
 #define s390_debr(c, r1, r2)           S390_RRE(c, 0xb30d, r1, r2)
@@ -637,6 +779,12 @@ typedef struct {
 #define s390_icm(c, r, m, b, d)                S390_RX(c, 0xbf, r, m, b, d)
 #define s390_icmy(c, r, x, b, d)       S390_RXY(c, 0xeb81, r, x, b, d)
 #define s390_icy(c, r, x, b, d)                S390_RXY(c, 0xe373, r, x, b, d)
+#define s390_iihf(c, r, v)             S390_RIL_1(c, 0xc08, r, v)
+#define s390_iihh(c, r, v)             S390_RI(c, 0xa50, r, v)
+#define s390_iihl(c, r, v)             S390_RI(c, 0xa51, r, v)
+#define s390_iilf(c, r, v)             S390_RIL_1(c, 0xc09, r, v)
+#define s390_iilh(c, r, v)             S390_RI(c, 0xa52, r, v)
+#define s390_iill(c, r, v)             S390_RI(c, 0xa53, r, v)
 #define s390_j(c,d)                    s390_brc(c, S390_CC_UN, d)
 #define s390_jc(c, m, d)               s390_brc(c, m, d)
 #define s390_jcl(c, m, d)              s390_brcl(c, m, d)
@@ -690,23 +838,28 @@ typedef struct {
 #define s390_ldy(c, r, x, b, d)                S390_RXY(c, 0xed65, r, x, b, d)
 #define s390_ldeb(c, r, x, b, d)       S390_RXE(c, 0xed04, r, x, b, d)
 #define s390_ldebr(c, r1, r2)          S390_RRE(c, 0xb304, r1, r2)
+#define s390_ldgr(c, r1, r2)           S390_RRE(c, 0xb3c1, r1, r2)
 #define s390_ldr(c, r1, r2)            S390_RR(c, 0x28, r1, r2)
 #define s390_le(c, f, x, b, d)         S390_RX(c, 0x78, f, x, b, d)
 #define s390_ledbr(c, r1, r2)          S390_RRE(c, 0xb344, r1, r2)
 #define s390_ler(c, r1, r2)            S390_RR(c, 0x38, r1, r2)
 #define s390_ley(c, r, x, b, d)                S390_RXY(c, 0xed64, r, x, b, d)
+#define s390_lg(c, r, x, b, d)         S390_RXY(c, 0xe304, r, x, b, d)
 #define s390_lgb(c, r, x, b, d)                S390_RXY(c, 0xe377, r, x, b, d)
 #define s390_lgbr(c, r1, r2)           S390_RRE(c, 0xb906, r1, r2)
-#define s390_lg(c, r, x, b, d)         S390_RXY(c, 0xe304, r, x, b, d)
+#define s390_lgdr(c, r1, r2)           S390_RRE(c, 0xb3cd, r1, r2)
 #define s390_lgf(c, r, x, b, d)                S390_RXY(c, 0xe314, r, x, b, d)
+#define s390_lgfi(c, r, v)             S390_RIL_1(c, 0xc01, r, v)
+#define s390_lgfrl(c, r1, d)           S390_RIL_1(c, 0xc4c, r1, d)
 #define s390_lgfr(c, r1, r2)           S390_RRE(c, 0xb914, r1, r2)
 #define s390_lgh(c, r, x, b, d)                S390_RXY(c, 0xe315, r, x, b, d)
 #define s390_lghi(c, r, v)             S390_RI(c, 0xa79, r, v)
+#define s390_lghr(c, r1, r2)           S390_RRE(c, 0xb907, r1, r2)
 #define s390_lgr(c, r1, r2)            S390_RRE(c, 0xb904, r1, r2)
+#define s390_lgrl(c, r1, d)            S390_RIL_1(c, 0xc48, r1, d)
 #define s390_lh(c, r, x, b, d)         S390_RX(c, 0x48, r, x, b, d)
 #define s390_lhr(c, r1, r2)            S390_RRE(c, 0xb927, r1, r2)
 #define s390_lhg(c, r, x, b, d)                S390_RXY(c, 0xe315, r, x, b, d)
-#define s390_lghr(c, r1, r2)           S390_RRE(c, 0xb907, r1, r2)
 #define s390_lhi(c, r, v)              S390_RI(c, 0xa78, r, v)
 #define s390_lhy(c, r, x, b, d)                S390_RXY(c, 0xe378, r, x, b, d)
 #define s390_llcr(c, r1, r2)           S390_RRE(c, 0xb994, r1, r2)
@@ -717,6 +870,12 @@ typedef struct {
 #define s390_llgh(c, r, x, b, d)       S390_RXY(c, 0xe391, r, x, b, d)
 #define s390_llghr(c, r1, r2)          S390_RRE(c, 0xb985, r1, r2)
 #define s390_llhr(c, r1, r2)           S390_RRE(c, 0xb995, r1, r2)
+#define s390_llihf(c, r, v)            S390_RIL_1(c, 0xc0e, r, v)
+#define s390_llihh(c, r, v)            S390_RI(c, 0xa5c, r, v)
+#define s390_llihl(c, r, v)            S390_RI(c, 0xa5d, r, v)
+#define s390_llilf(c, r, v)            S390_RIL_1(c, 0xc0f, r, v)
+#define s390_llilh(c, r, v)            S390_RI(c, 0xa5e, r, v)
+#define s390_llill(c, r, v)            S390_RI(c, 0xa5f, r, v)
 #define s390_lm(c, r1, r2, b, d)       S390_RS_1(c, 0x98, r1, r2, b, d)
 #define s390_lmg(c, r1, r2, b, d)      S390_RSY_1(c, 0xeb04, r1, r2, b, d)
 #define s390_lndbr(c, r1, r2)          S390_RRE(c, 0xb311, r1, r2)
@@ -726,6 +885,7 @@ typedef struct {
 #define s390_lpgr(c, r1, r2)           S390_RRE(c, 0xb900, r1, r2)
 #define s390_lpr(c, r1, r2)            S390_RR(c, 0x10, r1, r2)
 #define s390_lr(c, r1, r2)             S390_RR(c, 0x18, r1, r2)
+#define s390_lrl(c, r1, d)             S390_RIL_1(c, 0xc4d, r1, d)
 #define s390_ltgfr(c, r1, r2)          S390_RRE(c, 0xb912, r1, r2)
 #define s390_ltgr(c, r1, r2)           S390_RRE(c, 0xb902, r1, r2)
 #define s390_ltr(c, r1, r2)            S390_RR(c, 0x12, r1, r2)
@@ -734,24 +894,44 @@ typedef struct {
 #define s390_m(c, r, x, b, d)          S390_RX(c, 0x5c, r, x, b, d)
 #define s390_mdbr(c, r1, r2)           S390_RRE(c, 0xb31c, r1, r2)
 #define s390_meebr(c, r1, r2)          S390_RRE(c, 0xb317, r1, r2)
+#define s390_mfy(c, r, x, b, d)                S390_RXY(c, 0xe35c, r, x, b, d)
 #define s390_mlgr(c, r1, r2)           S390_RRE(c, 0xb986, r1, r2)
 #define s390_mlr(c, r1, r2)            S390_RRE(c, 0xb996, r1, r2)
 #define s390_mr(c, r1, r2)             S390_RR(c, 0x1c, r1, r2)
 #define s390_ms(c, r, x, b, d)         S390_RX(c, 0x71, r, x, b, d)
+#define s390_msi(c, r, v)              S390_RIL_1(c, 0xc21, r, v)
 #define s390_msgfr(c, r1, r2)          S390_RRE(c, 0xb91c, r1, r2)
+#define s390_msgi(c, r, v)             S390_RIL_1(c, 0xc20, r, v)
 #define s390_msgr(c, r1, r2)           S390_RRE(c, 0xb90c, r1, r2)
 #define s390_msr(c, r1, r2)            S390_RRE(c, 0xb252, r1, r2)
 #define s390_mvc(c, l, b1, d1, b2, d2) S390_SS_1(c, 0xd2, l, b1, d1, b2, d2)
 #define s390_mvcl(c, r1, r2)           S390_RR(c, 0x0e, r1, r2)
 #define s390_mvcle(c, r1, r3, d2, b2)  S390_RS_1(c, 0xa8, r1, r3, d2, b2)
 #define s390_n(c, r, x, b, d)          S390_RX(c, 0x54, r, x, b, d)
+#define s390_nc(c, l, b1, d1, b2, d2)  S390_SS_1(c, 0xd4, l, b1, d1, b2, d2)
 #define s390_ng(c, r, x, b, d)         S390_RXY(c, 0xe380, r, x, b, d)
 #define s390_ngr(c, r1, r2)            S390_RRE(c, 0xb980, r1, r2)
+#define s390_ngrk(c, r1, r2, r3)       S390_RRF_1(c, 0xb9e4, r1, r2, r3)
+#define s390_ni(c, b, d, v)            S390_SI(c, 0x94, b, d, v) 
+#define s390_nihf(c, r, v)             S390_RIL_1(c, 0xc0a, r, v)
+#define s390_nihh(c, r, v)             S390_RI(c, 0xa54, r, v)
+#define s390_nihl(c, r, v)             S390_RI(c, 0xa55, r, v)
+#define s390_nilf(c, r, v)             S390_RIL_1(c, 0xc0b, r, v)
 #define s390_nilh(c, r, v)             S390_RI(c, 0xa56, r, v)
 #define s390_nill(c, r, v)             S390_RI(c, 0xa57, r, v)
+#define s390_niy(c, b, d, v)           S390_SIY(c, 0xeb54, b, d, v) 
 #define s390_nop(c)                    S390_RR(c, 0x07, 0x0, 0)
 #define s390_nr(c, r1, r2)             S390_RR(c, 0x14, r1, r2)
+#define s390_nrk(c, r1, r2)            S390_RRF_1(c, 0xb9f4, r1, r2)
+#define s390_ny(c, r, x, b, d)         S390_RRY(c, 0xe354, r1, r2)
 #define s390_o(c, r, x, b, d)          S390_RX(c, 0x56, r, x, b, d)
+#define s390_oihf(c, r, v)             S390_RIL_1(c, 0xc0c, r, v)
+#define s390_oihh(c, r, v)             S390_RI(c, 0xa58, r, v)
+#define s390_oihl(c, r, v)             S390_RI(c, 0xa59, r, v)
+#define s390_oilf(c, r, v)             S390_RIL_1(c, 0xc0d, r, v)
+#define s390_oilh(c, r, v)             S390_RI(c, 0xa5a, r, v)
+#define s390_oill(c, r, v)             S390_RI(c, 0xa5b` r, v)
+#define s390_oiy(c, b, d, v)           S390_SIY(c, 0xeb56 b, d, v) 
 #define s390_og(c, r, x, b, d)         S390_RXY(c, 0xe381, r, x, b, d)
 #define s390_ogr(c, r1, r2)            S390_RRE(c, 0xb981, r1, r2)
 #define s390_or(c, r1, r2)             S390_RR(c, 0x16, r1, r2)
@@ -762,16 +942,19 @@ typedef struct {
 #define s390_sg(c, r, x, b, d)         S390_RXY(c, 0xe309, r, x, b, d)
 #define s390_sgf(c, r, x, b, d)                S390_RXY(c, 0xe319, r, x, b, d)
 #define s390_sgr(c, r1, r2)            S390_RRE(c, 0xb909, r1, r2)
+#define s390_sl(c, r, x, b, d)         S390_RX(c, 0x5f, r, x, b, d)
 #define s390_sla(c, r, b, d)           S390_RS_3(c, 0x8b, r, b, d) 
 #define s390_slag(c, r1, r2, b, d)     S390_RSY_1(c, 0xeb0b, r1, r2, b, d) 
 #define s390_slbg(c, r, x, b, d)       S390_RXY(c, 0xe389, r, x, b, d)
 #define s390_slbgr(c, r1, r2)          S390_RRE(c, 0xb989, r1, r2)
 #define s390_slbr(c, r1, r2)           S390_RRE(c, 0xb999, r1, r2)
-#define s390_sl(c, r, x, b, d)         S390_RX(c, 0x5f, r, x, b, d)
 #define s390_slda(c, r, b, d)          S390_RS_3(c, 0x8f, r, b, d) 
 #define s390_sldl(c, r, b, d)          S390_RS_3(c, 0x8d, r, b, d) 
+#define s390_slfi(c, r, v)             S390_RIL_1(c, 0xc25, r, v)
 #define s390_slg(c, r, x, b, d)                S390_RXY(c, 0xe30b, r, x, b, d)
 #define s390_slgf(c, r, x, b, d)       S390_RXY(c, 0xe31b, r, x, b, d)
+#define s390_slgfr(c, r1, r2)          S390_RRE(c, 0xb91b, r1, r2)
+#define s390_slgfi(c, r, v)            S390_RIL_1(c, 0xc24, r, v)
 #define s390_slgr(c, r1, r2)           S390_RRE(c, 0xb90b, r1, r2)
 #define s390_sll(c, r, b, d)           S390_RS_3(c, 0x89, r, b, d) 
 #define s390_sllg(c, r1, r2, b, d)     S390_RSY_1(c, 0xeb0d, r1, r2, b, d) 
@@ -805,7 +988,10 @@ typedef struct {
 #define s390_tcdb(c, r, x, b, d)       S390_RXE(c, 0xed11, r, x, b, d)
 #define s390_tceb(c, r, x, b, d)       S390_RXE(c, 0xed10, r, x, b, d)
 #define s390_x(c, r, x, b, d)          S390_RX(c, 0x57, r, x, b, d)
+#define s390_xihf(c, r, v)             S390_RIL_1(c, 0xc06, r, v)
+#define s390_xilf(c, r, v)             S390_RIL_1(c, 0xc07, r, v)
 #define s390_xg(c, r, x, b, d)         S390_RXY(c, 0xe382, r, x, b, d)
 #define s390_xgr(c, r1, r2)            S390_RRE(c, 0xb982, r1, r2)
 #define s390_xr(c, r1, r2)             S390_RR(c, 0x17, r1, r2)
+#define s390_xy(c, r, x, b, d)         S390_RXY(c, 0xe357, r, x, b, d)
 #endif
index be6a3509d1d1f13c5e8a88a455ecdc80d2f8717e..34b6cdb271e5ba8dfde63d48e688483a9595f166 100644 (file)
@@ -118,11 +118,11 @@ float_conv_to_i2: dest:i src1:f len:50
 float_conv_to_i4: dest:i src1:f len:50
 float_conv_to_i8: dest:l src1:f len:50
 float_conv_to_i: dest:i src1:f len:52
-float_conv_to_r4: dest:f src1:f len:4
-float_conv_to_u1: dest:i src1:f len:66
-float_conv_to_u2: dest:i src1:f len:66
-float_conv_to_u4: dest:i src1:f len:66
-float_conv_to_u8: dest:i src1:f len:66
+float_conv_to_r4: dest:f src1:f len:8
+float_conv_to_u1: dest:i src1:f len:72
+float_conv_to_u2: dest:i src1:f len:72
+float_conv_to_u4: dest:i src1:f len:72
+float_conv_to_u8: dest:i src1:f len:72
 float_conv_to_u: dest:i src1:f len:36
 float_div: dest:f src1:f src2:f len:6
 float_div_un: dest:f src1:f src2:f len:6
@@ -135,27 +135,25 @@ float_sub: dest:f src1:f src2:f len:6
 fmove: dest:f src1:f len:4
 i8const: dest:i len:20
 icompare: src1:i src2:i len:4
-icompare_imm: src1:i len:14
+icompare_imm: src1:i len:18
 iconst: dest:i len:40
-
-
 jmp: len:46
 label: len:0
 lcall: dest:o len:22 clob:c
 lcall_membase: dest:o src1:b len:12 clob:c
 lcall_reg: dest:o src1:i len:8 clob:c
 lcompare: src1:i src2:i len:4
-load_membase: dest:i src1:b len:26
+load_membase: dest:i src1:b len:30
 loadi1_membase: dest:i src1:b len:40
-loadi2_membase: dest:i src1:b len:26
-loadi4_membase: dest:i src1:b len:26
-loadi8_membase: dest:i src1:b len:26
+loadi2_membase: dest:i src1:b len:30
+loadi4_membase: dest:i src1:b len:30
+loadi8_membase: dest:i src1:b len:30
 loadr4_membase: dest:f src1:b len:28
 loadr8_membase: dest:f src1:b len:28
-loadu1_membase: dest:i src1:b len:26
-loadu2_membase: dest:i src1:b len:26
+loadu1_membase: dest:i src1:b len:30
+loadu2_membase: dest:i src1:b len:30
 loadu4_mem: dest:i len:8
-loadu4_membase: dest:i src1:b len:26
+loadu4_membase: dest:i src1:b len:30
 localloc: dest:i src1:i len:106
 memory_barrier: len: 10
 move: dest:i src1:i len:4
index 5374adc8b029f1c637417f777d1560339a3186e2..5d88174bac187c506c946cae96bdcc4604cd040d 100644 (file)
@@ -59,7 +59,7 @@ if (ins->inst_target_bb->native_offset) {                                     \
 #define EMIT_COND_SYSTEM_EXCEPTION(cond,exc_name)                      \
         do {                                                           \
                mono_add_patch_info (cfg, code - cfg->native_code,      \
-                                   MONO_PATCH_INFO_EXC, exc_name);     \
+                                    MONO_PATCH_INFO_EXC, exc_name);    \
                s390_jcl (code, cond, 0);                               \
        } while (0); 
 
@@ -257,6 +257,8 @@ if (ins->inst_target_bb->native_offset) {                                   \
 
 #include "mini.h"
 #include <string.h>
+#include <sys/types.h>
+#include <unistd.h>
 
 #include <mono/metadata/appdomain.h>
 #include <mono/metadata/debug-helpers.h>
@@ -267,6 +269,7 @@ if (ins->inst_target_bb->native_offset) {                                   \
 
 #include "mini-s390x.h"
 #include "cpu-s390x.h"
+#include "support-s390x.h"
 #include "jit-icalls.h"
 #include "ir-emit.h"
 #include "trace.h"
@@ -381,7 +384,7 @@ static __inline__ void emit_unwind_regs(MonoCompile *, guint8 *, int, int, long)
 
 int mono_exc_esp_offset = 0;
 
-static int indent_level = 0;
+__thread int indent_level = 0;
 
 static gint appdomain_tls_offset = -1,
            lmf_tls_offset = -1,
@@ -393,14 +396,6 @@ gboolean lmf_addr_key_inited = FALSE;
 
 facilityList_t facs;
 
-#if 0
-
-extern __thread MonoDomain *tls_appdomain;
-extern __thread MonoThread *tls_current_object;
-extern __thread gpointer   mono_lmf_addr;
-               
-#endif
-
 /*
  * The code generated for sequence points reads from this location, 
  * which is made read-only when single stepping is enabled.
@@ -626,7 +621,7 @@ indent (int diff) {
        if (diff < 0)
                indent_level += diff;
        v = indent_level;
-       printf("[%3d] ",v);
+       printf("%p [%3d] ",pthread_self(),v);
        while (v-- > 0) {
                printf (". ");
        }
@@ -1262,21 +1257,6 @@ mono_arch_init (void)
 {
        guint8 *code;
 
-#if 0
-       /*
-        * When we do an architectural level set at z9 or better 
-        * we can use the STFLE instruction to show us
-        * what hardware facilities are available
-        */
-       int lFacility = sizeof(facs) % 8;
-
-       memset((char *) &facs, 0, sizeof(facs));
-
-       __asm__ ("      lgfr    0,%1\n"
-                "      stfle   %0\n"
-                : "=m" (facs) : "r" (lFacility) : "0", "cc");
-#endif
-
        ss_trigger_page = mono_valloc (NULL, mono_pagesize (), MONO_MMAP_READ);
        bp_trigger_page = mono_valloc (NULL, mono_pagesize (), MONO_MMAP_READ);
        mono_mprotect (bp_trigger_page, mono_pagesize (), 0);
@@ -2608,54 +2588,23 @@ mono_arch_instrument_prolog (MonoCompile *cfg, void *func, void *p,
        if (cfg->method->save_lmf)
                parmOffset -= sizeof(MonoLMF);
        fpOffset   = parmOffset + (5*sizeof(gpointer));
-       if ((!mono_hwcap_s390x_has_ld) && (fpOffset > 4096)) {
-               s390_lgr (code, s390_r12, STK_BASE);
-               baseReg = s390_r12;
-               while (fpOffset > 4096) {
-                       s390_aghi (code, baseReg, 4096);
-                       fpOffset   -= 4096;
-                       parmOffset -= 4096;
-               }
-       } else {
-               baseReg = STK_BASE;
-       }       
+       baseReg = STK_BASE;
 
        s390_stmg (code, s390_r2, s390_r6, STK_BASE, parmOffset);
-       if (mono_hwcap_s390x_has_ld) {
-               s390_stdy (code, s390_f0, 0, STK_BASE, fpOffset);
-               s390_stdy (code, s390_f2, 0, STK_BASE, fpOffset+sizeof(gdouble));
-               s390_stdy (code, s390_f4, 0, STK_BASE, fpOffset+2*sizeof(gdouble));
-               s390_stdy (code, s390_f6, 0, STK_BASE, fpOffset+3*sizeof(gdouble));
-       } else {
-               s390_std  (code, s390_f0, 0, baseReg, fpOffset);
-               s390_std  (code, s390_f2, 0, baseReg, fpOffset+sizeof(gdouble));
-               s390_std  (code, s390_f4, 0, baseReg, fpOffset+2*sizeof(gdouble));
-               s390_std  (code, s390_f6, 0, baseReg, fpOffset+3*sizeof(gdouble));
-       }
-       s390_basr (code, s390_r13, 0);
-       s390_j    (code, 10);
-       s390_llong(code, cfg->method);
-       s390_llong(code, func);
-       s390_lg   (code, s390_r2, 0, s390_r13, 4);
-       if (mono_hwcap_s390x_has_ld)
-               s390_lay  (code, s390_r3, 0, STK_BASE, parmOffset);
-       else
-               s390_la   (code, s390_r3, 0, baseReg, parmOffset);
+       s390_stdy (code, s390_f0, 0, STK_BASE, fpOffset);
+       s390_stdy (code, s390_f2, 0, STK_BASE, fpOffset+sizeof(gdouble));
+       s390_stdy (code, s390_f4, 0, STK_BASE, fpOffset+2*sizeof(gdouble));
+       s390_stdy (code, s390_f6, 0, STK_BASE, fpOffset+3*sizeof(gdouble));
+       S390_SET  (code, s390_r1, func);
+       S390_SET  (code, s390_r2, cfg->method);
+       s390_lay  (code, s390_r3, 0, STK_BASE, parmOffset);
        s390_lgr  (code, s390_r4, STK_BASE);
        s390_aghi (code, s390_r4, cfg->stack_usage);
-       s390_lg   (code, s390_r1, 0, s390_r13, 12);
        s390_basr (code, s390_r14, s390_r1);
-       if (mono_hwcap_s390x_has_ld) {
-               s390_ldy  (code, s390_f6, 0, STK_BASE, fpOffset+3*sizeof(gdouble));
-               s390_ldy  (code, s390_f4, 0, STK_BASE, fpOffset+2*sizeof(gdouble));
-               s390_ldy  (code, s390_f2, 0, STK_BASE, fpOffset+sizeof(gdouble));
-               s390_ldy  (code, s390_f0, 0, STK_BASE, fpOffset);
-       } else {
-               s390_ld   (code, s390_f6, 0, baseReg, fpOffset+3*sizeof(gdouble));
-               s390_ld   (code, s390_f4, 0, baseReg, fpOffset+2*sizeof(gdouble));
-               s390_ld   (code, s390_f2, 0, baseReg, fpOffset+sizeof(gdouble));
-               s390_ld   (code, s390_f0, 0, baseReg, fpOffset);
-       }
+       s390_ldy  (code, s390_f6, 0, STK_BASE, fpOffset+3*sizeof(gdouble));
+       s390_ldy  (code, s390_f4, 0, STK_BASE, fpOffset+2*sizeof(gdouble));
+       s390_ldy  (code, s390_f2, 0, STK_BASE, fpOffset+sizeof(gdouble));
+       s390_ldy  (code, s390_f0, 0, STK_BASE, fpOffset);
        s390_lmg  (code, s390_r2, s390_r6, STK_BASE, parmOffset);
 
        return code;
@@ -2756,12 +2705,8 @@ handle_enum:
                break;
        }
 
-       s390_basr (code, s390_r13, 0);
-       s390_j    (code, 10);
-       s390_llong(code, cfg->method);
-       s390_llong(code, func);
-       s390_lg   (code, s390_r2, 0, s390_r13, 4);
-       s390_lg   (code, s390_r1, 0, s390_r13, 12);
+       S390_SET  (code, s390_r1, func);
+       S390_SET  (code, s390_r2, cfg->method);
        s390_basr (code, s390_r14, s390_r1);
 
        switch (save_mode) {
@@ -2890,14 +2835,14 @@ emit_float_to_int (MonoCompile *cfg, guchar *code, int dreg, int sreg, int size,
                }
        } else {
                short *o[1];
-               s390_basr   (code, s390_r13, 0);
-               s390_j      (code, 10);
-               s390_llong  (code, 0x41e0000000000000llu);
-               s390_llong  (code, 0x41f0000000000000llu);
+               S390_SET    (code, s390_r13, 0x41e0000000000000llu);
+               s390_ldgr   (code, s390_f14, s390_r13);
                s390_ldr    (code, s390_f15, sreg);
-               s390_cdb    (code, s390_f15, 0, s390_r13, 4);
+               s390_cdbr   (code, s390_f15, s390_f14);
                s390_jl     (code, 0); CODEPTR (code, o[0]);
-               s390_sdb    (code, s390_f15, 0, s390_r13, 12);
+               S390_SET    (code, s390_r13, 0x41f0000000000000llu);
+               s390_ldgr   (code, s390_f14, s390_r13);
+               s390_sdbr   (code, s390_f15, s390_f14);
                s390_cfdbr  (code, dreg, 7, s390_f15);
                s390_j      (code, 4);
                PTRSLOT (code, o[0]);
@@ -3017,28 +2962,14 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                }
                        break;
                case OP_STOREI4_MEMBASE_IMM: {
-                       if (s390_is_imm16(ins->inst_imm)) {
-                               s390_lghi (code, s390_r0, ins->inst_imm);
-                       } else {
-                               s390_basr (code, s390_r13, 0);
-                               s390_j    (code, 6);
-                               s390_llong(code, ins->inst_imm);
-                               s390_lg   (code, s390_r0, 0, s390_r13, 4);
-                       }
+                       s390_lgfi (code, s390_r0, ins->inst_imm);
                        S390_LONG (code, sty, st, s390_r0, 0, 
                                   ins->inst_destbasereg, ins->inst_offset);
                }
                        break;
                case OP_STORE_MEMBASE_IMM:
                case OP_STOREI8_MEMBASE_IMM: {
-                       if (s390_is_imm16(ins->inst_imm)) {
-                               s390_lghi (code, s390_r0, ins->inst_imm);
-                       } else {
-                               s390_basr (code, s390_r13, 0);
-                               s390_j    (code, 6);
-                               s390_llong(code, ins->inst_imm);
-                               s390_lg   (code, s390_r0, 0, s390_r13, 4);
-                       }
+                       S390_SET (code, s390_r0, ins->inst_imm);
                        S390_LONG (code, stg, stg, s390_r0, 0, 
                                   ins->inst_destbasereg, ins->inst_offset);
                }
@@ -3104,90 +3035,35 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                }
                        break;
                case OP_LCONV_TO_I1: {
-#if 0
                        s390_lgbr (code, ins->dreg, ins->sreg1);
-#else
-                       s390_sllg (code, ins->dreg, ins->sreg1, 0, 56);
-                       s390_srag (code, ins->dreg, ins->dreg, 0, 56);
-#endif
                }
                        break;
                case OP_LCONV_TO_I2: {
-#if 0
                        s390_lghr (code, ins->dreg, ins->sreg1);
-#else
-                       s390_sllg (code, ins->dreg, ins->sreg1, 0, 48);
-                       s390_srag (code, ins->dreg, ins->dreg, 0, 48);
-#endif
                }
                        break;
                case OP_LCONV_TO_U1: {
-#if 0
-                       s390_llghr (code, ins->dreg, ins->sreg1);
-#else
-                       if (ins->dreg != ins->sreg1)
-                               s390_lgr  (code, ins->dreg, ins->sreg1);
-                       s390_lghi  (code, s390_r0, 0xff);
-                       s390_ngr   (code, ins->dreg, s390_r0);
-#endif
+                       s390_llgcr (code, ins->dreg, ins->sreg1);
                }
                        break;
                case OP_LCONV_TO_U2: {
-#if 0
                        s390_llghr (code, ins->dreg, ins->sreg1);
-#else
-                       if (ins->dreg != ins->sreg1)
-                               s390_lgr  (code, ins->dreg, ins->sreg1);
-                       s390_lghi  (code, s390_r0, -1);
-                       s390_srlg  (code, s390_r0, s390_r0, 0, 48);
-                       s390_ngr   (code, ins->dreg, s390_r0);
-#endif
                }
                        break;
                case OP_ICONV_TO_I1: {
-#if 0
-                       s390_lbr  (code, ins->dreg, ins->sreg1);
-#else
-                       if (ins->dreg != ins->sreg1)
-                               s390_lr  (code, ins->dreg, ins->sreg1);
-                       s390_sll (code, ins->dreg, 0, 24);
-                       s390_sra (code, ins->dreg, 0, 24);
-                       
-#endif
+                       s390_lgbr  (code, ins->dreg, ins->sreg1);
                }
                        break;
                case OP_ICONV_TO_I2: {
-#if 0
-                       s390_lhr  (code, ins->dreg, ins->sreg1);
-#else
-                       if (ins->dreg != ins->sreg1)
-                               s390_lr  (code, ins->dreg, ins->sreg1);
-                       s390_sll (code, ins->dreg, 0, 16);
-                       s390_sra (code, ins->dreg, 0, 16);
-#endif
+                       s390_lghr  (code, ins->dreg, ins->sreg1);
                }
                        break;
                case OP_ICONV_TO_U1: {
-#if 0
-                       s390_llcr (code, ins->dreg, ins->sreg1);
-#else
-                       if (ins->dreg != ins->sreg1)
-                               s390_lr  (code, ins->dreg, ins->sreg1);
-                       s390_lhi  (code, s390_r0, 0xff);
-                       s390_nr   (code, ins->dreg, s390_r0);
-#endif
+                       s390_llgcr (code, ins->dreg, ins->sreg1);
                }
                        break;
                case OP_ICONV_TO_U2: {
-#if 0
-                       s390_llhr (code, ins->dreg, ins->sreg1);
-#else
-                       if (ins->dreg != ins->sreg1)
-                               s390_lr  (code, ins->dreg, ins->sreg1);
-                       s390_lhi  (code, s390_r0, -1);
-                       s390_srl  (code, s390_r0, 0, 16);
-                       s390_nr   (code, ins->dreg, s390_r0);
-#endif
+                       s390_llghr (code, ins->dreg, ins->sreg1);
                }
                        break;
                case OP_COMPARE: 
@@ -3207,50 +3083,25 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        break;
                case OP_COMPARE_IMM:
                case OP_LCOMPARE_IMM: {
-                       if (s390_is_imm16 (ins->inst_imm)) {
-                               s390_lghi (code, s390_r0, ins->inst_imm);
-                               if (is_unsigned (ins->next))
-                                       s390_clgr (code, ins->sreg1, s390_r0);
-                               else
-                                       s390_cgr  (code, ins->sreg1, s390_r0);
-                       } else {
-                               s390_basr (code, s390_r13, 0);
-                               s390_j    (code, 6);
-                               s390_llong(code, ins->inst_imm);
-                               if (is_unsigned (ins->next))
-                                       s390_clg  (code, ins->sreg1, 0, s390_r13, 4);
-                               else
-                                       s390_cg   (code, ins->sreg1, 0, s390_r13, 4);
-                       }
+                       S390_SET (code, s390_r0, ins->inst_imm);
+                       if (is_unsigned (ins->next))
+                               s390_clgr (code, ins->sreg1, s390_r0);
+                       else
+                               s390_cgr  (code, ins->sreg1, s390_r0);
                }
                        break;
                case OP_ICOMPARE_IMM: {
-                       if (s390_is_imm16 (ins->inst_imm)) {
-                               s390_lghi (code, s390_r0, ins->inst_imm);
-                               if (is_unsigned (ins->next))
-                                       s390_clr  (code, ins->sreg1, s390_r0);
-                               else
-                                       s390_cr   (code, ins->sreg1, s390_r0);
-                       }
-                       else {
-                               s390_basr (code, s390_r13, 0);
-                               s390_j    (code, 4);
-                               s390_word (code, ins->inst_imm);
-                               if (is_unsigned (ins->next))
-                                       s390_cl  (code, ins->sreg1, 0, s390_r13, 4);
-                               else
-                                       s390_c   (code, ins->sreg1, 0, s390_r13, 4);
-                       }
+                       S390_SET (code, s390_r0, ins->inst_imm);
+                       if (is_unsigned (ins->next))
+                               s390_clr  (code, ins->sreg1, s390_r0);
+                       else
+                               s390_cr   (code, ins->sreg1, s390_r0);
                }
                        break;
                case OP_BREAK: {
-                       s390_basr  (code, s390_r13, 0);
-                       s390_j     (code, 6);
                        mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_ABS, 
                                             mono_break);
-                       s390_llong (code, mono_break);
-                       s390_lg    (code, s390_r14, 0, s390_r13, 4);
-                        s390_basr  (code, s390_r14, s390_r14);
+                       S390_CALL_TEMPLATE (code, s390_r14);
                }
                        break;
                case OP_ADDCC: {
@@ -3274,11 +3125,11 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        }
                        if (s390_is_imm16 (ins->inst_imm)) {
                                s390_aghi (code, ins->dreg, ins->inst_imm);
+                       } else if (s390_is_imm32 (ins->inst_imm)) {
+                               s390_agfi (code, ins->dreg, ins->inst_imm);
                        } else {
-                               s390_basr (code, s390_r13, 0);
-                               s390_j    (code, 6);
-                               s390_llong(code, ins->inst_imm);
-                               s390_ag   (code, ins->dreg, 0, s390_r13, 4);
+                               S390_SET  (code, s390_r0, ins->inst_imm);
+                               s390_agr  (code, ins->dreg, s390_r0);
                        }
                }
                        break;
@@ -3298,11 +3149,8 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                                s390_lghi  (code, s390_r0, ins->inst_imm);
                                s390_alcgr (code, ins->dreg, s390_r0);
                        } else {
-                               s390_basr  (code, s390_r13, 0);
-                               s390_j     (code, 6);
-                               s390_llong (code, ins->inst_imm);
-                               s390_lg    (code, s390_r13, 0, s390_r13, 4);
-                               s390_alcgr (code, ins->dreg, s390_r13);
+                               S390_SET   (code, s390_r0, ins->inst_imm);
+                               s390_alcgr (code, ins->dreg, s390_r0);
                        }
                }
                        break;
@@ -3359,13 +3207,12 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                                s390_lgr   (code, ins->dreg, ins->sreg1);
                        }
                        if (s390_is_imm16 (-ins->inst_imm)) {
-                               s390_lghi  (code, s390_r0, ins->inst_imm);
-                               s390_slgr  (code, ins->dreg, s390_r0);
+                               s390_aghi  (code, ins->dreg, -ins->inst_imm);
+                       } else if (s390_is_imm32 (-ins->inst_imm)) {
+                               s390_slgfi  (code, ins->dreg, ins->inst_imm);
                        } else {
-                               s390_basr (code, s390_r13, 0);
-                               s390_j    (code, 6);
-                               s390_llong(code, ins->inst_imm);
-                               s390_slg  (code, ins->dreg, 0, s390_r13, 4);
+                               S390_SET  (code, s390_r0, ins->inst_imm);
+                               s390_slgr (code, ins->dreg, s390_r0);
                        }
                }
                        break;
@@ -3374,13 +3221,12 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                                s390_lgr   (code, ins->dreg, ins->sreg1);
                        }
                        if (s390_is_imm16 (-ins->inst_imm)) {
-                               s390_lghi  (code, s390_r0, ins->inst_imm);
-                               s390_slgr  (code, ins->dreg, s390_r0);
+                               s390_aghi  (code, ins->dreg, -ins->inst_imm);
+                       } else if (s390_is_imm32 (-ins->inst_imm)) {
+                               s390_slgfi (code, ins->dreg, ins->inst_imm);
                        } else {
-                               s390_basr (code, s390_r13, 0);
-                               s390_j    (code, 6);
-                               s390_llong(code, ins->inst_imm);
-                               s390_slg  (code, ins->dreg, 0, s390_r13, 4);
+                               S390_SET  (code, s390_r0, ins->inst_imm);
+                               s390_slgr (code, ins->dreg, s390_r0);
                        }
                }
                        break;
@@ -3392,10 +3238,8 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                                s390_lghi  (code, s390_r0, ins->inst_imm);
                                s390_slbgr (code, ins->dreg, s390_r0);
                        } else {
-                               s390_basr (code, s390_r13, 0);
-                               s390_j    (code, 6);
-                               s390_llong(code, ins->inst_imm);
-                               s390_slbg (code, ins->dreg, 0, s390_r13, 4);
+                               S390_SET  (code, s390_r0, ins->inst_imm);
+                               s390_slbgr(code, ins->dreg, s390_r0);
                        }
                }
                        break;
@@ -3435,15 +3279,8 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        if (ins->dreg != ins->sreg1) {
                                s390_lgr  (code, ins->dreg, ins->sreg1);
                        }
-                       if (s390_is_imm16 (ins->inst_imm)) {
-                               s390_lghi  (code, s390_r0, ins->inst_imm);
-                               s390_ngr  (code, ins->dreg, s390_r0);
-                       } else {
-                               s390_basr (code, s390_r13, 0);
-                               s390_j    (code, 6);
-                               s390_llong(code, ins->inst_imm);
-                               s390_ng   (code, ins->dreg, 0, s390_r13, 4);
-                       }
+                       S390_SET_MASK (code, s390_r0, ins->inst_imm);
+                       s390_ngr (code, ins->dreg, s390_r0);
                }
                        break;
                case OP_LDIV: {
@@ -3491,15 +3328,8 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        if (ins->dreg != ins->sreg1) {
                                s390_lgr  (code, ins->dreg, ins->sreg1);
                        }
-                       if (s390_is_imm16 (ins->inst_imm)) {
-                               s390_lghi (code, s390_r0, ins->inst_imm);
-                               s390_ogr  (code, ins->dreg, s390_r0);
-                       } else {
-                               s390_basr (code, s390_r13, 0);
-                               s390_j    (code, 6);
-                               s390_llong(code, ins->inst_imm);
-                               s390_og   (code, ins->dreg, 0, s390_r13, 4);
-                       }
+                       S390_SET_MASK(code, s390_r0, ins->inst_imm);
+                       s390_ogr (code, ins->dreg, s390_r0);
                }
                        break;
                case OP_LXOR: {
@@ -3521,15 +3351,8 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        if (ins->dreg != ins->sreg1) {
                                s390_lgr  (code, ins->dreg, ins->sreg1);
                        }
-                       if (s390_is_imm16 (ins->inst_imm)) {
-                               s390_lghi  (code, s390_r0, ins->inst_imm);
-                               s390_xgr  (code, ins->dreg, s390_r0);
-                       } else {
-                               s390_basr (code, s390_r13, 0);
-                               s390_j    (code, 6);
-                               s390_llong(code, ins->inst_imm);
-                               s390_xg   (code, ins->dreg, 0, s390_r13, 4);
-                       }
+                       S390_SET_MASK (code, s390_r0, ins->inst_imm);
+                       s390_xgr (code, ins->dreg, s390_r0);
                }
                        break;
                case OP_LSHL: {
@@ -3595,11 +3418,10 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        }
                        if (s390_is_imm16 (ins->inst_imm)) {
                                s390_lghi (code, s390_r13, ins->inst_imm);
+                       } else if (s390_is_imm32 (ins->inst_imm)) {
+                               s390_lgfi (code, s390_r13, ins->inst_imm);
                        } else {
-                               s390_basr (code, s390_r13, 0);
-                               s390_j    (code, 6);
-                               s390_llong(code, ins->inst_imm);
-                               s390_lg   (code, s390_r13, 0, s390_r13, 4);
+                               S390_SET (code, s390_r13, ins->inst_imm);
                        }
                        s390_msgr (code, ins->dreg, s390_r13);
                }
@@ -3654,12 +3476,9 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                                s390_lgfr (code, ins->dreg, ins->sreg1);
                        }
                        if (s390_is_imm16 (ins->inst_imm)) {
-                               s390_aghi(code, ins->dreg, ins->inst_imm);
+                               s390_aghi (code, ins->dreg, ins->inst_imm);
                        } else {
-                               s390_basr (code, s390_r13, 0);
-                               s390_j    (code, 4);
-                               s390_word (code, ins->inst_imm);
-                               s390_agf  (code, ins->dreg, 0, s390_r13, 4);
+                               s390_afi  (code, ins->dreg, ins->inst_imm);
                        }
                }
                        break;
@@ -3671,11 +3490,8 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                                s390_lghi  (code, s390_r0, ins->inst_imm);
                                s390_alcgr (code, ins->dreg, s390_r0);
                        } else {
-                               s390_basr  (code, s390_r13, 0);
-                               s390_j     (code, 4);
-                               s390_word  (code, ins->inst_imm);
-                               s390_lgf   (code, s390_r13, 0, s390_r13, 4);
-                               s390_alcgr (code, ins->dreg, s390_r13);
+                               S390_SET   (code, s390_r0, ins->inst_imm);
+                               s390_alcgr (code, ins->dreg, s390_r0);
                        }
                }
                        break;
@@ -3715,18 +3531,13 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        if (s390_is_imm16 (-ins->inst_imm)) {
                                s390_aghi (code, ins->dreg, -ins->inst_imm);
                        } else {
-                               s390_basr (code, s390_r13, 0);
-                               s390_j    (code, 4);
-                               s390_word (code, ins->inst_imm);
-                               s390_sgf  (code, ins->dreg, 0, s390_r13, 4);
+                               s390_agfi (code, ins->dreg, -ins->inst_imm);
                        }
                }
                        break;
                case OP_ISBB_IMM: {
-                       s390_basr (code, s390_r13, 0);
-                       s390_j    (code, 4);
-                       s390_word (code, ins->inst_imm);
-                       s390_slgf (code, ins->dreg, 0, s390_r13, 4);
+                       S390_SET (code, s390_r0, ins->inst_imm);
+                       s390_slgfr (code, ins->dreg, s390_r0);
                }
                        break;
                case OP_ISUB_OVF:
@@ -3768,15 +3579,8 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        if (ins->dreg != ins->sreg1) {
                                s390_lgfr (code, ins->dreg, ins->sreg1);
                        }
-                       if (s390_is_imm16 (ins->inst_imm)) {
-                               s390_lghi (code, s390_r0, ins->inst_imm);
-                               s390_ngr  (code, ins->dreg, s390_r0);
-                       } else {
-                               s390_basr (code, s390_r13, 0);
-                               s390_j    (code, 6);
-                               s390_llong(code, ins->inst_imm);
-                               s390_ng   (code, ins->dreg, 0, s390_r13, 4);
-                       }
+                       S390_SET_MASK (code, s390_r0, ins->inst_imm);
+                       s390_ngr  (code, ins->dreg, s390_r0);
                }
                        break;
                case OP_IDIV: {
@@ -3796,14 +3600,10 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                case OP_IDIV_IMM: {
                        if (s390_is_imm16 (ins->inst_imm)) {
                                s390_lghi (code, s390_r13, ins->inst_imm);
-                               s390_lgfr (code, s390_r0, ins->sreg1);
                        } else {
-                               s390_basr (code, s390_r13, 0);
-                               s390_j    (code, 4);
-                               s390_word (code, ins->inst_imm);
-                               s390_lgfr (code, s390_r0, ins->sreg1);
-                               s390_lgf  (code, s390_r13, 0, s390_r13, 4);
+                               s390_lgfi (code, s390_r13, ins->inst_imm);
                        }
+                       s390_lgfr (code, s390_r0, ins->sreg1);
                        s390_srda (code, s390_r0, 0, 32);
                        s390_dr   (code, s390_r0, ins->sreg2);
                        s390_lgfr (code, ins->dreg, s390_r1);
@@ -3825,14 +3625,10 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                case OP_IREM_IMM: {
                        if (s390_is_imm16 (ins->inst_imm)) {
                                s390_lghi (code, s390_r13, ins->inst_imm);
-                               s390_lgfr (code, s390_r0, ins->sreg1);
                        } else {
-                               s390_basr (code, s390_r13, 0);
-                               s390_j    (code, 4);
-                               s390_word (code, ins->inst_imm);
-                               s390_lgfr (code, s390_r0, ins->sreg1);
-                               s390_lgf  (code, s390_r13, 0, s390_r13, 4);
+                               s390_lgfi (code, s390_r13, ins->inst_imm);
                        }
+                       s390_lgfr (code, s390_r0, ins->sreg1);
                        s390_srda (code, s390_r0, 0, 32);
                        s390_dr   (code, s390_r0, ins->sreg2);
                        s390_lgfr (code, ins->dreg, s390_r0);
@@ -3847,15 +3643,8 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        if (ins->dreg != ins->sreg1) {
                                s390_lgfr (code, ins->dreg, ins->sreg1);
                        }
-                       if (s390_is_imm16 (ins->inst_imm)) {
-                               s390_lghi (code, s390_r0, ins->inst_imm);
-                               s390_ogr  (code, ins->dreg, s390_r0);
-                       } else {
-                               s390_basr (code, s390_r13, 0);
-                               s390_j    (code, 6);
-                               s390_llong(code, ins->inst_imm);
-                               s390_og   (code, ins->dreg, 0, s390_r13, 4);
-                       }
+                       S390_SET_MASK (code, s390_r0, ins->inst_imm);
+                       s390_ogr  (code, ins->dreg, s390_r0);
                }
                        break;
                case OP_IXOR: {
@@ -3867,15 +3656,8 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        if (ins->dreg != ins->sreg1) {
                                s390_lgfr (code, ins->dreg, ins->sreg1);
                        }
-                       if (s390_is_imm16 (ins->inst_imm)) {
-                               s390_lghi (code, s390_r0, ins->inst_imm);
-                               s390_xgr  (code, ins->dreg, s390_r0);
-                       } else {
-                               s390_basr (code, s390_r13, 0);
-                               s390_j    (code, 6);
-                               s390_llong(code, ins->inst_imm);
-                               s390_xg   (code, ins->dreg, 0, s390_r13, 4);
-                       }
+                       S390_SET_MASK (code, s390_r0, ins->inst_imm);
+                       s390_xgr  (code, ins->dreg, s390_r0);
                }
                        break;
                case OP_ISHL: {
@@ -3936,14 +3718,11 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                                s390_lgfr (code, ins->dreg, ins->sreg1);
                        }
                        if (s390_is_imm16 (ins->inst_imm)) {
-                               s390_lghi (code, s390_r13, ins->inst_imm);
+                               s390_lghi (code, s390_r0, ins->inst_imm);
                        } else {
-                               s390_basr (code, s390_r13, 0);
-                               s390_j    (code, 4);
-                               s390_word (code, ins->inst_imm);
-                               s390_lgf  (code, s390_r13, 0, s390_r13, 4);
+                               s390_lgfi (code, s390_r0, ins->inst_imm);
                        }
-                       s390_msr  (code, ins->dreg, s390_r13);
+                       s390_msr  (code, ins->dreg, s390_r0);
                }
                        break;
                case OP_IMUL_OVF: {
@@ -3976,32 +3755,19 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        break;
                case OP_ICONST: 
                case OP_I8CONST: {
-                       if (s390_is_imm16(ins->inst_c0)) {
-                               s390_lghi (code, ins->dreg, ins->inst_c0);
-                       } else {
-                               s390_basr (code, s390_r13, 0);
-                               s390_j    (code, 6);
-                               s390_llong(code, ins->inst_c0);
-                               s390_lg   (code, ins->dreg, 0, s390_r13, 4);
-                       }
+                       S390_SET (code, ins->dreg, ins->inst_c0);
                }
                        break;
                case OP_AOTCONST: {
-                       s390_basr (code, s390_r13, 0);
-                       s390_j    (code, 6);
                        mono_add_patch_info (cfg, code - cfg->native_code, 
                                (MonoJumpInfoType)ins->inst_i1, ins->inst_p0);
-                       s390_llong(code, 0);
-                       s390_lg   (code,ins->dreg, 0, s390_r13, 4);
+                       S390_LOAD_TEMPLATE (code, ins->dreg);
                }
                        break;
                case OP_JUMP_TABLE: {
                        mono_add_patch_info (cfg, code - cfg->native_code, 
                                (MonoJumpInfoType)ins->inst_i1, ins->inst_p0);
-                       s390_basr  (code, s390_r13, 0);
-                       s390_j     (code, 6);
-                       s390_llong (code, 0);
-                       s390_lg    (code, ins->dreg, 0, s390_r13, 4);
+                       S390_LOAD_TEMPLATE (code, ins->dreg);
                }
                        break;
                case OP_MOVE:
@@ -4024,32 +3790,32 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        s390_llgfr (code, ins->dreg, ins->sreg1);
                        break;
                case OP_LCONV_TO_OVF_U4:
-                       s390_basr (code, s390_r13, 0);
-                       s390_j    (code, 6);
-                       s390_llong(code, 4294967295);
-                       s390_clg  (code, ins->sreg1, 0, s390_r13, 4);   
+                       S390_SET  (code, s390_r0, 4294967295);
+                       s390_clgr (code, ins->sreg1, s390_r0);
                        EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT, "OverflowException");
                        s390_ltgr (code, ins->sreg1, ins->sreg1);
                        EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT, "OverflowException");
                        s390_llgfr(code, ins->dreg, ins->sreg1);
                        break;
                case OP_LCONV_TO_OVF_I4_UN:
-                       s390_basr (code, s390_r13, 0);
-                       s390_j    (code, 6);
-                       s390_llong(code, 2147483647);
-                       s390_cg   (code, ins->sreg1, 0, s390_r13, 4);
+                       S390_SET  (code, s390_r0, 2147483647);
+                       s390_cgr  (code, ins->sreg1, s390_r0);
                        EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT, "OverflowException");
                        s390_ltgr (code, ins->sreg1, ins->sreg1);
                        EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT, "OverflowException");
                        s390_lgfr (code, ins->dreg, ins->sreg1);
                        break;
-               case OP_FMOVE:
-               case OP_FCONV_TO_R4: {
+               case OP_FMOVE: {
                        if (ins->dreg != ins->sreg1) {
                                s390_ldr   (code, ins->dreg, ins->sreg1);
                        }
                }
                        break;
+               case OP_FCONV_TO_R4: {
+                       s390_ledbr (code, ins->dreg, ins->sreg1);
+                       s390_ldebr (code, ins->dreg, ins->dreg);
+               }
+                       break;
                case OP_S390_SETF4RET: {
                        s390_ledbr (code, ins->dreg, ins->sreg1);
                }
@@ -4057,11 +3823,10 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                case OP_TLS_GET: {
                        if (s390_is_imm16 (ins->inst_offset)) {
                                s390_lghi (code, s390_r13, ins->inst_offset);
+                       } else if (s390_is_imm32 (ins->inst_offset)) {
+                               s390_lgfi (code, s390_r13, ins->inst_offset);
                        } else {
-                               s390_bras (code, s390_r13, 0);
-                               s390_j    (code, 4);
-                               s390_llong(code, ins->inst_offset);
-                               s390_lg   (code, s390_r13, 0, s390_r13, 4);
+                               S390_SET  (code, s390_r13, ins->inst_offset);
                        }
                        s390_ear (code, s390_r1, 0);
                        s390_sllg(code, s390_r1, s390_r1, 0, 32);
@@ -4095,21 +3860,18 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                case OP_ARGLIST: {
                        int offset = cfg->sig_cookie + cfg->stack_usage;
 
-                       if (s390_is_imm16 (offset))
+                       if (s390_is_imm16 (offset)) {
                                s390_lghi (code, s390_r0, offset);
-                       else {
-                               s390_basr (code, s390_r13, 0);
-                               s390_j    (code, 6);
-                               s390_llong(code, offset);
-                               s390_lg   (code, s390_r0, 0, s390_r13, 0);
+                       } else if (s390_is_imm32 (offset)) {
+                               s390_lgfi (code, s390_r0, offset);
+                       } else {
+                               S390_SET  (code, s390_r0, offset);
                        }
                        s390_agr  (code, s390_r0, cfg->frame_reg);
                        s390_stg  (code, s390_r0, 0, ins->sreg1, 0);
                }
                        break;
                case OP_FCALL: {
-                       s390_basr (code, s390_r13, 0);
-                       s390_j    (code, 6);
                        call = (MonoCallInst*)ins;
                        if (ins->flags & MONO_INST_HAS_METHOD)
                                mono_add_patch_info (cfg, code-cfg->native_code,
@@ -4119,9 +3881,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                                mono_add_patch_info (cfg, code-cfg->native_code,
                                                     MONO_PATCH_INFO_ABS, 
                                                     call->fptr);
-                       s390_llong(code, 0);
-                       s390_lg   (code, s390_r14, 0, s390_r13, 4);
-                       s390_basr (code, s390_r14, s390_r14);
+                       S390_CALL_TEMPLATE (code, s390_r14);
                        if (call->signature->ret->type == MONO_TYPE_R4)
                                s390_ldebr (code, s390_f0, s390_f0);
                }
@@ -4131,8 +3891,6 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                case OP_VCALL2:
                case OP_VOIDCALL:
                case OP_CALL: {
-                       s390_basr (code, s390_r13, 0);
-                       s390_j    (code, 6);
                        call = (MonoCallInst*)ins;
                        if (ins->flags & MONO_INST_HAS_METHOD)
                                mono_add_patch_info (cfg, code-cfg->native_code,
@@ -4142,9 +3900,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                                mono_add_patch_info (cfg, code-cfg->native_code,
                                                     MONO_PATCH_INFO_ABS, 
                                                     call->fptr);
-                       s390_llong(code, 0);
-                       s390_lg   (code, s390_r14, 0, s390_r13, 4);
-                       s390_basr (code, s390_r14, s390_r14);
+                       S390_CALL_TEMPLATE (code, s390_r14);
                }
                        break;
                case OP_FCALL_REG: {
@@ -4204,13 +3960,12 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                                int lmfOffset = cfg->stack_usage - sizeof(MonoLMF);
 
                                s390_lgr (code, s390_r13, cfg->frame_reg);
-                               if (s390_is_imm16(lmfOffset))
+                               if (s390_is_imm16(lmfOffset)) {
                                        s390_aghi (code, s390_r13, lmfOffset);
-                               else {
-                                       s390_basr (code, s390_r14, 0);
-                                       s390_j    (code, 4);
-                                       s390_word (code, lmfOffset);
-                                       s390_agf  (code, s390_r13, 0, s390_r14, 4);
+                               } else if (s390_is_imm32(lmfOffset)) {
+                                       s390_agfi (code, s390_r13, lmfOffset);
+                               } else {
+                                       S390_SET  (code, s390_r13, lmfOffset);
                                }
                                s390_lgr (code, s390_r14, STK_BASE);
                                s390_sgr (code, s390_r14, s390_r1);
@@ -4236,24 +3991,16 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        break;
                case OP_THROW: {
                        s390_lgr  (code, s390_r2, ins->sreg1);
-                       s390_basr (code, s390_r13, 0);
-                       s390_j    (code, 6);
                        mono_add_patch_info (cfg, code-cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD, 
                                             (gpointer) "mono_arch_throw_exception");
-                       s390_llong(code, 0);
-                       s390_lg   (code, s390_r14, 0, s390_r13, 4);
-                       s390_basr (code, s390_r14, s390_r14);
+                       S390_CALL_TEMPLATE(code, s390_r14);
                }
                        break;
                case OP_RETHROW: {
                        s390_lgr  (code, s390_r2, ins->sreg1);
-                       s390_basr (code, s390_r13, 0);
-                       s390_j    (code, 6);
                        mono_add_patch_info (cfg, code-cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD, 
                                             (gpointer) "mono_arch_rethrow_exception");
-                       s390_llong(code, 0);
-                       s390_lg   (code, s390_r14, 0, s390_r13, 4);
-                       s390_basr (code, s390_r14, s390_r14);
+                       S390_CALL_TEMPLATE(code, s390_r14);
                }
                        break;
                case OP_START_HANDLER: {
@@ -4465,11 +4212,8 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        if (*((double *) ins->inst_p0) == 0) {
                                s390_lzdr (code, ins->dreg);
                        } else {
-                               s390_basr  (code, s390_r13, 0);
-                               s390_j     (code, 6);
-                               s390_llong (code, ins->inst_p0);
-                               s390_lg    (code, s390_r13, 0, s390_r13, 4);
-                               s390_ld    (code, ins->dreg, 0, s390_r13, 0);
+                               S390_SET  (code, s390_r13, ins->inst_p0);
+                               s390_ld   (code, ins->dreg, 0, s390_r13, 0);
                        }
                }
                        break;
@@ -4477,10 +4221,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        if (*((float *) ins->inst_p0) == 0) {
                                s390_lzdr (code, ins->dreg);
                        } else {
-                               s390_basr (code, s390_r13, 0);
-                               s390_j    (code, 6);
-                               s390_llong(code, ins->inst_p0);
-                               s390_lg   (code, s390_r13, 0, s390_r13, 4);
+                               S390_SET  (code, s390_r13, ins->inst_p0);
                                s390_ldeb (code, ins->dreg, 0, s390_r13, 0);
                        }
                }
@@ -4510,28 +4251,25 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                case OP_ICONV_TO_R_UN: {
                        s390_cdfbr (code, ins->dreg, ins->sreg1);
                        s390_ltr   (code, ins->sreg1, ins->sreg1);
-                       s390_jnl   (code, 12);
-                       s390_basr  (code, s390_r13, 0);
-                       s390_j     (code, 6);
-                       s390_word  (code, 0x41f00000);
-                       s390_word  (code, 0);
-                       s390_adb   (code, ins->dreg, 0, s390_r13, 4);
+                       s390_jnl   (code, 8);
+                       S390_SET   (code, s390_r13, 0x41f0000000000000llu);
+                       s390_ldgr  (code, s390_f15, s390_r13);
+                       s390_adbr  (code, ins->dreg, s390_f15);
                }
                        break;
                case OP_LCONV_TO_R_UN: {
                        s390_cdgbr (code, ins->dreg, ins->sreg1);
                        s390_ltgr  (code, ins->sreg1, ins->sreg1);
-                       s390_jnl   (code, 12);
-                       s390_basr  (code, s390_r13, 0);
-                       s390_j     (code, 6);
-                       s390_word  (code, 0x41f00000);
-                       s390_word  (code, 0);
-                       s390_adb   (code, ins->dreg, 0, s390_r13, 4);
+                       s390_jnl   (code, 8);
+                       S390_SET   (code, s390_r13, 0x41f0000000000000llu);
+                       s390_ldgr  (code, s390_f15, s390_r13);
+                       s390_adbr  (code, ins->dreg, s390_f15);
                }
                        break;
                case OP_LCONV_TO_R4:
                case OP_ICONV_TO_R4: {
-                       s390_cdgbr (code, ins->dreg, ins->sreg1);
+                       s390_cegbr (code, ins->dreg, ins->sreg1);
+                       s390_ldebr (code, ins->dreg, ins->dreg);
                }
                        break;
                case OP_LCONV_TO_R8:
@@ -4733,31 +4471,31 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                                        if (ins->inst_offset > 0) {
                                                if (s390_is_imm16 (ins->inst_offset)) {
                                                        s390_aghi (code, s390_r0, ins->inst_offset);
+                                               } else if (s390_is_imm32 (ins->inst_offset)) {
+                                                       s390_agfi (code, s390_r0, ins->inst_offset);
                                                } else {
-                                                       s390_basr (code, s390_r13, 0);
-                                                       s390_j    (code, 6);
-                                                       s390_llong(code, ins->inst_offset);
-                                                       s390_ag   (code, s390_r0, 0, s390_r13, 4);
+                                                       S390_SET  (code, s390_r13, ins->inst_offset);
+                                                       s390_agr  (code, s390_r0, s390_r13);
                                                }
                                        }
                                        s390_lgr  (code, s390_r12, ins->sreg1);
                                        if (ins->inst_imm > 0) {
                                                if (s390_is_imm16 (ins->inst_imm)) {
                                                        s390_aghi (code, s390_r12, ins->inst_imm);
+                                               } else if (s390_is_imm32 (ins->inst_imm)) {
+                                                       s390_agfi (code, s390_r12, ins->inst_imm);
                                                } else {
-                                                       s390_basr (code, s390_r13, 0);
-                                                       s390_j    (code, 6);
-                                                       s390_llong(code, ins->inst_imm);
-                                                       s390_ag   (code, s390_r12, 0, s390_r13, 4);
+                                                       S390_SET  (code, s390_r13, ins->inst_imm);
+                                                       s390_agr  (code, s390_r12, s390_r13);
                                                }
                                        }
                                        if (s390_is_imm16 (ins->backend.size)) {
                                                s390_lghi (code, s390_r1, ins->backend.size);
+                                       } else if (s390_is_imm32 (ins->inst_offset)) {
+                                               s390_agfi (code, s390_r1, ins->backend.size);
                                        } else {
-                                               s390_basr (code, s390_r13, 0);
-                                               s390_j    (code, 6);
-                                               s390_llong(code, ins->backend.size);
-                                               s390_lg   (code, s390_r1, 0, s390_r13, 4);
+                                               S390_SET  (code, s390_r13, ins->backend.size);
+                                               s390_agr  (code, s390_r1, s390_r13);
                                        }
                                        s390_lgr  (code, s390_r13, s390_r1);
                                        s390_mvcle(code, s390_r0, s390_r12, 0, 0);
@@ -4820,11 +4558,11 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        s390_lgr  (code, ins->dreg, ins->sreg1);
                        if (s390_is_imm16 (cfg->stack_offset)) {
                                s390_aghi (code, ins->dreg, cfg->stack_offset);
+                       } else if (s390_is_imm32 (cfg->stack_offset)) {
+                               s390_agfi (code, ins->dreg, cfg->stack_offset);
                        } else {
-                               s390_basr (code, s390_r13, 0);
-                               s390_j    (code, 6);
-                               s390_llong(code, cfg->stack_offset);
-                               s390_ag   (code, ins->dreg, 0, s390_r13, 4);
+                               S390_SET  (code, s390_r13, cfg->stack_offset);
+                               s390_agr  (code, ins->dreg, s390_r13);
                        }
                }
                        break;  
@@ -4901,33 +4639,36 @@ mono_arch_patch_code (MonoMethod *method, MonoDomain *domain,
 
                switch (patch_info->type) {
                        case MONO_PATCH_INFO_IP:
-                       case MONO_PATCH_INFO_EXC_NAME:
                        case MONO_PATCH_INFO_LDSTR:
                        case MONO_PATCH_INFO_TYPE_FROM_HANDLE: 
                        case MONO_PATCH_INFO_LDTOKEN: 
                        case MONO_PATCH_INFO_EXC:
-                       case MONO_PATCH_INFO_ABS:
+                               s390_patch_addr (ip, (guint64) target);
+                               continue;
                        case MONO_PATCH_INFO_METHOD:
-                       case MONO_PATCH_INFO_RGCTX_FETCH:
                        case MONO_PATCH_INFO_INTERNAL_METHOD:
-                       case MONO_PATCH_INFO_CLASS_INIT:
                        case MONO_PATCH_INFO_JIT_ICALL_ADDR:
+                       case MONO_PATCH_INFO_CLASS_INIT:
                        case MONO_PATCH_INFO_GENERIC_CLASS_INIT:
-                               s390_patch_addr (ip, (guint64) target);
+                       case MONO_PATCH_INFO_RGCTX_FETCH:
+                       case MONO_PATCH_INFO_ABS: {
+                               S390_EMIT_CALL (ip, target);
                                continue;
+                       }
                        case MONO_PATCH_INFO_SWITCH: 
                                /*----------------------------------*/
                                /* ip points at the basr r13,0/j +4 */
                                /* instruction the vtable value     */
                                /* follows this (i.e. ip+6)         */
                                /*----------------------------------*/
-                               *((gconstpointer *)(ip+6)) = target;
+                               S390_EMIT_LOAD (ip, target);
                                continue;
                        case MONO_PATCH_INFO_METHODCONST:
                        case MONO_PATCH_INFO_CLASS:
                        case MONO_PATCH_INFO_IMAGE:
                        case MONO_PATCH_INFO_FIELD:
                        case MONO_PATCH_INFO_IID:
+                       case MONO_PATCH_INFO_EXC_NAME:
                                target = S390_RELATIVE(target, ip);
                                s390_patch_rel (ip, (guint64) target);
                                continue;
@@ -5109,13 +4850,15 @@ mono_arch_emit_prolog (MonoCompile *cfg)
        s390_lgr  (code, s390_r11, STK_BASE);
        if (s390_is_imm16 (alloc_size)) {
                s390_aghi (code, STK_BASE, -alloc_size);
-       } else { 
+       } else if (s390_is_imm32 (alloc_size)) { 
+               s390_agfi (code, STK_BASE, -alloc_size);
+       } else {
                int stackSize = alloc_size;
-               while (stackSize > 32767) {
-                       s390_aghi (code, STK_BASE, -32767);
-                       stackSize -= 32767;
+               while (stackSize > INT_MAX) {
+                       s390_agfi (code, STK_BASE, -INT_MAX);
+                       stackSize -= INT_MAX;
                }
-               s390_aghi (code, STK_BASE, -stackSize);
+               s390_agfi (code, STK_BASE, -stackSize);
        }
        s390_stg  (code, s390_r11, 0, STK_BASE, 0);
 
@@ -5282,14 +5025,10 @@ mono_arch_emit_prolog (MonoCompile *cfg)
                /* On return from this call r2 have the address of the &lmf      */
                /*---------------------------------------------------------------*/
                if (lmf_addr_tls_offset == -1) {
-                       s390_basr(code, s390_r14, 0);
-                       s390_j   (code, 6);
                        mono_add_patch_info (cfg, code - cfg->native_code, 
                                             MONO_PATCH_INFO_INTERNAL_METHOD, 
                                             (gpointer)"mono_get_lmf_addr");
-                       s390_llong(code, 0);
-                       s390_lg   (code, s390_r1, 0, s390_r14, 4);
-                       s390_basr (code, s390_r14, s390_r1);
+                       S390_CALL_TEMPLATE(code, s390_r1);
                } else {
                        /*-------------------------------------------------------*/
                        /* Get LMF by getting value from thread level storage    */
@@ -5325,10 +5064,7 @@ mono_arch_emit_prolog (MonoCompile *cfg)
                /*---------------------------------------------------------------*/     
                /* save method info                                              */     
                /*---------------------------------------------------------------*/     
-               s390_basr  (code, s390_r1, 0);                                          
-               s390_j     (code, 6);
-               s390_llong (code, method);                                              
-               s390_lg    (code, s390_r1, 0, s390_r1, 4);                      
+               S390_SET   (code, s390_r1, method);
                s390_stg   (code, s390_r1, 0, s390_r13,                                 
                            G_STRUCT_OFFSET(MonoLMF, method));                          
                                                                                
@@ -5499,27 +5235,19 @@ mono_arch_emit_exceptions (MonoCompile *cfg)
                                /*---------------------------------------------*/
                                /* Patch the parameter passed to the handler   */ 
                                /*---------------------------------------------*/
-                               s390_basr (code, s390_r13, 0);
-                               s390_j    (code, 6);
-//                             s390_llong(code, patch_info->data.target);
-                               s390_llong(code, exc_class->type_token);
+                               S390_SET  (code, s390_r2, exc_class->type_token);
                                /*---------------------------------------------*/
                                /* Load return address & parameter register    */
                                /*---------------------------------------------*/
                                s390_larl (code, s390_r14, (guint64)S390_RELATIVE((patch_info->ip.i +
                                                           cfg->native_code + 8), code));
-                               s390_lg   (code, s390_r2, 0, s390_r13, 4);
                                /*---------------------------------------------*/
                                /* Reuse the current patch to set the jump     */
                                /*---------------------------------------------*/
-                               s390_basr (code, s390_r13, 0);
-                               s390_j    (code, 6);
                                patch_info->type      = MONO_PATCH_INFO_INTERNAL_METHOD;
                                patch_info->data.name = "mono_arch_throw_corlib_exception";
                                patch_info->ip.i      = code - cfg->native_code;
-                               s390_llong(code, 0);
-                               s390_lg   (code, s390_r1, 0, s390_r13, 4);
-                               s390_br   (code, s390_r1);
+                               S390_BR_TEMPLATE (code, s390_r1);
                        }
                        break;
                }
@@ -5572,7 +5300,7 @@ mono_arch_free_jit_tls_data (MonoJitTlsData *tls)
 
 /*------------------------------------------------------------------*/
 /*                                                                  */
-/* Name                - mono_arch_emit_inst_for_method                        */
+/* Name                - mono_arch_emit_inst_for_method                    */
 /*                                                                  */
 /*------------------------------------------------------------------*/
 
@@ -5745,7 +5473,7 @@ mono_arch_flush_register_windows (void)
 gboolean 
 mono_arch_is_inst_imm (gint64 imm)
 {
-       return s390_is_imm16 (imm);
+       return s390_is_imm32 (imm);
 }
 
 /*========================= End of Function ========================*/
@@ -5819,7 +5547,40 @@ mono_arch_get_this_arg_from_call (mgreg_t *regs, guint8 *code)
 }
 
 /*========================= End of Function ========================*/
+/*------------------------------------------------------------------*/
+/*                                                                  */
+/* Name                - mono_arch_install_handler_block_guard             */
+/*                                                                  */
+/* Function    -                                                   */
+/*                                                                 */
+/*------------------------------------------------------------------*/
+
+gpointer
+mono_arch_install_handler_block_guard (MonoJitInfo *ji, MonoJitExceptionInfo *clause, 
+                                      MonoContext *ctx, gpointer new_value)
+{
+       int offset;
+       gpointer *sp, old_value;
+       char *bp;
+
+       offset = clause->exvar_offset;
+
+       /*Load the spvar*/
+       bp = MONO_CONTEXT_GET_BP (ctx);
+       sp = *(gpointer*)(bp + offset);
+
+       old_value = *sp;
+       if (old_value < ji->code_start || (char*)old_value > ((char*)ji->code_start + ji->code_size))
+               return old_value;
+
+       *sp = new_value;
+
+       return old_value;
+}
 
+/*========================= End of Function ========================*/
 /*------------------------------------------------------------------*/
 /*                                                                  */
 /* Name                - get_delegate_invoke_impl.                         */
@@ -6027,55 +5788,39 @@ mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain,
                if (item->is_equals) {
                        if (item->check_target_idx) {
                                if (!item->compare_done) {
-                                       s390_basr (code, s390_r13, s390_r0);
-                                       s390_j    (code, 6);
-                                       s390_llong(code, item->key);
-                                       s390_lg   (code, s390_r0, 0, s390_r13, 4);
+                                       S390_SET  (code, s390_r0, item->key);
                                        s390_cgr  (code, s390_r0, MONO_ARCH_IMT_REG);
                                }
                                item->jmp_code = (guint8*) code;
                                s390_jcl (code, S390_CC_NE, 0);
                                
-                               s390_basr (code, s390_r13, s390_r0);
-                               s390_j    (code, 6);
-                               if (item->has_target_code)  {
-                                       s390_llong(code, item->value.target_code);
-                                       s390_lg   (code, s390_r1, 0, s390_r13, 4);
-                               } else {        
-                                       s390_llong(code, (&(vtable->vtable [item->value.vtable_slot])));
-                                       s390_lg   (code, s390_r1, 0, s390_r13, 4);
-                                       s390_lg   (code, s390_r1, 0, s390_r1, 0);
+                               if (item->has_target_code) {
+                                       S390_SET (code, s390_r1, item->value.target_code);
+                               } else {
+                                       S390_SET (code, s390_r1, (&(vtable->vtable [item->value.vtable_slot])));
+                                       s390_lg  (code, s390_r1, 0, s390_r1, 0);
                                }
                                s390_br   (code, s390_r1);
                        } else {
                                if (fail_tramp) {
                                        gint64  target;
 
-                                       s390_basr (code, s390_r13, s390_r0);
-                                       s390_j    (code, 6);
-                                       s390_llong(code, item->key);
-                                       s390_lg   (code, s390_r0, 0, s390_r13, 4);
+                                       S390_SET  (code, s390_r0, item->key);
                                        s390_cgr  (code, s390_r0, MONO_ARCH_IMT_REG);
                                        item->jmp_code = (guint8*) code;
                                        s390_jcl  (code, S390_CC_NE, 0);
-                                       s390_basr (code, s390_r13, s390_r0);
-                                       s390_j    (code, 6);
                                        if (item->has_target_code) {
-                                               s390_llong(code, item->value.target_code);
-                                               s390_lg   (code, s390_r1, 0, s390_r13, 4);
+                                               S390_SET (code, s390_r1, item->value.target_code);
                                        } else {
                                                g_assert (vtable);
-                                               s390_llong(code, (&(vtable->vtable [item->value.vtable_slot])));
-                                               s390_lg   (code, s390_r1, 0, s390_r13, 4);
+                                               S390_SET  (code, s390_r1, 
+                                                          (&(vtable->vtable [item->value.vtable_slot])));
                                                s390_lg   (code, s390_r1, 0, s390_r1, 0);
                                        }
                                        s390_br   (code, s390_r1);
                                        target = S390_RELATIVE(code, item->jmp_code);
                                        s390_patch_rel(item->jmp_code+2, target);
-                                       s390_basr (code, s390_r13, s390_r0);
-                                       s390_j    (code, 6);
-                                       s390_llong(code, fail_tramp);
-                                       s390_lg   (code, s390_r1, 0, s390_r13, 4);
+                                       S390_SET  (code, s390_r1, fail_tramp);
                                        s390_br   (code, s390_r1);
                                        item->jmp_code = NULL;
                                } else {
@@ -6083,28 +5828,21 @@ mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain,
 #if ENABLE_WRONG_METHOD_CHECK
                                        g_assert_not_reached ();
 #endif
-                                       s390_basr (code, s390_r13, s390_r0);
-                                       s390_j    (code, 6);
-                                       s390_llong(code, (&(vtable->vtable [item->value.vtable_slot])));
-                                       s390_lg   (code, s390_r1, 0, s390_r13, 4);
+                                       S390_SET (code, s390_r1, (&(vtable->vtable [item->value.vtable_slot])));
                                        s390_lg   (code, s390_r1, 0, s390_r1, 0);
                                        s390_br   (code, s390_r1);
-#if ENABLE_WRONG_METHOD_CHECK
-                                       g_assert_not_reached ();
-#endif
                                }
                        }
                } else {
-                       s390_basr (code, s390_r13, s390_r0);
-                       s390_j    (code, 6);
-                       s390_llong(code, item->key);
-                       s390_lg   (code, s390_r0, 0, s390_r13, 4);
+                       S390_SET  (code, s390_r0, item->key);
                        s390_cgr  (code, MONO_ARCH_IMT_REG, s390_r0);
                        item->jmp_code = (guint8 *) code;
                        s390_jcl  (code, S390_CC_GE, 0);
                }
        }
-       /* patch the branches to get to the target items */
+       /* 
+        * patch the branches to get to the target items 
+        */
        for (i = 0; i < count; ++i) {
                MonoIMTCheckItem *item = imt_entries [i];
                if (item->jmp_code) {
index a5be8f01087162cbde7ed649cf1cb945bc0464aa..8ca5fb27ad29937182d013f1f838007ed13f0521 100644 (file)
 /* Parameters used by the register allocator */
 /*-------------------------------------------*/
 
-#define S390_LONG(loc, opy, op, r, ix, br, off)                                        \
-       if (mono_hwcap_s390x_has_ld) {                                          \
-               if (s390_is_imm20(off)) {                                       \
-                       s390_##opy (loc, r, ix, br, off);                       \
-               } else {                                                        \
-                       s390_basr (code, s390_r13, 0);                          \
-                       s390_j    (code, 6);                                    \
-                       s390_llong(code, off);                                  \
-                       s390_lg   (code, s390_r13, 0, s390_r13, 4);             \
-                       s390_##op (code, r, s390_r13, br, 0);                   \
-               }                                                               \
-       } else {                                                                \
-               if (s390_is_uimm12(off)) {                                      \
-                       s390_##op (loc, r, ix, br, off);                        \
-               } else {                                                        \
-                       s390_basr (code, s390_r13, 0);                          \
-                       s390_j    (code, 6);                                    \
-                       s390_llong(code, off);                                  \
-                       s390_lg   (code, s390_r13, 0, s390_r13, 4);             \
-                       s390_##op (code, r, s390_r13, br, 0);                   \
-               }                                                               \
-       }
-
 struct MonoLMF {
        gpointer    previous_lmf;
        gpointer    lmf_addr;
@@ -62,46 +39,6 @@ typedef struct
        void *return_address;
 } MonoS390StackFrame;
 
-typedef struct
-{
-       char    n3:1;           // N3 instructions present
-       char    zArch:1;        // z/Architecture mode installed
-       char    zAct:1;         // z/Architecture mode active
-       char    date:1;         // DATE enhancement facility
-       char    idte1:1;        // IDTE present (PST)
-       char    idte2:1;        // IDTE present (REG)
-       char    asnlx:1;        // ASN and LX reuse facility
-       char    stfle:1;        // STFLE installed
-       char    zDATe:1;        // Enhanced DAT in z mode
-       char    srstat:1;       // Sense running status facility
-       char    cSSKE:1;        // Conditional SSKE facility
-       char    topo:1;         // COnfiguration topology facility
-       char    xTrans2:1;      // Extended translation facility 2
-       char    msgSec:1;       // Message security facility
-       char    longDsp:1;      // Long displacement facility
-       char    hiPerfLD:1;     // High performance long displacement facility
-       char    hfpMAS:1;       // HFP multiply-and-add/subtrace facility
-       char    xImm:1;         // Extended immediate facility
-       char    xTrans3:1;      // Extended translation facility 3
-       char    hfpUnX:1;       // HFP unnormalized extension facility
-       char    etf2:1;         // ETF2-enhancement facility
-       char    stckf:1;        // Store-clock-fast facility
-       char    parse:1;        // Parsing enhancement facility
-       char    mvcos:1;        // MVCOS facility
-       char    todSteer:1;     // TOD-clock steering facility
-       char    etf3:1;         // ETF3-enhancement facility
-       char    xCPUtm:1;       // Extract CPU time facility
-       char    csst:1;         // Compare-swap-and-store facility
-       char    csst2:1;        // Compare-swap-and-store facility 2
-       char    giX:1;          // General instructions extension facility
-       char    exX:1;          // Execute extensions facility
-       char    ibm:1;          // IBM internal use
-       char    fps:1;          // Floating point support enhancement
-       char    dfp:1;          // Decimal floating point facility
-       char    hiDFP:1;        // High Performance DFP facility
-       char    pfpo:1;         // PFPO instruction facility
-} __attribute__((aligned(8))) facilityList_t;
-       
 // #define MONO_ARCH_SIGSEGV_ON_ALTSTACK               1
 #define MONO_ARCH_EMULATE_LCONV_TO_R8_UN               1
 #define MONO_ARCH_NO_EMULATE_LONG_MUL_OPTS             1
@@ -128,6 +65,8 @@ typedef struct
 #define MONO_ARCH_GC_MAPS_SUPPORTED                    1
 #define MONO_ARCH_GSHARED_SUPPORTED                    1
 #define MONO_ARCH_MONITOR_ENTER_ADJUSTMENT             1
+#define MONO_ARCH_HAVE_HANDLER_BLOCK_GUARD             1
+#define MONO_ARCH_HAVE_INVALIDATE_METHOD               1
 
 #define S390_STACK_ALIGNMENT            8
 #define S390_FIRST_ARG_REG             s390_r2
diff --git a/mono/mini/support-s390x.h b/mono/mini/support-s390x.h
new file mode 100644 (file)
index 0000000..3ae4c48
--- /dev/null
@@ -0,0 +1,95 @@
+#ifndef __MONO_SUPPORT_S390X_H__
+#define __MONO_SUPPORT_S390X_H__
+
+#define S390_SET(loc, dr, v)                                   \
+       do {                                                    \
+               guint64 val = (guint64) v;                      \
+               if (s390_is_uimm16(val)) {                      \
+                       s390_llill(loc, dr, val);               \
+               } else if (s390_is_uimm32(val)) {               \
+                       s390_llilf(loc, dr, val);               \
+               } else {                                        \
+                       guint32 hi = (val) >> 32;               \
+                       guint32 lo = (val) & 0xffffffff;        \
+                       s390_iihf(loc, dr, hi);                 \
+                       s390_iilf(loc, dr, lo);                 \
+               }                                               \
+       } while (0)
+
+#define S390_LONG(loc, opy, op, r, ix, br, off)                                \
+       if (s390_is_imm20(off)) {                                       \
+               s390_##opy (loc, r, ix, br, off);                       \
+       } else {                                                        \
+               if (ix == 0) {                                          \
+fprintf(stderr,"\nS390_LONG - no index - r: %d br: %d off: %d\n",r,br,off); \
+                       S390_SET(loc, s390_r13, off);                   \
+                       s390_la (loc, s390_r13, s390_r13, br, 0);       \
+               } else {                                                \
+fprintf(stderr,"\nS390_LONG - index - r: %d br: %d ix: %d off: %d\n",r,br,ix,off); \
+                       s390_la   (loc, s390_r13, ix, br, 0);           \
+                       S390_SET  (loc, s390_r0, off);                  \
+                       s390_agr  (loc, s390_r13, s390_r0);             \
+               }                                                       \
+               s390_##op (loc, r, 0, s390_r13, 0);                     \
+       }
+
+#define S390_SET_MASK(loc, dr, v)                              \
+       do {                                                    \
+               if (s390_is_imm16 (v)) {                        \
+                       s390_lghi (loc, dr, v);                 \
+               } else if (s390_is_imm32 (v)) {                 \
+                       s390_lgfi (loc, dr, v);                 \
+               } else {                                        \
+                       gint64 val = (gint64) v;                \
+                       guint32 hi = (val) >> 32;               \
+                       guint32 lo = (val) & 0xffffffff;        \
+                       s390_iilf(loc, dr, lo);                 \
+                       s390_iihf(loc, dr, hi);                 \
+               }                                               \
+       } while (0)
+
+#define S390_CALL_TEMPLATE(loc, r)                             \
+       do {                                                    \
+               s390_iihf (loc, r, 0);                          \
+               s390_iilf (loc, r, 0);                          \
+               s390_basr (loc, s390_r14, r);                   \
+       } while (0)
+
+#define S390_BR_TEMPLATE(loc, r)                               \
+       do {                                                    \
+               s390_iihf (loc, r, 0);                          \
+               s390_iilf (loc, r, 0);                          \
+               s390_br   (loc, r);                             \
+       } while (0)
+
+#define S390_LOAD_TEMPLATE(loc, r)                             \
+       do {                                                    \
+               s390_iihf (loc, r, 0);                          \
+               s390_iilf (loc, r, 0);                          \
+       } while (0)
+
+#define S390_EMIT_CALL(loc, t)                                 \
+       do {                                                    \
+               gint64 val = (gint64) t;                        \
+               guint32 hi = (val) >> 32;                       \
+               guint32 lo = (val) & 0xffffffff;                \
+               uintptr_t p = (uintptr_t) loc;                  \
+               p += 2;                                         \
+               *(guint32 *) p = hi;                            \
+               p += 6;                                         \
+               *(guint32 *) p = lo;                            \
+       } while (0)
+
+#define S390_EMIT_LOAD(loc, v)                                 \
+       do {                                                    \
+               gint64 val = (gint64) v;                        \
+               guint32 hi = (val) >> 32;                       \
+               guint32 lo = (val) & 0xffffffff;                \
+               uintptr_t p = (uintptr_t) loc;                  \
+               p += 2;                                         \
+               *(guint32 *) p = hi;                            \
+               p += 6;                                         \
+               *(guint32 *) p = lo;                            \
+       } while (0)
+
+#endif /* __MONO_SUPPORT_S390X_H__ */
index 8f2875afdff874cb0cf258b322d5061f3b3087d5..d694c70f01db531db14c953ada975f3bd12c622e 100644 (file)
@@ -53,6 +53,7 @@
 
 #include "mini.h"
 #include "mini-s390x.h"
+#include "support-s390x.h"
 
 /*========================= End of Includes ========================*/
 
@@ -99,10 +100,7 @@ mono_arch_get_unbox_trampoline (MonoMethod *method, gpointer addr)
 
        start = code = mono_domain_code_reserve (domain, 28);
 
-       s390_basr (code, s390_r1, 0);
-       s390_j    (code, 6);
-       s390_llong(code, addr);
-       s390_lg   (code, s390_r1, 0, s390_r1, 4);
+       S390_SET  (code, s390_r1, addr);
        s390_aghi (code, this_pos, sizeof(MonoObject));
        s390_br   (code, s390_r1);
 
@@ -129,27 +127,20 @@ mono_arch_patch_callsite (guint8 *method_start, guint8 *orig_code, guint8 *addr)
        gint32 displace;
        unsigned short opcode;
 
-       opcode = *((unsigned short *) (orig_code - 6));
-       if (opcode == 0xc0e5) {
+       opcode = *((unsigned short *) (orig_code - 2));
+       if (opcode == 0x0dee) {
+               /* This should be a 'iihf/iilf' sequence */
+               S390_EMIT_CALL((orig_code - 14), addr);
+               mono_arch_flush_icache (orig_code - 14, 12);
+       } else {
+fprintf(stderr, "%p %02x %02x %02x %02x\n",
+&orig_code[-14], orig_code[-12], orig_code[-11], orig_code[-6], orig_code[-5]);
+fflush(stderr);
                /* This is the 'brasl' instruction */
                orig_code    -= 4;
                displace = ((gssize) addr - (gssize) (orig_code - 2)) / 2;
                s390_patch_rel (orig_code, displace);
                mono_arch_flush_icache (orig_code, 4);
-       } else {
-               /* This should be a 'lg %r14,4(%r13)' then a 'basr r14, r14' instruction */
-               g_assert (orig_code [-8] == 0xe3);
-               g_assert (orig_code [-7] == 0xe0);
-               g_assert (orig_code [-6] == 0xd0);
-               g_assert (orig_code [-5] == 0x04);
-               g_assert (orig_code [-4] == 0x00);
-               g_assert (orig_code [-3] == 0x04);
-               opcode = *((unsigned short*) (orig_code - 2));
-               g_assert (opcode == 0x0dee);
-
-               /* The call address is stored in the 8 bytes preceeding the basr instruction */
-               s390_patch_addr(orig_code - 16, (gssize)addr);
-               mono_arch_flush_icache (orig_code - 16, 8);
        }
 }
 
@@ -231,7 +222,7 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf
 {
        char *tramp_name;
        guint8 *buf, *tramp, *code;
-       int i, offset, lmfOffset;
+       int i, offset, lmfOffset, has_caller;
        GSList *unwind_ops = NULL;
        MonoJumpInfo *ji = NULL;
 
@@ -242,6 +233,12 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf
                
        code = buf = mono_global_codeman_reserve(512);
                
+       if ((tramp_type == MONO_TRAMPOLINE_JUMP) ||
+           (tramp_type == MONO_TRAMPOLINE_HANDLER_BLOCK_GUARD)) 
+               has_caller = 0;
+       else
+               has_caller = 1;
+
        /*-----------------------------------------------------------
          STEP 0: First create a non-standard function prologue with a
          stack size big enough to save our registers.
@@ -268,10 +265,7 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf
          method.
          ----------------------------------------------------------*/
                                
-       s390_basr (buf, s390_r13, 0);
-       s390_j    (buf, 6);
-       s390_llong(buf, mono_get_lmf_addr);
-       s390_lg   (buf, s390_r1, 0, s390_r13, 4);
+       S390_SET  (buf, s390_r1, mono_get_lmf_addr);
        s390_basr (buf, s390_r14, s390_r1);
 
        /*---------------------------------------------------------------*/
@@ -321,11 +315,10 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf
        /*---------------------------------------------------------------*/     
        /* save the current IP                                           */     
        /*---------------------------------------------------------------*/     
-       if (tramp_type == MONO_TRAMPOLINE_JUMP) {
-               s390_lghi  (buf, s390_r1, 0);
-       } else {
+       if (has_caller) {
                s390_lg    (buf, s390_r1, 0, s390_r1, S390_RET_ADDR_OFFSET);
-               //                      s390_la    (buf, s390_r1, 0, s390_r1, 0);
+       } else {
+               s390_lghi  (buf, s390_r1, 0);
        }
        s390_stg   (buf, s390_r1, 0, s390_r13, G_STRUCT_OFFSET(MonoLMF, eip));  
                                                                                        
@@ -351,10 +344,10 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf
        s390_la  (buf, s390_r2, 0, STK_BASE, CREATE_STACK_SIZE);
                
        /* Arg 2: code (next address to the instruction that called us) */
-       if (tramp_type == MONO_TRAMPOLINE_JUMP) {
-               s390_lghi (buf, s390_r3, 0);
-       } else {
+       if (has_caller) {
                s390_lg   (buf, s390_r3, 0, s390_r11, S390_RET_ADDR_OFFSET);
+       } else {
+               s390_lghi (buf, s390_r3, 0);
        }
 
        /* Arg 3: Trampoline argument */
@@ -366,11 +359,8 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf
        /* Arg 4: trampoline address. Ignore for now */
                
        /* Calculate call address and call the C trampoline. Return value will be in r2 */
-       s390_basr (buf, s390_r13, 0);
-       s390_j    (buf, 6);
        tramp = (guint8*)mono_get_trampoline_func (tramp_type);
-       s390_llong (buf, tramp);
-       s390_lg   (buf, s390_r1, 0, s390_r13, 4);
+       S390_SET  (buf, s390_r1, tramp);
        s390_basr (buf, s390_r14, s390_r1);
                
        /* OK, code address is now on r2. Move it to r1, so that we
@@ -426,6 +416,28 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf
 
 /*========================= End of Function ========================*/
 
+/*------------------------------------------------------------------*/
+/*                                                                  */
+/* Name                - mono_arch_invalidate_method                       */
+/*                                                                  */
+/* Function    -                                                   */
+/*                                                                  */
+/*------------------------------------------------------------------*/
+
+void
+mono_arch_invalidate_method (MonoJitInfo *ji, void *func, gpointer func_arg)
+{
+       /* FIXME: This is not thread safe */
+       guint8 *code = ji->code_start;
+
+       S390_SET  (code, s390_r1, func);
+       S390_SET  (code, s390_r2, func_arg);
+       s390_br   (code, s390_r1);
+
+}
+
+/*========================= End of Function ========================*/
+
 /*------------------------------------------------------------------*/
 /*                                                                  */
 /* Name                - mono_arch_create_specific_trampoline              */
@@ -449,10 +461,7 @@ mono_arch_create_specific_trampoline (gpointer arg1, MonoTrampolineType tramp_ty
        /*----------------------------------------------------------*/
        code = buf = mono_domain_code_reserve (domain, SPECIFIC_TRAMPOLINE_SIZE);
 
-       s390_basr (buf, s390_r1, 0);
-       s390_j    (buf, 6);
-       s390_llong(buf, arg1);
-       s390_lg   (buf, s390_r1, 0, s390_r1, 4);
+       S390_SET  (buf, s390_r1, arg1);
        displace = (tramp - buf) / 2;
        s390_jg   (buf, displace);
 
@@ -615,10 +624,7 @@ mono_arch_get_static_rgctx_trampoline (MonoMethod *m,
 
        start = code = mono_domain_code_reserve (domain, buf_len);
 
-       s390_basr (code, s390_r1, 0);
-       s390_j    (code, 6);
-       s390_llong(code, mrgctx);
-       s390_lg   (code, MONO_ARCH_RGCTX_REG, 0, s390_r1, 4);
+       S390_SET  (code, MONO_ARCH_RGCTX_REG, mrgctx);
        displace = ((uintptr_t) addr - (uintptr_t) code) / 2;
        s390_jg   (code, displace);
        g_assert ((code - start) < buf_len);
@@ -630,6 +636,80 @@ mono_arch_get_static_rgctx_trampoline (MonoMethod *m,
 
 /*========================= End of Function ========================*/
 
+/*------------------------------------------------------------------*/
+/*                                                                  */
+/* Name                - handler_block_trampoline_helper                   */
+/*                                                                  */
+/* Function    -                                                   */
+/*                                                                  */
+/*------------------------------------------------------------------*/
+
+static void
+handler_block_trampoline_helper (gpointer *ptr)
+{
+       MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
+       *ptr = jit_tls->handler_block_return_address;
+}
+
+/*========================= End of Function ========================*/
+
+/*------------------------------------------------------------------*/
+/*                                                                  */
+/* Name                - mono_arch_create_handler_block_trampoline         */
+/*                                                                  */
+/* Function    -                                                   */
+/*                                                                  */
+/*------------------------------------------------------------------*/
+
+gpointer
+mono_arch_create_handler_block_trampoline (MonoTrampInfo **info, gboolean aot)
+{
+       guint8 *tramp = mono_get_trampoline_code (MONO_TRAMPOLINE_HANDLER_BLOCK_GUARD);
+       guint8 *code, *buf;
+       int tramp_size = 64;
+       MonoJumpInfo *ji = NULL;
+       GSList *unwind_ops = NULL;
+
+       g_assert (!aot);
+
+       code = buf = mono_global_codeman_reserve (tramp_size);
+
+       /*
+        * This trampoline restore the call chain of the handler block 
+        * then jumps into the code that deals with it.
+        */
+
+       if (mono_get_jit_tls_offset () != -1) {
+               s390_ear  (code, s390_r1, 0);
+               s390_sllg (code, s390_r1, s390_r1, 0, 32);
+               s390_ear  (code, s390_r1, 1);
+               S390_SET  (code, s390_r14, mono_get_jit_tls_offset());
+               s390_lg   (code, s390_r14, s390_r1, 0, G_STRUCT_OFFSET(MonoJitTlsData, handler_block_return_address));
+               /* 
+                * Simulate a call 
+                */
+               S390_SET  (code, s390_r1, tramp);
+               s390_br   (code, s390_r1);
+       } else {
+               /*
+                * Slow path uses a C helper
+                */
+               S390_SET  (code, s390_r2, tramp);
+               S390_SET  (code, s390_r1, handler_block_trampoline_helper);
+               s390_br   (code, s390_r1);
+       }
+
+       mono_arch_flush_icache (buf, code - buf);
+       g_assert (code - buf <= tramp_size);
+
+       if (info)
+               *info = mono_tramp_info_create ("handler_block_trampoline", buf, code - buf, ji, unwind_ops);
+
+       return buf;
+}
+
+/*========================= End of Function ========================*/
+
 /*------------------------------------------------------------------*/
 /*                                                                  */
 /* Name                - mono_arch_create_generic_class_init_trampoline    */
@@ -645,7 +725,6 @@ mono_arch_create_generic_class_init_trampoline (MonoTrampInfo **info, gboolean a
        guint8 *code, *buf;
        static int byte_offset = -1;
        static guint8 bitmask;
-       guint8 *jump;
        gint32 displace;
        int tramp_size;
        GSList *unwind_ops = NULL;
index d2f2bc5a4a9735030f340a91f861a38fac9d01c8..d5c9d254c3c95cd31648f2e6a44fb66fd1d2e483 100644 (file)
  */
 
 #include "mono/utils/mono-hwcap-s390x.h"
-
 #include <signal.h>
 
-gboolean mono_hwcap_s390x_has_ld = FALSE;
-
-static void
-catch_sigill (int sig_no, siginfo_t *info, gpointer act)
-{
-       mono_hwcap_s390x_has_ld = FALSE;
-}
+facilityList_t facs;
 
 void
 mono_hwcap_arch_init (void)
 {
-       mono_hwcap_s390x_has_ld = TRUE;
-
-       struct sigaction sa, *old_sa;
-
-       /* Determine if we have a long displacement facility
-        * by executing the STY instruction. If it fails, we
-        * catch the SIGILL and assume the answer is no.
-        */
-       sa.sa_sigaction = catch_sigill;
-       sigemptyset (&sa.sa_mask);
-       sa.sa_flags = SA_SIGINFO;
-
-       sigaction (SIGILL, &sa, old_sa);
-
-       __asm__ __volatile__ (
-               "LGHI\t0,1\n\t"
-               "LA\t1,%0\n\t"
-               ".byte\t0xe3,0x00,0x10,0x00,0x00,0x50\n\t"
-               : "=m" (mono_hwcap_s390x_has_ld)
-               :
-               : "0", "1"
-       );
+       int lFacs = sizeof(facs) / 8;
 
-       sigaction (SIGILL, old_sa, NULL);
+       __asm__ ("      lgfr    0,%1\n"
+                "      .insn   s,0xb2b00000,%0\n"
+                : "=m" (facs) : "r" (lFacs) : "0", "cc");
 }
 
 void
 mono_hwcap_print (FILE *f)
 {
-       g_fprintf (f, "mono_hwcap_s390x_has_ld = %i\n", mono_hwcap_s390x_has_ld);
 }
index 24c76a28545a429f63072de1c7c22ed772ef0947..313aca8bcb432fbd174cfd6deaaab76a04ef1514 100644 (file)
@@ -3,6 +3,84 @@
 
 #include "mono/utils/mono-hwcap.h"
 
-extern gboolean mono_hwcap_s390x_has_ld;
+typedef struct
+{
+       char    n3:1;           // N3 instructions present
+       char    zArch:1;        // z/Architecture mode installed
+       char    zAct:1;         // z/Architecture mode active
+       char    date:1;         // DAT enhancement facility
+       char    idte1:1;        // IDTE present (PST)
+       char    idte2:1;        // IDTE present (REG)
+       char    asnlx:1;        // ASN and LX reuse facility
+       char    stfle:1;        // STFLE installed
+       char    zDATe:1;        // Enhanced DAT in z mode
+       char    srstat:1;       // Sense running status facility
+       char    cSSKE:1;        // Conditional SSKE facility
+       char    topo:1;         // Configuration topology facility
+       char    rv1:1;          // Reserved
+       char    xTrans2:1;      // Extended translation facility 2
+       char    msgSec:1;       // Message security facility
+       char    longDsp:1;      // Long displacement facility
+       char    hiPerfLD:1;     // High performance long displacement facility
+       char    hfpMAS:1;       // HFP multiply-and-add/subtrace facility
+       char    xImm:1;         // Extended immediate facility
+       char    xTrans3:1;      // Extended translation facility 3
+       char    hfpUnX:1;       // HFP unnormalized extension facility
+       char    etf2:1;         // ETF2-enhancement facility
+       char    stckf:1;        // Store-clock-fast facility
+       char    parse:1;        // Parsing enhancement facility
+       char    mvcos:1;        // MVCOS facility
+       char    todSteer:1;     // TOD-clock steering facility
+       char    etf3:1;         // ETF3-enhancement facility
+       char    xCPUtm:1;       // Extract CPU time facility
+       char    csst:1;         // Compare-swap-and-store facility
+       char    csst2:1;        // Compare-swap-and-store facility 2
+       char    giX:1;          // General instructions extension facility
+       char    exX:1;          // Execute extensions facility
+       char    em:1;           // Enhanced monitor
+       char    rv2:1;          // Reserved
+       char    spp:1;          // Set program parameters
+       char    fps:1;          // Floating point support enhancement
+       char    dfp:1;          // Decimal floating point facility
+       char    hiDFP:1;        // High Performance DFP facility
+       char    pfpo:1;         // PFPO instruction facility
+       char    doclpkia:1;     // DO/Fast BCR/CL/PK/IA
+       char    rv3:1;          // Reserved
+       char    cmpsce:1;       // CMPSC enhancement
+       char    dfpzc:1;        // DFP zoned-conversion
+       char    eh:1;           // Execution hint
+       char    lt:1;           // Load and trap
+       char    mi:1;           // Miscellaneous instruction enhancements
+       char    pa:1;           // Processor assist
+       char    cx:1;           // Constrained transactional execution
+       char    ltlb:1;         // Local TLB clearing
+       char    ia2:1;          // Interlocked access 2
+       char    rv4:1;          // Reserved;
+       char    rv5:1;          // Reserved;
+       char    rv6:1;          // Reserved;
+       char    rv7:1;          // Reserved;
+       char    rv8:1;          // Reserved;
+       char    rv9:1;          // Reserved;
+       char    rva:1;          // Reserved;
+       char    rvb:1;          // Reserved;
+       char    rvc:1;          // Reserved;
+       char    rvd:1;          // Reserved;
+       char    rve:1;          // Reserved;
+       char    rvf:1;          // Reserved;
+       char    rvg:1;          // Reserved;
+       char    rb:1;           // RRB multiple
+       char    cmc:1;          // CPU measurement counter
+       char    cms:1;          // CPU measurement sampling
+       char    rvh:4;          // Reserved
+       char    tx:1;           // Transactional execution
+       char    rvi:1;          // Reserved
+       char    axsi:1;         // Access exception/store indication
+       char    m3:1;           // Message security extension 3
+       char    m4:1;           // Message security extension 4
+       char    ed2:1;          // Enhanced DAT 2
+       int64_t end[0];         // End on a double word
+} __attribute__((aligned(8))) facilityList_t;
+       
+extern facilityList_t facs;
 
 #endif /* __MONO_UTILS_HWCAP_S390X_H__ */