diff options
Diffstat (limited to 'src/arch/s390x')
-rw-r--r-- | src/arch/s390x/.gitignore | 6 | ||||
-rw-r--r-- | src/arch/s390x/ChangeLog | 35 | ||||
-rw-r--r-- | src/arch/s390x/Makefile.am | 7 | ||||
-rw-r--r-- | src/arch/s390x/s390x-codegen.h | 997 | ||||
-rw-r--r-- | src/arch/s390x/tramp.c | 1149 |
5 files changed, 2194 insertions, 0 deletions
diff --git a/src/arch/s390x/.gitignore b/src/arch/s390x/.gitignore new file mode 100644 index 0000000..341daec --- /dev/null +++ b/src/arch/s390x/.gitignore @@ -0,0 +1,6 @@ +/Makefile +/Makefile.in +/.libs +/.deps +/*.la +/*.lo diff --git a/src/arch/s390x/ChangeLog b/src/arch/s390x/ChangeLog new file mode 100644 index 0000000..e756d35 --- /dev/null +++ b/src/arch/s390x/ChangeLog @@ -0,0 +1,35 @@ +2010-03-23 Neale Ferguson <neale@sinenomine.net> + + * s390x-codegen.h: Remove duplicate + +2009-06-24 Neale Ferguson <neale@sinenomine.net> + + * s390x-codegen.h: Add some new instructions. + +2007-04-12 Neale Ferguson <neale@sinenomine.net> + + * tramp.c: Add MONO_TYPE_PTR case. + +2007-01-23 Neale Ferguson <neale@sinenomine.net> + + * s390x-codegen.h: Add packed attribute to several instruction structures. + +2006-03-13 Neale Ferguson <neale@sinenomine.net> + + * s390x-codegen.h: Fix immediate checks. + +2006-01-06 Neale Ferguson <neale@sinenomine.net> + + * s390x-codegen.h: Add lpdbr instruction (OP_ABS). + +2006-01-03 Neale Ferguson <neale@sinenomine.net> + + * s390x-codegen.h: Add some new instructions. + +2004-12-15 Neale Ferguson <Neale.Ferguson@SoftwareAG-usa.com> + + * s390x-codegen.h: Add some new instructions (CS, CSG, CSY, CDS, CDSG, CDSY) + +2004-08-03 Neale Ferguson <Neale.Ferguson@SoftwareAG-usa.com> + + * s390x-codegen.h Makefile.am tramp.c: S/390 64-bit interpreter diff --git a/src/arch/s390x/Makefile.am b/src/arch/s390x/Makefile.am new file mode 100644 index 0000000..ce7f470 --- /dev/null +++ b/src/arch/s390x/Makefile.am @@ -0,0 +1,7 @@ + +AM_CPPFLAGS = $(GLIB_CFLAGS) -I$(top_srcdir) + +noinst_LTLIBRARIES = libmonoarch-s390x.la + +libmonoarch_s390x_la_SOURCES = tramp.c s390x-codegen.h + diff --git a/src/arch/s390x/s390x-codegen.h b/src/arch/s390x/s390x-codegen.h new file mode 100644 index 0000000..47e6564 --- /dev/null +++ b/src/arch/s390x/s390x-codegen.h @@ -0,0 +1,997 @@ +/* + Copyright (C) 2001 Radek Doulik +*/ + +#ifndef S390X_H +#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 */ + +#define ARG_BASE s390_r10 /* Register for addressing arguments*/ +#define STKARG \ + (i*(sizeof(stackval))) /* Displacement of ith argument */ + +#define MINV_POS 160 /* MonoInvocation stack offset */ +#define STACK_POS (MINV_POS - sizeof (stackval) * sig->param_count) +#define OBJ_POS 8 +#define TYPE_OFFSET (G_STRUCT_OFFSET (stackval, type)) + +#define MIN_CACHE_LINE 256 + +/*------------------------------------------------------------------*/ +/* Sequence to add an int/long long to parameters to stack_from_data*/ +/*------------------------------------------------------------------*/ +#define ADD_ISTACK_PARM(r, i) \ + if (reg_param < GENERAL_REGS-(r)) { \ + s390_lay (p, s390_r4, 0, STK_BASE, \ + local_start + (reg_param - this_flag) * sizeof(long)); \ + reg_param += (i); \ + } else { \ + s390_lay (p, s390_r4, 0, STK_BASE, \ + sz.stack_size + MINV_POS + stack_param * sizeof(long)); \ + stack_param += (i); \ + } + +/*------------------------------------------------------------------*/ +/* Sequence to add a float/double to parameters to stack_from_data */ +/*------------------------------------------------------------------*/ +#define ADD_RSTACK_PARM(i) \ + if (fpr_param < FLOAT_REGS) { \ + s390_lay (p, s390_r4, 0, STK_BASE, \ + float_pos + (fpr_param * sizeof(float) * (i))); \ + fpr_param++; \ + } else { \ + stack_param += (stack_param % (i)); \ + s390_lay (p, s390_r4, 0, STK_BASE, \ + sz.stack_size + MINV_POS + stack_param * sizeof(float) * (i)); \ + stack_param += (i); \ + } + +/*------------------------------------------------------------------*/ +/* Sequence to add a structure ptr to parameters to stack_from_data */ +/*------------------------------------------------------------------*/ +#define ADD_TSTACK_PARM \ + if (reg_param < GENERAL_REGS) { \ + s390_ly (p, s390_r4, 0, STK_BASE, \ + local_start + (reg_param - this_flag) * sizeof(long)); \ + reg_param++; \ + } else { \ + s390_ly (p, s390_r4, 0, STK_BASE, \ + sz.stack_size + MINV_POS + stack_param * sizeof(long)); \ + stack_param++; \ + } + +#define ADD_PSTACK_PARM(r, i) \ + if (reg_param < GENERAL_REGS-(r)) { \ + s390_lay (p, s390_r4, 0, STK_BASE, \ + local_start + (reg_param - this_flag) * sizeof(long)); \ + reg_param += (i); \ + } else { \ + s390_ly (p, s390_r4, 0, STK_BASE, \ + sz.stack_size + MINV_POS + stack_param * sizeof(long)); \ + stack_param++; \ + } + +typedef enum { + s390_r0 = 0, + s390_r1, + s390_r2, + s390_r3, + s390_r4, + s390_r5, + s390_r6, + s390_r7, + s390_r8, + s390_r9, + s390_r10, + s390_r11, + s390_r12, + s390_r13, + s390_r14, + s390_r15, +} S390IntRegister; + +typedef enum { + s390_f0 = 0, + s390_f1, + s390_f2, + s390_f3, + s390_f4, + s390_f5, + s390_f6, + s390_f7, + s390_f8, + s390_f9, + s390_f10, + s390_f11, + s390_f12, + s390_f13, + s390_f14, + s390_f15, +} S390FloatRegister; + +typedef enum { + s390_a0 = 0, + s390_a1, + s390_a2, + s390_a3, + s390_a4, + s390_a5, + s390_a6, + s390_a7, + s390_a8, + s390_a9, + s390_a10, + s390_a11, + s390_a12, + s390_a13, + s390_a14, + s390_a15, +} S390AccRegister; + +typedef enum { + s390_fpc = 256, +} S390SpecialRegister; + +#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)-4096 && \ + (glong)val <= (glong)4095) +#define s390_is_uimm12(val) ((glong)val >= 0 && (glong)val <= 4095) + +#define STK_BASE s390_r15 +#define S390_SP s390_r15 +#define S390_FP s390_r11 +#define S390_MINIMAL_STACK_SIZE 160 +#define S390_REG_SAVE_OFFSET 48 +#define S390_PARM_SAVE_OFFSET 16 +#define S390_RET_ADDR_OFFSET 112 +#define S390_FLOAT_SAVE_OFFSET 128 + +#define S390_CC_ZR 8 +#define S390_CC_NE 7 +#define S390_CC_NZ 7 +#define S390_CC_LT 4 +#define S390_CC_GT 2 +#define S390_CC_GE 11 +#define S390_CC_NM 11 +#define S390_CC_LE 13 +#define S390_CC_OV 1 +#define S390_CC_NO 14 +#define S390_CC_CY 3 +#define S390_CC_NC 12 +#define S390_CC_UN 15 + +#define s390_word(addr, value) do \ +{ \ + * (guint32 *) addr = (guint32) value; \ + addr += sizeof(guint32); \ +} while (0) + +#define s390_float(addr, value) do \ +{ \ + * (gfloat *) addr = (gfloat) value; \ + addr += sizeof(gfloat); \ +} while (0) + +#define s390_llong(addr, value) do \ +{ \ + * (guint64 *) addr = (guint64) value; \ + addr += sizeof(guint64); \ +} while (0) + +#define s390_double(addr, value) do \ +{ \ + * (gdouble *) addr = (gdouble) value; \ + addr += sizeof(gdouble); \ +} while (0) + +typedef struct { + short op; +} E_Format; + +typedef struct { + char op; + int im; +} I_Format; + +typedef struct { + char op; + char r1 : 4; + char r2 : 4; +} RR_Format; + +typedef struct { + short op; + char xx; + char r1 : 4; + char r2 : 4; +} RRE_Format; + +typedef struct { + short op; + char r1 : 4; + char xx : 4; + char r3 : 4; + char r2 : 4; +} RRF_Format_1; + +typedef struct { + short op; + char m3 : 4; + char xx : 4; + char r1 : 4; + char r2 : 4; +} RRF_Format_2; + +typedef struct { + short op; + char r3 : 4; + char m4 : 4; + char r1 : 4; + char r2 : 4; +} RRF_Format_3; + +typedef struct { + char op; + char r1 : 4; + char x2 : 4; + char b2 : 4; + short d2 : 12; +} RX_Format; + +typedef struct { + char op1; + char r1 : 4; + char x2 : 4; + char b2 : 4; + int d2 : 12; + char xx; + char op2; +} RXE_Format; + +typedef struct { + char op1; + char r3 : 4; + char x2 : 4; + char b2 : 4; + int d2 : 12; + char r1 : 4; + char xx : 4; + char op2; +} RXF_Format; + +typedef struct { + char op1; + char r1 : 4; + char x2 : 4; + char b2 : 4; + int d2 : 20; + char op2; +} __attribute__ ((packed)) RXY_Format; + +typedef struct { + char op; + char r1 : 4; + char r3 : 4; + char b2 : 4; + int d2 : 12; +} RS_Format_1; + +typedef struct { + char op; + char r1 : 4; + char m3 : 4; + char b2 : 4; + int d2 : 12; +} RS_Format_2; + +typedef struct { + char op; + char r1 : 4; + char xx : 4; + char b2 : 4; + int d2 : 12; +} RS_Format_3; + +typedef struct { + char op1; + char r1 : 4; + char r3 : 4; + char b2 : 4; + int d2 : 20; + char op2; +} __attribute__ ((packed)) RSY_Format_1; + +typedef struct { + char op1; + char r1 : 4; + char m3 : 4; + char b2 : 4; + int d2 : 20; + char op2; +} __attribute__ ((packed)) RSY_Format_2; + +typedef struct { + char op1; + char l1 : 4; + char xx : 4; + char b1 : 4; + int d1 : 12; + char yy; + char op2; +} RSL_Format; + +typedef struct { + char op; + char r1 : 4; + char r3 : 4; + short i2; +} RSI_Format; + +typedef struct { + char op1; + char m1 : 4; + char op2 : 4; + short i2; +} RI_Format; + +typedef struct { + char op1; + char r1 : 4; + char r3 : 4; + short i2; + char xx; + char op2; +} 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; + char r1 : 4; + char op2 : 4; + int i2; +} __attribute__ ((packed)) RIL_Format_1; + +typedef struct { + char op1; + char m1 : 4; + char op2 : 4; + int i2; +} __attribute__ ((packed)) RIL_Format_2; + +typedef struct { + char op; + char i2; + char b1 : 4; + short d1 : 12; +} SI_Format; + +typedef struct { + char op1; + char i2; + char b1 : 4; + int d1 : 20; + char op2; +} __attribute__ ((packed)) SIY_Format; + +typedef struct { + short op; + char b2 : 4; + short d2 : 12; +} S_Format; + +typedef struct { + char op; + char ll; + char b1 : 4; + short d1 : 12; + char b2 : 4; + short d2 : 12; +} SS_Format_1; + +typedef struct { + char op; + char l1 : 4; + char l2 : 4; + char b1 : 4; + short d1 : 12; + char b2 : 4; + short d2 : 12; +} SS_Format_2; + +typedef struct { + char op; + char r1 : 4; + char r3 : 4; + char b1 : 4; + short d1 : 12; + char b2 : 4; + short d2 : 12; +} SS_Format_3; + +typedef struct { + char op; + char r1 : 4; + char r3 : 4; + char b2 : 4; + short d2 : 12; + char b4 : 4; + short d4 : 12; +} SS_Format_4; + +typedef struct { + short op; + short tb1 : 4; + short d1 : 12; + 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; \ + c += sizeof(guint16); \ +} while(0) + +#define s390_emit32(c, x) do \ +{ \ + *((guint32 *) c) = (guint32) x; \ + c += sizeof(guint32); \ +} while(0) + +#define S390_E(c,opc) s390_emit16(c,opc) + +#define S390_I(c,opc,imm) s390_emit16(c, (opc << 8 | imm)) + +#define S390_RR(c,opc,g1,g2) s390_emit16(c, (opc << 8 | (g1) << 4 | g2)) + +#define S390_RRE(c,opc,g1,g2) s390_emit32(c, (opc << 16 | (g1) << 4 | g2)) + +#define S390_RRF_1(c,opc,g1,g2,g3) s390_emit32(c, (opc << 16 | (g1) << 12 | (g3) << 4 | g2)) + +#define S390_RRF_2(c,opc,g1,k3,g2) s390_emit32(c, (opc << 16 | (k3) << 12 | (g1) << 4 | g2)) + +#define S390_RRF_3(c,opc,g1,g2,k4,g3) s390_emit32(c, (opc << 16 | (g3) << 12 | (k4) << 8 | (g1) << 4 | g2)) + +#define S390_RX(c,opc,g1,n2,s2,p2) s390_emit32(c, (opc << 24 | (g1) << 20 | (n2) << 16 | (s2) << 12 | ((p2) & 0xfff))) + +#define S390_RXE(c,opc,g1,n2,s2,p2) do \ +{ \ + s390_emit16(c, ((opc & 0xff00) | (g1) << 4 | n2)); \ + s390_emit32(c, ((s2) << 28 | (((p2) & 0xfff) << 16) | \ + (opc & 0xff))); \ +} while (0) + +#define S390_RXY(c,opc,g1,n2,s2,p2) do \ +{ \ + s390_emit16(c, ((opc & 0xff00) | (g1) << 4 | n2)); \ + s390_emit32(c, ((s2) << 28 | (((p2) & 0xfff) << 16) | \ + ((((p2) & 0xff000) >> 12) << 8) | \ + (opc & 0xff))); \ +} while (0) + +#define S390_RS_1(c,opc,g1,g3,s2,p2) s390_emit32(c, (opc << 24 | (g1) << 20 | (g3) << 16 | (s2) << 12 | ((p2) & 0xfff))) + +#define S390_RS_2(c,opc,g1,k3,s2,p2) s390_emit32(c, (opc << 24 | (g1) << 20 | (k3) << 16 | (s2) << 12 | ((p2) & 0xfff))) + +#define S390_RS_3(c,opc,g1,s2,p2) s390_emit32(c, (opc << 24 | (g1) << 20 | (s2) << 12 | ((p2) & 0xfff))) + +#define S390_RSY_1(c,opc,g1,g3,s2,p2) do \ +{ \ + s390_emit16(c, ((opc & 0xff00) | (g1) << 4 | g3)); \ + s390_emit32(c, ((s2) << 28 | (((p2) & 0xfff) << 16) | \ + ((((p2) & 0xff000) >> 12) << 8) | \ + (opc & 0xff))); \ +} while (0) + +#define S390_RSY_2(c,opc,g1,k3,s2,p2) do \ +{ \ + s390_emit16(c, ((opc & 0xff00) | (g1) << 4 | k3)); \ + s390_emit32(c, ((s2) << 28 | (((p2) & 0xfff) << 16) | \ + ((((p2) & 0xff000) >> 12) << 8) | \ + (opc & 0xff))); \ +} while (0) + +#define S390_RSL(c,opc,ln,s1,p1) do \ +{ \ + s390_emit16(c, ((opc & 0xff00) | (ln) << 4)); \ + s390_emit32(c, ((s1) << 28 | ((s1 & 0xfff) << 16) | \ + (opc & 0xff))); \ +} while (0) + +#define S390_RSI(c,opc,g1,g3,m2) s390_emit32(c, (opc << 24 | (g1) << 20 | (g3) << 16 | (m2 & 0xffff))) + +#define S390_RI(c,opc,g1,m2) s390_emit32(c, ((opc >> 4) << 24 | (g1) << 20 | (opc & 0x0f) << 16 | (m2 & 0xffff))) + +#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))); \ + s390_emit32(c, m2); \ +} while (0) + +#define S390_RIL_2(c,opc,k1,m2) do \ +{ \ + s390_emit16(c, ((opc >> 4) << 8 | (k1) << 4 | (opc & 0xf))); \ + 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 \ +{ \ + s390_emit16(c, ((opc & 0xff00) | m2)); \ + s390_emit32(c, ((s1) << 24 | (((p2) & 0xfffff) << 8) | \ + (opc & 0xff))); \ +} while (0) + +#define S390_S(c,opc,s2,p2) s390_emit32(c, (opc << 16 | (s2) << 12 | ((p2) & 0xfff))) + +#define S390_SS_1(c,opc,ln,s1,p1,s2,p2) do \ +{ \ + s390_emit32(c, (opc << 24 | ((ln-1) & 0xff) << 16 | \ + (s1) << 12 | ((p1) & 0xfff))); \ + s390_emit16(c, ((s2) << 12 | ((p2) & 0xfff))); \ +} while (0) + +#define S390_SS_2(c,opc,n1,n2,s1,p1,s2,p2) do \ +{ \ + s390_emit32(c, (opc << 24 | (n1) << 16 | (n2) << 12 | \ + (s1) << 12 | ((p1) & 0xfff))); \ + s390_emit16(c, ((s2) << 12 | ((p2) & 0xfff))); \ +} while (0) + +#define S390_SS_3(c,opc,g1,g3,s1,p1,s2,p2) do \ +{ \ + s390_emit32(c, (opc << 24 | (g1) << 16 | (g3) << 12 | \ + (s1) << 12 | ((p1) & 0xfff))); \ + s390_emit16(c, ((s2) << 12 | ((p2) & 0xfff))); \ +} while (0) + +#define S390_SS_4(c,opc,g1,g3,s2,p2,s4,p4) do \ +{ \ + s390_emit32(c, (opc << 24 | (g1) << 16 | (g3) << 12 | \ + (s2) << 12 | ((p2) & 0xfff))); \ + s390_emit16(c, ((s4) << 12 | ((p4) & 0xfff))); \ +} while (0) + +#define S390_SSE(c,opc,s1,p1,s2,p2) do \ +{ \ + s390_emit16(c, opc); \ + s390_emit16(c, ((s1) << 12 | ((p1) & 0xfff))); \ + 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_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) +#define s390_bnzr(c, r) S390_RR(c, 0x07, 0x07, r) +#define s390_bras(c, r, o) S390_RI(c, 0xa75, r, o) +#define s390_brasl(c, r, o) S390_RIL_1(c, 0xc05, r, o) +#define s390_brc(c, m, d) S390_RI(c, 0xa74, m, d) +#define s390_brcl(c, m, d) S390_RIL_2(c, 0xc04, m, d) +#define s390_br(c, r) S390_RR(c, 0x07, 0xf, r) +#define s390_break(c) S390_RR(c, 0, 0, 0) +#define s390_bzr(c, r) S390_RR(c, 0x07, 0x08, r) +#define s390_c(c, r, x, b, d) S390_RX(c, 0x59, r, x, b, d) +#define s390_cdb(c, r, x, b, d) S390_RXE(c, 0xed19, r, x, b, d) +#define s390_cdbr(c, r1, r2) S390_RRE(c, 0xb319, r1, r2) +#define s390_cdfbr(c, r1, r2) S390_RRE(c, 0xb395, r1, r2) +#define s390_cdgbr(c, r1, r2) S390_RRE(c, 0xb3a5, r1, r2) +#define s390_cds(c, r1, r2, b, d) S390_RX(c, 0xbb, r1, r2, b, d) +#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) +#define s390_didbr(c, r1, r2, m, r3) S390_RRF_3(c, 0xb35b, r1, r2, m, r3) +#define s390_dlgr(c, r1, r2) S390_RRE(c, 0xb987, r1, r2) +#define s390_dlr(c, r1, r2) S390_RRE(c, 0xb997, r1, r2) +#define s390_dr(c, r1, r2) S390_RR(c, 0x1d, r1, r2) +#define s390_dsgfr(c, r1, r2) S390_RRE(c, 0xb91d, r1, r2) +#define s390_dsgr(c, r1, r2) S390_RRE(c, 0xb90d, r1, r2) +#define s390_ear(c, r1, r2) S390_RRE(c, 0xb24f, r1, r2) +#define s390_ic(c, r, x, b, d) S390_RX(c, 0x43, r, x, b, d) +#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) +#define s390_jcy(c, d) s390_brc(c, S390_CC_CY, d) +#define s390_je(c, d) s390_brc(c, S390_CC_EQ, d) +#define s390_jeo(c, d) s390_brc(c, S390_CC_ZR|S390_CC_OV, d) +#define s390_jh(c, d) s390_brc(c, S390_CC_GT, d) +#define s390_jho(c, d) s390_brc(c, S390_CC_GT|S390_CC_OV, d) +#define s390_jl(c, d) s390_brc(c, S390_CC_LT, d) +#define s390_jlo(c, d) s390_brc(c, S390_CC_LT|S390_CC_OV, d) +#define s390_jm(c, d) s390_brc(c, S390_CC_LT, d) +#define s390_jnc(c, d) s390_brc(c, S390_CC_NC, d) +#define s390_jne(c, d) s390_brc(c, S390_CC_NZ, d) +#define s390_jnh(c, d) s390_brc(c, S390_CC_LE, d) +#define s390_jnl(c, d) s390_brc(c, S390_CC_GE, d) +#define s390_jnz(c, d) s390_brc(c, S390_CC_NZ, d) +#define s390_jo(c, d) s390_brc(c, S390_CC_OV, d) +#define s390_jno(c, d) s390_brc(c, S390_CC_NO, d) +#define s390_jp(c, d) s390_brc(c, S390_CC_GT, d) +#define s390_jz(c, d) s390_brc(c, S390_CC_ZR, d) +#define s390_jg(c,d) s390_brcl(c, S390_CC_UN, d) +#define s390_jgcy(c, d) s390_brcl(c, S390_CC_CY, d) +#define s390_jge(c, d) s390_brcl(c, S390_CC_EQ, d) +#define s390_jgeo(c, d) s390_brcl(c, S390_CC_ZR|S390_CC_OV, d) +#define s390_jgh(c, d) s390_brcl(c, S390_CC_GT, d) +#define s390_jgho(c, d) s390_brcl(c, S390_CC_GT|S390_CC_OV, d) +#define s390_jgl(c, d) s390_brcl(c, S390_CC_LT, d) +#define s390_jglo(c, d) s390_brcl(c, S390_CC_LT|S390_CC_OV, d) +#define s390_jgm(c, d) s390_brcl(c, S390_CC_LT, d) +#define s390_jgnc(c, d) s390_brcl(c, S390_CC_NC, d) +#define s390_jgne(c, d) s390_brcl(c, S390_CC_NZ, d) +#define s390_jgnh(c, d) s390_brcl(c, S390_CC_LE, d) +#define s390_jgnl(c, d) s390_brcl(c, S390_CC_GE, d) +#define s390_jgnz(c, d) s390_brcl(c, S390_CC_NZ, d) +#define s390_jgo(c, d) s390_brcl(c, S390_CC_OV, d) +#define s390_jgno(c, d) s390_brcl(c, S390_CC_NO, d) +#define s390_jgp(c, d) s390_brcl(c, S390_CC_GT, d) +#define s390_jgz(c, d) s390_brcl(c, S390_CC_ZR, d) +#define s390_l(c, r, x, b, d) S390_RX(c, 0x58, r, x, b, d) +#define s390_ly(c, r, x, b, d) S390_RXY(c, 0xe358, r, x, b, d) +#define s390_la(c, r, x, b, d) S390_RX(c, 0x41, r, x, b, d) +#define s390_lay(c, r, x, b, d) S390_RXY(c, 0xe371, r, x, b, d) +#define s390_lam(c, r1, r2, b, d) S390_RS_1(c, 0x9a, r1, r2, b, d) +#define s390_larl(c, r, o) S390_RIL_1(c, 0xc00, r, o) +#define s390_lb(c, r, x, b, d) S390_RXY(c, 0xe376, r, x, b, d) +#define s390_lbr(c, r1, r2) S390_RRE(c, 0xb926, r1, r2) +#define s390_lcdbr(c, r1, r2) S390_RRE(c, 0xb313, r1, r2) +#define s390_lcgr(c, r1, r2) S390_RRE(c, 0xb903, r1, r2) +#define s390_lcr(c, r1, r2) S390_RR(c, 0x13, r1, r2) +#define s390_ld(c, f, x, b, d) S390_RX(c, 0x68, f, x, b, d) +#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_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_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) +#define s390_llgc(c, r, x, b, d) S390_RXY(c, 0xe390, r, x, b, d) +#define s390_llgcr(c, r1, r2) S390_RRE(c, 0xb984, r1, r2) +#define s390_llgf(c, r, x, b, d) S390_RXY(c, 0xe316, r, x, b, d) +#define s390_llgfr(c, r1, r2) S390_RRE(c, 0xb916, r1, r2) +#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) +#define s390_lngr(c, r1, r2) S390_RRE(c, 0xb901, r1, r2) +#define s390_lnr(c, r1, r2) S390_RR(c, 0x11, r1, r2) +#define s390_lpdbr(c, r1, r2) S390_RRE(c, 0xb310, r1, r2) +#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) +#define s390_lzdr(c, r) S390_RRE(c, 0xb375, r, 0) +#define s390_lzer(c, r) S390_RRE(c, 0xb374, r, 0) +#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) +#define s390_s(c, r, x, b, d) S390_RX(c, 0x5b, r, x, b, d) +#define s390_sdb(c, r, x, b, d) S390_RXE(c, 0xed1b, r, x, b, d) +#define s390_sdbr(c, r1, r2) S390_RRE(c, 0xb31b, r1, r2) +#define s390_sebr(c, r1, r2) S390_RRE(c, 0xb30b, r1, r2) +#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_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) +#define s390_slr(c, r1, r2) S390_RR(c, 0x1f, r1, r2) +#define s390_sqdbr(c, r1, r2) S390_RRE(c, 0xb315, r1, r2) +#define s390_sqebr(c, r1, r2) S390_RRE(c, 0xb314, r1, r2) +#define s390_sra(c, r, b, d) S390_RS_3(c, 0x8a, r, b, d) +#define s390_srag(c, r1, r2, b, d) S390_RSY_1(c, 0xeb0a, r1, r2, b, d) +#define s390_sr(c, r1, r2) S390_RR(c, 0x1b, r1, r2) +#define s390_srda(c, r, b, d) S390_RS_3(c, 0x8e, r, b, d) +#define s390_srdl(c, r, b, d) S390_RS_3(c, 0x8c, r, b, d) +#define s390_srl(c, r, b, d) S390_RS_3(c, 0x88, r, b, d) +#define s390_srlg(c, r1, r2, b, d) S390_RSY_1(c, 0xeb0c, r1, r2, b, d) +#define s390_st(c, r, x, b, d) S390_RX(c, 0x50, r, x, b, d) +#define s390_stam(c, r1, r2, b, d) S390_RS_1(c, 0x9b, r1, r2, b, d) +#define s390_stc(c, r, x, b, d) S390_RX(c, 0x42, r, x, b, d) +#define s390_stcm(c, r, m, b, d) S390_RX(c, 0xbe, r, m, b, d) +#define s390_stcmy(c, r, x, b, d) S390_RXY(c, 0xeb2d, r, x, b, d) +#define s390_stcy(c, r, x, b, d) S390_RXY(c, 0xe372, r, x, b, d) +#define s390_std(c, f, x, b, d) S390_RX(c, 0x60, f, x, b, d) +#define s390_stdy(c, r, x, b, d) S390_RXY(c, 0xed67, r, x, b, d) +#define s390_ste(c, f, x, b, d) S390_RX(c, 0x70, f, x, b, d) +#define s390_stey(c, r, x, b, d) S390_RXY(c, 0xed66, r, x, b, d) +#define s390_stfpc(c, b, d) S390_S(c, 0xb29c, b, d) +#define s390_stg(c, r, x, b, d) S390_RXY(c, 0xe324, r, x, b, d) +#define s390_sth(c, r, x, b, d) S390_RX(c, 0x40, r, x, b, d) +#define s390_sthy(c, r, x, b, d) S390_RXY(c, 0xe370, r, x, b, d) +#define s390_stm(c, r1, r2, b, d) S390_RS_1(c, 0x90, r1, r2, b, d) +#define s390_stmg(c, r1, r2, b, d) S390_RSY_1(c, 0xeb24, r1, r2, b, d) +#define s390_sty(c, r, x, b, d) S390_RXY(c, 0xe350, r, x, b, d) +#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/src/arch/s390x/tramp.c b/src/arch/s390x/tramp.c new file mode 100644 index 0000000..fe9f310 --- /dev/null +++ b/src/arch/s390x/tramp.c @@ -0,0 +1,1149 @@ +/*------------------------------------------------------------------*/ +/* */ +/* Name - tramp.c */ +/* */ +/* Function - Create trampolines to invoke arbitrary functions. */ +/* */ +/* Name - Neale Ferguson. */ +/* */ +/* Date - October, 2002 */ +/* */ +/* */ +/*------------------------------------------------------------------*/ + +/*------------------------------------------------------------------*/ +/* D e f i n e s */ +/*------------------------------------------------------------------*/ + +#define PROLOG_INS 24 /* Size of emitted prolog */ +#define CALL_INS 4 /* Size of emitted call */ +#define EPILOG_INS 18 /* Size of emitted epilog */ + +#define DEBUG(x) + +/*========================= End of Defines =========================*/ + +/*------------------------------------------------------------------*/ +/* I n c l u d e s */ +/*------------------------------------------------------------------*/ + +#ifdef NEED_MPROTECT +# include <sys/mman.h> +# include <limits.h> /* for PAGESIZE */ +# ifndef PAGESIZE +# define PAGESIZE 4096 +# endif +#endif + +#include "config.h" +#include <stdlib.h> +#include <string.h> +#include "s390x-codegen.h" +#include "mono/metadata/class.h" +#include "mono/metadata/tabledefs.h" +#include "mono/interpreter/interp.h" +#include "mono/metadata/appdomain.h" +#include "mono/metadata/marshal.h" + +/*========================= End of Includes ========================*/ + +/*------------------------------------------------------------------*/ +/* T y p e d e f s */ +/*------------------------------------------------------------------*/ + +/*------------------------------------------------------------------*/ +/* Structure used to accummulate size of stack, code, and locals */ +/*------------------------------------------------------------------*/ +typedef struct { + guint stack_size, + local_size, + code_size, + retStruct; +} size_data; + +/*========================= End of Typedefs ========================*/ + +/*------------------------------------------------------------------*/ +/* */ +/* Name - add_general */ +/* */ +/* Function - Determine code and stack size incremements for a */ +/* parameter. */ +/* */ +/*------------------------------------------------------------------*/ + +static void inline +add_general (guint *gr, size_data *sz, gboolean simple) +{ + if (simple) { + if (*gr >= GENERAL_REGS) { + sz->stack_size += sizeof(long); + sz->code_size += 12; + } else { + sz->code_size += 8; + } + } else { + if (*gr >= GENERAL_REGS - 1) { + sz->stack_size += 8 + (sz->stack_size % 8); + sz->code_size += 10; + } else { + sz->code_size += 8; + } + (*gr) ++; + } + (*gr) ++; +} + +/*========================= End of Function ========================*/ + +/*------------------------------------------------------------------*/ +/* */ +/* Name - calculate_sizes */ +/* */ +/* Function - Determine the amount of space required for code */ +/* and stack. In addition determine starting points */ +/* for stack-based parameters, and area for struct- */ +/* ures being returned on the stack. */ +/* */ +/*------------------------------------------------------------------*/ + +static void inline +calculate_sizes (MonoMethodSignature *sig, size_data *sz, + gboolean string_ctor) +{ + guint i, fr, gr, size; + guint32 simpletype, align; + + fr = 0; + gr = 2; + sz->retStruct = 0; + sz->stack_size = S390_MINIMAL_STACK_SIZE; + sz->code_size = (PROLOG_INS + CALL_INS + EPILOG_INS); + sz->local_size = 0; + + if (sig->hasthis) { + add_general (&gr, sz, TRUE); + } + + /*----------------------------------------------------------*/ + /* We determine the size of the return code/stack in case we*/ + /* need to reserve a register to be used to address a stack */ + /* area that the callee will use. */ + /*----------------------------------------------------------*/ + + if (sig->ret->byref || string_ctor) { + sz->code_size += 8; + } else { + simpletype = sig->ret->type; +enum_retvalue: + switch (simpletype) { + case MONO_TYPE_BOOLEAN: + case MONO_TYPE_I1: + case MONO_TYPE_U1: + case MONO_TYPE_I2: + case MONO_TYPE_U2: + case MONO_TYPE_CHAR: + case MONO_TYPE_I4: + case MONO_TYPE_U4: + case MONO_TYPE_I: + case MONO_TYPE_U: + case MONO_TYPE_CLASS: + case MONO_TYPE_OBJECT: + case MONO_TYPE_R4: + case MONO_TYPE_R8: + case MONO_TYPE_PTR: + case MONO_TYPE_SZARRAY: + case MONO_TYPE_ARRAY: + case MONO_TYPE_STRING: + sz->code_size += 4; + break; + case MONO_TYPE_I8: + sz->code_size += 4; + break; + case MONO_TYPE_VALUETYPE: + if (sig->ret->data.klass->enumtype) { + simpletype = sig->ret->data.klass->enum_basetype->type; + goto enum_retvalue; + } + gr++; + if (sig->pinvoke) + size = mono_class_native_size (sig->ret->data.klass, &align); + else + size = mono_class_value_size (sig->ret->data.klass, &align); + if (align > 1) + sz->code_size += 10; + switch (size) { + /*----------------------------------*/ + /* On S/390, structures of size 1, */ + /* 2, 4, and 8 bytes are returned */ + /* in (a) register(s). */ + /*----------------------------------*/ + case 1: + case 2: + case 4: + case 8: + sz->code_size += 16; + sz->stack_size += 4; + break; + default: + sz->retStruct = 1; + sz->code_size += 32; + } + break; + case MONO_TYPE_VOID: + break; + default: + g_error ("Can't handle as return value 0x%x", sig->ret->type); + } + } + + /*----------------------------------------------------------*/ + /* We determine the size of the parameter code and stack */ + /* requirements by checking the types and sizes of the */ + /* parameters. */ + /*----------------------------------------------------------*/ + + for (i = 0; i < sig->param_count; ++i) { + if (sig->params [i]->byref) { + add_general (&gr, sz, TRUE); + continue; + } + simpletype = sig->params [i]->type; + enum_calc_size: + switch (simpletype) { + case MONO_TYPE_BOOLEAN: + case MONO_TYPE_CHAR: + case MONO_TYPE_I1: + case MONO_TYPE_U1: + case MONO_TYPE_I2: + case MONO_TYPE_U2: + case MONO_TYPE_I4: + case MONO_TYPE_U4: + case MONO_TYPE_I: + case MONO_TYPE_U: + case MONO_TYPE_PTR: + case MONO_TYPE_CLASS: + case MONO_TYPE_OBJECT: + case MONO_TYPE_STRING: + add_general (&gr, sz, TRUE); + break; + case MONO_TYPE_SZARRAY: + add_general (&gr, sz, TRUE); + break; + case MONO_TYPE_VALUETYPE: + if (sig->params [i]->data.klass->enumtype) { + simpletype = sig->params [i]->data.klass->enum_basetype->type; + goto enum_calc_size; + } + if (sig->pinvoke) + size = mono_class_native_size (sig->params [i]->data.klass, &align); + else + size = mono_class_value_size (sig->params [i]->data.klass, &align); + DEBUG(printf("%d typesize: %d (%d)\n",i,size,align)); + switch (size) { + /*----------------------------------*/ + /* On S/390, structures of size 1, */ + /* 2, 4, and 8 bytes are passed in */ + /* (a) register(s). */ + /*----------------------------------*/ + case 0: + case 1: + case 2: + case 4: + add_general(&gr, sz, TRUE); + break; + case 8: + add_general(&gr, sz, FALSE); + break; + default: + sz->local_size += (size + (size % align)); + sz->code_size += 40; + } + break; + case MONO_TYPE_I8: + add_general (&gr, sz, FALSE); + break; + case MONO_TYPE_R4: + if (fr < FLOAT_REGS) { + sz->code_size += 4; + fr++; + } + else { + sz->code_size += 4; + sz->stack_size += 8; + } + break; + case MONO_TYPE_R8: + if (fr < FLOAT_REGS) { + sz->code_size += 4; + fr++; + } else { + sz->code_size += 4; + sz->stack_size += 8 + (sz->stack_size % 8); + } + break; + default: + g_error ("Can't trampoline 0x%x", sig->params [i]->type); + } + } + + + /* align stack size to 8 */ + DEBUG (printf (" stack size: %d (%d)\n" + " code size: %d\n" + " local size: %d\n", + (sz->stack_size + 8) & ~8, sz->stack_size, + (sz->code_size),(sz->local_size + 8) & ~8)); + sz->stack_size = (sz->stack_size + 8) & ~8; + sz->local_size = (sz->local_size + 8) & ~8; +} + +/*========================= End of Function ========================*/ + +/*------------------------------------------------------------------*/ +/* */ +/* Name - emit_prolog */ +/* */ +/* Function - Create the instructions that implement the stand- */ +/* ard function prolog according to the S/390 ABI. */ +/* */ +/*------------------------------------------------------------------*/ + +static inline guint8 * +emit_prolog (guint8 *p, MonoMethodSignature *sig, size_data *sz) +{ + guint stack_size; + + stack_size = sz->stack_size + sz->local_size; + + /* function prolog */ + s390_stmg(p, s390_r6, s390_r14, STK_BASE, S390_REG_SAVE_OFFSET); + s390_lg (p, s390_r7, 0, STK_BASE, MINV_POS); + s390_lgr (p, s390_r11, STK_BASE); + s390_aghi(p, STK_BASE, -stack_size); + s390_stg (p, s390_r11, 0, STK_BASE, 0); + + /*-----------------------------------------*/ + /* Save: */ + /* - address of "callme" */ + /* - address of "retval" */ + /* - address of "arguments" */ + /*-----------------------------------------*/ + s390_lgr (p, s390_r9, s390_r2); + s390_lgr (p, s390_r8, s390_r3); + s390_lgr (p, s390_r10, s390_r5); + + return p; +} + +/*========================= End of Function ========================*/ + +/*------------------------------------------------------------------*/ +/* */ +/* Name - emit_save_parameters */ +/* */ +/* Function - Create the instructions that load registers with */ +/* parameters, place others on the stack according */ +/* to the S/390 ABI. */ +/* */ +/* The resulting function takes the form: */ +/* void func (void (*callme)(), void *retval, */ +/* void *this_obj, stackval *arguments); */ +/* */ +/*------------------------------------------------------------------*/ + +inline static guint8* +emit_save_parameters (guint8 *p, MonoMethodSignature *sig, size_data *sz) +{ + guint i, fr, gr, act_strs, align, + stack_par_pos, size, local_pos; + guint32 simpletype; + + /*----------------------------------------------------------*/ + /* If a structure on stack is being returned, reserve r2 */ + /* to point to an area where it can be passed. */ + /*----------------------------------------------------------*/ + if (sz->retStruct) + gr = 1; + else + gr = 0; + fr = 0; + act_strs = 0; + stack_par_pos = S390_MINIMAL_STACK_SIZE; + local_pos = sz->stack_size; + + if (sig->hasthis) { + s390_lr (p, s390_r2 + gr, s390_r4); + gr++; + } + + act_strs = 0; + for (i = 0; i < sig->param_count; ++i) { + DEBUG(printf("par: %d type: %d ref: %d\n",i,sig->params[i]->type,sig->params[i]->byref)); + if (sig->params [i]->byref) { + if (gr < GENERAL_REGS) { + s390_lg (p, s390_r2 + gr, 0, ARG_BASE, STKARG); + gr ++; + } else { + s390_lg (p, s390_r0, 0, ARG_BASE, STKARG); + s390_stg(p, s390_r0, 0, STK_BASE, stack_par_pos); + stack_par_pos += sizeof(long); + } + continue; + } + simpletype = sig->params [i]->type; + enum_calc_size: + switch (simpletype) { + case MONO_TYPE_BOOLEAN: + case MONO_TYPE_I1: + case MONO_TYPE_U1: + case MONO_TYPE_I2: + case MONO_TYPE_U2: + case MONO_TYPE_CHAR: + case MONO_TYPE_I4: + case MONO_TYPE_U4: + case MONO_TYPE_I: + case MONO_TYPE_U: + case MONO_TYPE_PTR: + case MONO_TYPE_CLASS: + case MONO_TYPE_OBJECT: + case MONO_TYPE_STRING: + case MONO_TYPE_SZARRAY: + if (gr < GENERAL_REGS) { + s390_lg (p, s390_r2 + gr, 0, ARG_BASE, STKARG); + gr ++; + } else { + s390_lg (p, s390_r0, 0, ARG_BASE, STKARG); + s390_stg(p, s390_r0, 0, STK_BASE, stack_par_pos); + stack_par_pos += sizeof(long); + } + break; + case MONO_TYPE_VALUETYPE: + if (sig->params [i]->data.klass->enumtype) { + simpletype = sig->params [i]->data.klass->enum_basetype->type; + goto enum_calc_size; + } + if (sig->pinvoke) + size = mono_class_native_size (sig->params [i]->data.klass, &align); + else + size = mono_class_value_size (sig->params [i]->data.klass, &align); + DEBUG(printf("parStruct - size %d pinvoke: %d\n",size,sig->pinvoke)); + switch (size) { + case 0: + case 1: + case 2: + case 4: + if (gr < GENERAL_REGS) { + s390_lg (p, s390_r2 + gr, 0,ARG_BASE, STKARG); + s390_lgf(p, s390_r2 + gr, 0, s390_r2 + gr, 0); + gr++; + } else { + stack_par_pos += (stack_par_pos % align); + s390_lg (p, s390_r10, 0,ARG_BASE, STKARG); + s390_lgf(p, s390_r10, 0, s390_r10, 0); + s390_st (p, s390_r10, 0, STK_BASE, stack_par_pos); + stack_par_pos += sizeof(long); + } + break; + case 8: + if (gr < GENERAL_REGS) { + s390_lg (p, s390_r2 + gr, 0, ARG_BASE, STKARG); + s390_lg (p, s390_r2 + gr, 0, s390_r2 + gr, 0); + } else { + stack_par_pos += (stack_par_pos % align); + s390_lg (p, s390_r10, 0, ARG_BASE, STKARG); + s390_mvc (p, sizeof(long long), STK_BASE, stack_par_pos, s390_r10, 0); + stack_par_pos += sizeof(long long); + } + break; + default: + if (size <= 256) { + local_pos += (local_pos % align); + s390_lg (p, s390_r13, 0, ARG_BASE, STKARG); + s390_mvc (p, size, STK_BASE, local_pos, s390_r13, 0); + s390_la (p, s390_r13, 0, STK_BASE, local_pos); + local_pos += size; + } else { + local_pos += (local_pos % align); + s390_bras (p, s390_r13, 4); + s390_llong(p, size); + s390_lg (p, s390_r1, 0, s390_r13, 0); + s390_lg (p, s390_r0, 0, ARG_BASE, STKARG); + s390_lgr (p, s390_r14, s390_r12); + s390_la (p, s390_r12, 0, STK_BASE, local_pos); + s390_lgr (p, s390_r13, s390_r1); + s390_mvcl (p, s390_r12, s390_r0); + s390_lgr (p, s390_r12, s390_r14); + s390_la (p, s390_r13, 0, STK_BASE, local_pos); + local_pos += size; + } + if (gr < GENERAL_REGS) { + s390_lgr(p, s390_r2 + gr, s390_r13); + gr++; + } else { + s390_stg(p, s390_r13, 0, STK_BASE, stack_par_pos); + stack_par_pos += sizeof(long); + } + } + break; + case MONO_TYPE_I8: + if (gr < GENERAL_REGS) { + s390_lg (p, s390_r2 + gr, 0, ARG_BASE, STKARG); + gr += 2; + } else { + *(guint32 *) p += 7; + *(guint32 *) p &= ~7; + s390_mvc (p, sizeof(long long), STK_BASE, stack_par_pos, ARG_BASE, STKARG); + stack_par_pos += sizeof(long long) + (stack_par_pos % sizeof(long long)); + } + break; + case MONO_TYPE_R4: + if (fr < FLOAT_REGS) { + s390_le (p, s390_r0 + fr, 0, ARG_BASE, STKARG); + fr++; + } else { + s390_mvc (p, sizeof(float), STK_BASE, stack_par_pos, ARG_BASE, STKARG); + stack_par_pos += sizeof(float); + } + break; + case MONO_TYPE_R8: + if (fr < FLOAT_REGS) { + s390_ld (p, s390_r0 + fr, 0, ARG_BASE, STKARG); + fr++; + } else { + *(guint32 *) p += 7; + *(guint32 *) p &= ~7; + s390_mvc (p, sizeof(double), STK_BASE, stack_par_pos, ARG_BASE, STKARG); + stack_par_pos += sizeof(long long) + (stack_par_pos % sizeof(long long)); + } + break; + default: + g_error ("Can't trampoline 0x%x", sig->params [i]->type); + } + } + + /*----------------------------------------------------------*/ + /* If we're returning a structure but not in a register */ + /* then point the result area for the called routine */ + /*----------------------------------------------------------*/ + if (sz->retStruct) { + s390_lg (p, s390_r2, 0, s390_r8, 0); + } + + return p; +} + +/*========================= End of Function ========================*/ + +/*------------------------------------------------------------------*/ +/* */ +/* Name - alloc_code_memory */ +/* */ +/* Function - Allocate space to place the emitted code. */ +/* */ +/*------------------------------------------------------------------*/ + +static inline guint8 * +alloc_code_memory (guint code_size) +{ + guint8 *p; + +#ifdef NEED_MPROTECT + p = g_malloc (code_size + PAGESIZE - 1); + + /* Align to a multiple of PAGESIZE, assumed to be a power of two */ + p = (char *)(((int) p + PAGESIZE-1) & ~(PAGESIZE-1)); +#else + p = g_malloc (code_size); +#endif + DEBUG (printf (" align: %p (%d)\n", p, (guint)p % 4)); + + return p; +} + +/*========================= End of Function ========================*/ + +/*------------------------------------------------------------------*/ +/* */ +/* Name - emit_call_and_store_retval */ +/* */ +/* Function - Emit code that will implement the call to the */ +/* desired function, and unload the result according */ +/* to the S390 ABI for the type of value returned */ +/* */ +/*------------------------------------------------------------------*/ + +static inline guint8 * +emit_call_and_store_retval (guint8 *p, MonoMethodSignature *sig, + size_data *sz, gboolean string_ctor) +{ + guint32 simpletype; + guint retSize, align; + + /* call "callme" */ + s390_basr (p, s390_r14, s390_r9); + + /* get return value */ + if (sig->ret->byref || string_ctor) { + s390_stg(p, s390_r2, 0, s390_r8, 0); + } else { + simpletype = sig->ret->type; +enum_retvalue: + switch (simpletype) { + case MONO_TYPE_BOOLEAN: + case MONO_TYPE_I1: + case MONO_TYPE_U1: + s390_stc (p, s390_r2, 0, s390_r8, 0); + break; + case MONO_TYPE_I2: + case MONO_TYPE_U2: + case MONO_TYPE_CHAR: + s390_sth (p, s390_r2, 0, s390_r8, 0); + break; + case MONO_TYPE_I4: + case MONO_TYPE_U4: + case MONO_TYPE_I: + case MONO_TYPE_U: + case MONO_TYPE_CLASS: + case MONO_TYPE_OBJECT: + case MONO_TYPE_SZARRAY: + case MONO_TYPE_ARRAY: + case MONO_TYPE_STRING: + s390_st (p, s390_r2, 0, s390_r8, 0); + break; + case MONO_TYPE_R4: + s390_ste (p, s390_f0, 0, s390_r8, 0); + break; + case MONO_TYPE_R8: + s390_std (p, s390_f0, 0, s390_r8, 0); + break; + case MONO_TYPE_I8: + s390_stg (p, s390_r2, 0, s390_r8, 0); + break; + case MONO_TYPE_VALUETYPE: + if (sig->ret->data.klass->enumtype) { + simpletype = sig->ret->data.klass->enum_basetype->type; + goto enum_retvalue; + } + if (sig->pinvoke) + retSize = mono_class_native_size (sig->ret->data.klass, &align); + else + retSize = mono_class_value_size (sig->ret->data.klass, &align); +printf("Returning %d bytes for type %d (%d)\n",retSize,simpletype,sig->pinvoke); + switch(retSize) { + case 0: + break; + case 1: + s390_stc (p, s390_r2, 0, s390_r8, 0); + break; + case 2: + s390_sth (p, s390_r2, 0, s390_r8, 0); + break; + case 4: + s390_st (p, s390_r2, 0, s390_r8, 0); + break; + case 8: + s390_stg (p, s390_r2, 0, s390_r8, 0); + break; + default: ; + /*------------------------------------------*/ + /* The callee has already placed the result */ + /* in the required area */ + /*------------------------------------------*/ + } + break; + case MONO_TYPE_VOID: + break; + default: + g_error ("Can't handle as return value 0x%x", + sig->ret->type); + } + } + + return p; +} + +/*========================= End of Function ========================*/ + +/*------------------------------------------------------------------*/ +/* */ +/* Name - emit_epilog */ +/* */ +/* Function - Create the instructions that implement the stand- */ +/* ard function epilog according to the S/390 ABI. */ +/* */ +/*------------------------------------------------------------------*/ + +static inline guint8 * +emit_epilog (guint8 *p, MonoMethodSignature *sig, size_data *sz) +{ + /* function epilog */ + s390_lg (p, STK_BASE, 0, STK_BASE, 0); + s390_lg (p, s390_r4, 0, STK_BASE, S390_RET_ADDR_OFFSET); + s390_lmg (p, s390_r6, STK_BASE, STK_BASE, S390_REG_SAVE_OFFSET); + s390_br (p, s390_r4); + + return p; +} + +/*========================= End of Function ========================*/ + +/*------------------------------------------------------------------*/ +/* */ +/* Name - mono_arch_create_trampoline. */ +/* */ +/* Function - Create the code that will allow a mono method to */ +/* invoke a system subroutine. */ +/* */ +/*------------------------------------------------------------------*/ + +MonoPIFunc +mono_arch_create_trampoline (MonoMethodSignature *sig, gboolean string_ctor) +{ + guint8 *p, *code_buffer; + size_data sz; + + DEBUG (printf ("\nPInvoke [start emiting]\n")); + calculate_sizes (sig, &sz, string_ctor); + + p = code_buffer = alloc_code_memory (sz.code_size); + p = emit_prolog (p, sig, &sz); + p = emit_save_parameters (p, sig, &sz); + p = emit_call_and_store_retval (p, sig, &sz, string_ctor); + p = emit_epilog (p, sig, &sz); + +#ifdef NEED_MPROTECT + if (mprotect (code_buffer, 1024, PROT_READ | PROT_WRITE | PROT_EXEC)) { + g_error ("Cannot mprotect trampoline\n"); + } +#endif + + DEBUG (printf ("emited code size: %d\n", p - code_buffer)); + + DEBUG (printf ("PInvoke [end emiting]\n")); + + return (MonoPIFunc) code_buffer; +} + +/*========================= End of Function ========================*/ + +/*------------------------------------------------------------------*/ +/* */ +/* Name - mono_arch_create_method_pointer */ +/* */ +/* Function - Returns a pointer to a native function that can */ +/* be used to call the specified method. */ +/* */ +/* The function created will receive the arguments */ +/* according to the calling convention specified in */ +/* in the method. */ +/* */ +/* This function works by creating a MonoInvocation */ +/* structure, filling the fields in and calling */ +/* ves_exec_method() on it. */ +/* */ +/* Logic: */ +/* ------ */ +/* mono_arch_create_method_pointer (MonoMethod *method) */ +/* create the unmanaged->managed wrapper */ +/* register it with mono_jit_info_table_add() */ +/* */ +/* What does the unmanaged->managed wrapper do? */ +/* allocate a MonoInvocation structure (inv) on the stack */ +/* allocate an array of stackval on the stack with length = */ +/* method->signature->param_count + 1 [call it stack_args] */ +/* set inv->ex, inv->ex_handler, inv->parent to NULL */ +/* set inv->method to method */ +/* if method is an instance method, set inv->obj to the */ +/* 'this' argument (the first argument) else set to NULL */ +/* for each argument to the method call: */ +/* stackval_from_data (sig->params[i], &stack_args[i], */ +/* arg, sig->pinvoke); */ +/* Where: */ +/* ------ */ +/* sig - is method->signature */ +/* &stack_args[i] - is the pointer to the ith element */ +/* in the stackval array */ +/* arg - is a pointer to the argument re- */ +/* ceived by the function according */ +/* to the call convention. If it */ +/* gets passed in a register, save */ +/* on the stack first. */ +/* */ +/* set inv->retval to the address of the last element of */ +/* stack_args [recall we allocated param_count+1 of them] */ +/* call ves_exec_method(inv) */ +/* copy the returned value from inv->retval where the calling */ +/* convention expects to find it on return from the wrap- */ +/* per [if it's a structure, use stackval_to_data] */ +/* */ +/*------------------------------------------------------------------*/ + +void * +mono_arch_create_method_pointer (MonoMethod *method) +{ + MonoMethodSignature *sig; + MonoJitInfo *ji; + guint8 *p, *code_buffer; + guint i, align = 0, simple_type, retSize, reg_save = 0, + stackval_arg_pos, local_pos, float_pos, + local_start, reg_param = 0, stack_param, + this_flag, arg_pos, fpr_param, parSize; + guint32 simpletype; + size_data sz; + int *vtbuf, cpos, vt_cur; + + sz.code_size = 1024; + sz.stack_size = 1024; + stack_param = 0; + fpr_param = 0; + arg_pos = 0; + + sig = method->signature; + + p = code_buffer = g_malloc (sz.code_size); + + DEBUG (printf ("\nDelegate [start emiting] %s at 0x%08x\n", + method->name,p)); + + /*----------------------------------------------------------*/ + /* prolog */ + /*----------------------------------------------------------*/ + s390_stmg(p, s390_r6, STK_BASE, STK_BASE, S390_REG_SAVE_OFFSET); + s390_lg (p, s390_r7, 0, STK_BASE, MINV_POS); + s390_lgr (p, s390_r0, STK_BASE); + s390_aghi(p, STK_BASE, -(sz.stack_size+MINV_POS)); + s390_stg (p, s390_r0, 0, STK_BASE, 0); + s390_la (p, s390_r8, 0, STK_BASE, 4); + s390_lgr (p, s390_r10, s390_r8); + s390_lghi(p, s390_r9, sz.stack_size+92); + s390_lghi(p, s390_r11, 0); + s390_mvcl(p, s390_r8, s390_r10); + + /*----------------------------------------------------------*/ + /* Let's fill MonoInvocation - first zero some fields */ + /*----------------------------------------------------------*/ + s390_lghi (p, s390_r0, 0); + s390_stg (p, s390_r0, 0, STK_BASE, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, ex))); + s390_stg (p, s390_r0, 0, STK_BASE, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, ex_handler))); + s390_stg (p, s390_r0, 0, STK_BASE, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, parent))); + s390_lghi (p, s390_r0, 1); + s390_stg (p, s390_r0, 0, STK_BASE, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, invoke_trap))); + + /*----------------------------------------------------------*/ + /* set method pointer */ + /*----------------------------------------------------------*/ + s390_bras (p, s390_r13, 4); + s390_llong(p, method); + s390_lg (p, s390_r0, 0, s390_r13, 0); + s390_stg (p, s390_r0, 0, STK_BASE, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, method))); + + local_start = local_pos = MINV_POS + + sizeof (MonoInvocation) + (sig->param_count + 1) * sizeof (stackval); + this_flag = (sig->hasthis ? 1 : 0); + + /*----------------------------------------------------------*/ + /* if we are returning a structure, checks it's length to */ + /* see if there's a "hidden" parameter that points to the */ + /* area. If necessary save this hidden parameter for later */ + /*----------------------------------------------------------*/ + if (MONO_TYPE_ISSTRUCT(sig->ret)) { + if (sig->pinvoke) + retSize = mono_class_native_size (sig->ret->data.klass, &align); + else + retSize = mono_class_value_size (sig->ret->data.klass, &align); + switch(retSize) { + case 0: + case 1: + case 2: + case 4: + case 8: + sz.retStruct = 0; + break; + default: + sz.retStruct = 1; + s390_lgr(p, s390_r8, s390_r2); + reg_save = 1; + } + } else { + reg_save = 0; + } + + if (this_flag) { + s390_stg (p, s390_r2 + reg_save, 0, STK_BASE, + (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, obj))); + reg_param++; + } else { + s390_stg (p, s390_r2 + reg_save, 0, STK_BASE, local_pos); + local_pos += sizeof(int); + s390_stg (p, s390_r0, 0, STK_BASE, + (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, obj))); + } + + s390_stmg (p, s390_r3 + reg_param, s390_r6, STK_BASE, local_pos); + local_pos += 4 * sizeof(long); + float_pos = local_pos; + s390_std (p, s390_f0, 0, STK_BASE, local_pos); + local_pos += sizeof(double); + s390_std (p, s390_f2, 0, STK_BASE, local_pos); + local_pos += sizeof(double); + + /*----------------------------------------------------------*/ + /* prepare space for valuetypes */ + /*----------------------------------------------------------*/ + vt_cur = local_pos; + vtbuf = alloca (sizeof(int)*sig->param_count); + cpos = 0; + for (i = 0; i < sig->param_count; i++) { + MonoType *type = sig->params [i]; + vtbuf [i] = -1; + DEBUG(printf("par: %d type: %d ref: %d\n",i,type->type,type->byref)); + if (type->type == MONO_TYPE_VALUETYPE) { + MonoClass *klass = type->data.klass; + gint size; + + if (klass->enumtype) + continue; + size = mono_class_native_size (klass, &align); + cpos += align - 1; + cpos &= ~(align - 1); + vtbuf [i] = cpos; + cpos += size; + } + } + cpos += 3; + cpos &= ~3; + + local_pos += cpos; + + /*----------------------------------------------------------*/ + /* set MonoInvocation::stack_args */ + /*----------------------------------------------------------*/ + stackval_arg_pos = MINV_POS + sizeof (MonoInvocation); + s390_la (p, s390_r0, 0, STK_BASE, stackval_arg_pos); + s390_stg (p, s390_r0, 0, STK_BASE, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, stack_args))); + + /*----------------------------------------------------------*/ + /* add stackval arguments */ + /*----------------------------------------------------------*/ + for (i = 0; i < sig->param_count; ++i) { + if (sig->params [i]->byref) { + ADD_ISTACK_PARM(0, 1); + } else { + simple_type = sig->params [i]->type; + enum_savechk: + switch (simple_type) { + case MONO_TYPE_I8: + ADD_ISTACK_PARM(-1, 2); + break; + case MONO_TYPE_R4: + ADD_RSTACK_PARM(1); + break; + case MONO_TYPE_R8: + ADD_RSTACK_PARM(2); + break; + case MONO_TYPE_VALUETYPE: + if (sig->params [i]->data.klass->enumtype) { + simple_type = sig->params [i]->data.klass->enum_basetype->type; + goto enum_savechk; + } + if (sig->pinvoke) + parSize = mono_class_native_size (sig->params [i]->data.klass, &align); + else + parSize = mono_class_value_size (sig->params [i]->data.klass, &align); + switch(parSize) { + case 0: + case 1: + case 2: + case 4: + ADD_PSTACK_PARM(0, 1); + break; + case 8: + ADD_PSTACK_PARM(-1, 2); + break; + default: + ADD_TSTACK_PARM; + } + break; + default: + ADD_ISTACK_PARM(0, 1); + } + } + + if (vtbuf [i] >= 0) { + s390_la (p, s390_r3, 0, STK_BASE, vt_cur); + s390_stg (p, s390_r3, 0, STK_BASE, stackval_arg_pos); + s390_la (p, s390_r3, 0, STK_BASE, stackval_arg_pos); + vt_cur += vtbuf [i]; + } else { + s390_la (p, s390_r3, 0, STK_BASE, stackval_arg_pos); + } + + /*--------------------------------------*/ + /* Load the parameter registers for the */ + /* call to stackval_from_data */ + /*--------------------------------------*/ + s390_bras (p, s390_r13, 8); + s390_llong(p, sig->params [i]); + s390_llong(p, sig->pinvoke); + s390_llong(p, stackval_from_data); + s390_lg (p, s390_r2, 0, s390_r13, 0); + s390_lg (p, s390_r5, 0, s390_r13, 4); + s390_lg (p, s390_r1, 0, s390_r13, 8); + s390_basr (p, s390_r14, s390_r1); + + stackval_arg_pos += sizeof(stackval); + + /* fixme: alignment */ + DEBUG (printf ("arg_pos %d --> ", arg_pos)); + if (sig->pinvoke) + arg_pos += mono_type_native_stack_size (sig->params [i], &align); + else + arg_pos += mono_type_stack_size (sig->params [i], &align); + + DEBUG (printf ("%d\n", stackval_arg_pos)); + } + + /*----------------------------------------------------------*/ + /* Set return area pointer. */ + /*----------------------------------------------------------*/ + s390_la (p, s390_r10, 0, STK_BASE, stackval_arg_pos); + s390_stg(p, s390_r10, 0, STK_BASE, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, retval))); + if (sig->ret->type == MONO_TYPE_VALUETYPE && !sig->ret->byref) { + MonoClass *klass = sig->ret->data.klass; + if (!klass->enumtype) { + s390_la (p, s390_r9, 0, s390_r10, sizeof(stackval)); + s390_st (p, s390_r9, 0,STK_BASE, stackval_arg_pos); + stackval_arg_pos += sizeof(stackval); + } + } + + /*----------------------------------------------------------*/ + /* call ves_exec_method */ + /*----------------------------------------------------------*/ + s390_bras (p, s390_r13, 4); + s390_llong(p, ves_exec_method); + s390_lg (p, s390_r1, 0, s390_r13, 0); + s390_la (p, s390_r2, 0, STK_BASE, MINV_POS); + s390_basr (p, s390_r14, s390_r1); + + /*----------------------------------------------------------*/ + /* move retval from stackval to proper place (r3/r4/...) */ + /*----------------------------------------------------------*/ + DEBUG(printf("retType: %d byRef: %d\n",sig->ret->type,sig->ret->byref)); + if (sig->ret->byref) { + DEBUG (printf ("ret by ref\n")); + s390_stg(p, s390_r2, 0, s390_r10, 0); + } else { + enum_retvalue: + switch (sig->ret->type) { + case MONO_TYPE_VOID: + break; + case MONO_TYPE_BOOLEAN: + case MONO_TYPE_U1: + s390_lghi(p, s390_r2, 0); + s390_ic (p, s390_r2, 0, s390_r10, 0); + break; + case MONO_TYPE_I2: + case MONO_TYPE_U2: + s390_lh (p, s390_r2, 0,s390_r10, 0); + break; + case MONO_TYPE_I4: + case MONO_TYPE_U4: + case MONO_TYPE_I: + case MONO_TYPE_U: + s390_lgf(p, s390_r2, 0, s390_r10, 0); + break; + case MONO_TYPE_OBJECT: + case MONO_TYPE_STRING: + case MONO_TYPE_CLASS: + case MONO_TYPE_I8: + s390_lg (p, s390_r2, 0, s390_r10, 0); + break; + case MONO_TYPE_R4: + s390_le (p, s390_f0, 0, s390_r10, 0); + break; + case MONO_TYPE_R8: + s390_ld (p, s390_f0, 0, s390_r10, 0); + break; + case MONO_TYPE_VALUETYPE: + if (sig->ret->data.klass->enumtype) { + simpletype = sig->ret->data.klass->enum_basetype->type; + goto enum_retvalue; + } + /*---------------------------------*/ + /* Call stackval_to_data to return */ + /* the structure */ + /*---------------------------------*/ + s390_bras (p, s390_r13, 8); + s390_llong(p, sig->ret); + s390_llong(p, sig->pinvoke); + s390_llong(p, stackval_to_data); + s390_lg (p, s390_r2, 0, s390_r13, 0); + s390_lg (p, s390_r3, 0, STK_BASE, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, retval))); + if (sz.retStruct) { + /*------------------------------------------*/ + /* Get stackval_to_data to set result area */ + /*------------------------------------------*/ + s390_lgr (p, s390_r4, s390_r8); + } else { + /*------------------------------------------*/ + /* Give stackval_to_data a temp result area */ + /*------------------------------------------*/ + s390_la (p, s390_r4, 0, STK_BASE, stackval_arg_pos); + } + s390_lg (p, s390_r5, 0,s390_r13, 4); + s390_lg (p, s390_r1, 0, s390_r13, 8); + s390_basr (p, s390_r14, s390_r1); + switch (retSize) { + case 0: + break; + case 1: + s390_lghi(p, s390_r2, 0); + s390_ic (p, s390_r2, 0, s390_r10, 0); + break; + case 2: + s390_lh (p, s390_r2, 0, s390_r10, 0); + break; + case 4: + s390_lgf(p, s390_r2, 0, s390_r10, 0); + break; + case 8: + s390_lg (p, s390_r2, 0, s390_r10, 0); + break; + default: ; + /*-------------------------------------------------*/ + /* stackval_to_data has placed data in result area */ + /*-------------------------------------------------*/ + } + break; + default: + g_error ("Type 0x%x not handled yet in thunk creation", + sig->ret->type); + break; + } + } + + /*----------------------------------------------------------*/ + /* epilog */ + /*----------------------------------------------------------*/ + s390_lg (p, STK_BASE, 0, STK_BASE, 0); + s390_lg (p, s390_r4, 0, STK_BASE, S390_RET_ADDR_OFFSET); + s390_lmg (p, s390_r6, STK_BASE, STK_BASE, S390_REG_SAVE_OFFSET); + s390_br (p, s390_r4); + + DEBUG (printf ("emited code size: %d\n", p - code_buffer)); + + DEBUG (printf ("Delegate [end emiting]\n")); + + ji = g_new0 (MonoJitInfo, 1); + ji->method = method; + ji->code_size = p - code_buffer; + ji->code_start = code_buffer; + + mono_jit_info_table_add (mono_get_root_domain (), ji); + + return ji->code_start; +} + +/*========================= End of Function ========================*/ |