From: Neale Ferguson Date: Tue, 3 Jun 2014 15:52:00 +0000 (-0400) Subject: Architectural level set to z10 instruction set X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=commitdiff_plain;h=4dfae5ba82d30b9465f1ba5d82789b4748a23955;p=mono.git Architectural level set to z10 instruction set --- diff --git a/mono/arch/s390x/s390x-codegen.h b/mono/arch/s390x/s390x-codegen.h index 3677b2d95b1..47e656422ee 100644 --- a/mono/arch/s390x/s390x-codegen.h +++ b/mono/arch/s390x/s390x-codegen.h @@ -6,6 +6,7 @@ #define S390X_H #include #include +#include #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 diff --git a/mono/mini/cpu-s390x.md b/mono/mini/cpu-s390x.md index be6a3509d1d..34b6cdb271e 100644 --- a/mono/mini/cpu-s390x.md +++ b/mono/mini/cpu-s390x.md @@ -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 diff --git a/mono/mini/mini-s390x.c b/mono/mini/mini-s390x.c index 5374adc8b02..5d88174bac1 100644 --- a/mono/mini/mini-s390x.c +++ b/mono/mini/mini-s390x.c @@ -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 +#include +#include #include #include @@ -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) { diff --git a/mono/mini/mini-s390x.h b/mono/mini/mini-s390x.h index a5be8f01087..8ca5fb27ad2 100644 --- a/mono/mini/mini-s390x.h +++ b/mono/mini/mini-s390x.h @@ -14,29 +14,6 @@ /* 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 index 00000000000..3ae4c48572a --- /dev/null +++ b/mono/mini/support-s390x.h @@ -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__ */ diff --git a/mono/mini/tramp-s390x.c b/mono/mini/tramp-s390x.c index 8f2875afdff..d694c70f01d 100644 --- a/mono/mini/tramp-s390x.c +++ b/mono/mini/tramp-s390x.c @@ -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; diff --git a/mono/utils/mono-hwcap-s390x.c b/mono/utils/mono-hwcap-s390x.c index d2f2bc5a4a9..d5c9d254c3c 100644 --- a/mono/utils/mono-hwcap-s390x.c +++ b/mono/utils/mono-hwcap-s390x.c @@ -19,48 +19,21 @@ */ #include "mono/utils/mono-hwcap-s390x.h" - #include -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); } diff --git a/mono/utils/mono-hwcap-s390x.h b/mono/utils/mono-hwcap-s390x.h index 24c76a28545..313aca8bcb4 100644 --- a/mono/utils/mono-hwcap-s390x.h +++ b/mono/utils/mono-hwcap-s390x.h @@ -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__ */