X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmini%2Fmini-s390x.c;h=b32953ca3e883bc3dc86edc96accdadb17c0ebc6;hb=ce6acbe4db3caca1d54f08f9758a88a7768ff236;hp=126d78c513bc195b242f0703a47b31442a20021d;hpb=679be0d28fc7ecdd24864383a2127e030c6913d8;p=mono.git diff --git a/mono/mini/mini-s390x.c b/mono/mini/mini-s390x.c index 126d78c513b..b32953ca3e8 100644 --- a/mono/mini/mini-s390x.c +++ b/mono/mini/mini-s390x.c @@ -231,6 +231,9 @@ if (ins->inst_target_bb->native_offset) { \ #define S390_TRACE_STACK_SIZE (5*sizeof(gpointer)+4*sizeof(gdouble)) +#define BREAKPOINT_SIZE sizeof(breakpoint_t) +#define S390X_NOP_SIZE sizeof(I_Format) + #define MAX(a, b) ((a) > (b) ? (a) : (b)) /* @@ -243,6 +246,9 @@ if (ins->inst_target_bb->native_offset) { \ #define JUMP_SIZE 6 #define ENABLE_WRONG_METHOD_CHECK 0 +#define mono_mini_arch_lock() EnterCriticalSection (&mini_arch_mutex) +#define mono_mini_arch_unlock() LeaveCriticalSection (&mini_arch_mutex) + /*========================= End of Defines =========================*/ /*------------------------------------------------------------------*/ @@ -256,11 +262,13 @@ if (ins->inst_target_bb->native_offset) { \ #include #include #include +#include #include "mini-s390x.h" #include "cpu-s390x.h" #include "jit-icalls.h" #include "ir-emit.h" +#include "trace.h" /*========================= End of Includes ========================*/ @@ -337,6 +345,14 @@ typedef struct { gdouble fp[3]; /* F0-F2 */ } __attribute__ ((packed)) RegParm; +typedef struct { + RR_Format basr; + RI_Format j; + void *pTrigger; + RXY_Format lg; + RXY_Format trigger; +} __attribute__ ((packed)) breakpoint_t; + /*========================= End of Typedefs ========================*/ /*------------------------------------------------------------------*/ @@ -352,9 +368,8 @@ static gboolean is_regsize_var (MonoType *); static inline void add_general (guint *, size_data *, ArgInfo *); static inline void add_stackParm (guint *, size_data *, ArgInfo *, gint); static inline void add_float (guint *, size_data *, ArgInfo *); -static CallInfo * get_call_info (MonoCompile *, MonoMemPool *, MonoMethodSignature *, gboolean); +static CallInfo * get_call_info (MonoCompile *, MonoMemPool *, MonoMethodSignature *); static guchar * emit_float_to_int (MonoCompile *, guchar *, int, int, int, gboolean); -gpointer mono_arch_get_lmf_addr (void); static guint8 * emit_load_volatile_arguments (guint8 *, MonoCompile *); static void catch_SIGILL(int, siginfo_t *, void *); static __inline__ void emit_unwind_regs(MonoCompile *, guint8 *, int, int, long); @@ -371,10 +386,9 @@ static int indent_level = 0; int has_ld = 0; -static gboolean tls_offset_inited = FALSE; - -static int appdomain_tls_offset = -1, - thread_tls_offset = -1; +static gint appdomain_tls_offset = -1, + lmf_tls_offset = -1, + lmf_addr_tls_offset = -1; pthread_key_t lmf_addr_key; @@ -390,6 +404,24 @@ 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. + */ +static gpointer ss_trigger_page; + +/* + * Enabled breakpoints read from this trigger page + */ +static gpointer bp_trigger_page; + +breakpoint_t breakpointCode; + +/* + * This mutex protects architecture specific caches + */ +static CRITICAL_SECTION mini_arch_mutex; + /*====================== End of Global Variables ===================*/ /*------------------------------------------------------------------*/ @@ -461,7 +493,7 @@ mono_arch_fregname (int reg) { /*------------------------------------------------------------------*/ int -mono_arch_get_argument_info (MonoMethodSignature *csig, +mono_arch_get_argument_info (MonoGenericSharingContext *gsctx, MonoMethodSignature *csig, int param_count, MonoJitArgumentInfo *arg_info) { @@ -612,6 +644,97 @@ indent (int diff) { /*========================= End of Function ========================*/ +/*------------------------------------------------------------------*/ +/* */ +/* Name - cvtMonoType */ +/* */ +/* Function - Convert a mono-type to a string. */ +/* */ +/*------------------------------------------------------------------*/ + +static const char * +cvtMonoType(MonoTypeEnum t) +{ + switch(t) + { + case MONO_TYPE_END: + return "MONO_TYPE_END"; + case MONO_TYPE_VOID: + return "MONO_TYPE_VOID"; + case MONO_TYPE_BOOLEAN: + return "MONO_TYPE_BOOLEAN"; + case MONO_TYPE_CHAR: + return "MONO_TYPE_CHAR"; + case MONO_TYPE_I1: + return "MONO_TYPE_I1"; + case MONO_TYPE_U1: + return "MONO_TYPE_U1"; + case MONO_TYPE_I2: + return "MONO_TYPE_I2"; + case MONO_TYPE_U2: + return "MONO_TYPE_U2"; + case MONO_TYPE_I4: + return "MONO_TYPE_I4"; + case MONO_TYPE_U4: + return "MONO_TYPE_U4"; + case MONO_TYPE_I8: + return "MONO_TYPE_I8"; + case MONO_TYPE_U8: + return "MONO_TYPE_U8"; + case MONO_TYPE_R4: + return "MONO_TYPE_R4"; + case MONO_TYPE_R8: + return "MONO_TYPE_R8"; + case MONO_TYPE_STRING: + return "MONO_TYPE_STRING"; + case MONO_TYPE_PTR: + return "MONO_TYPE_PTR"; + case MONO_TYPE_BYREF: + return "MONO_TYPE_BYREF"; + case MONO_TYPE_VALUETYPE: + return "MONO_TYPE_VALUETYPE"; + case MONO_TYPE_CLASS: + return "MONO_TYPE_CLASS"; + case MONO_TYPE_VAR: + return "MONO_TYPE_VAR"; + case MONO_TYPE_ARRAY: + return "MONO_TYPE_ARRAY"; + case MONO_TYPE_GENERICINST: + return "MONO_TYPE_GENERICINST"; + case MONO_TYPE_TYPEDBYREF: + return "MONO_TYPE_TYPEDBYREF"; + case MONO_TYPE_I: + return "MONO_TYPE_I"; + case MONO_TYPE_U: + return "MONO_TYPE_U"; + case MONO_TYPE_FNPTR: + return "MONO_TYPE_FNPTR"; + case MONO_TYPE_OBJECT: + return "MONO_TYPE_OBJECT"; + case MONO_TYPE_SZARRAY: + return "MONO_TYPE_SZARRAY"; + case MONO_TYPE_MVAR: + return "MONO_TYPE_MVAR"; + case MONO_TYPE_CMOD_REQD: + return "MONO_TYPE_CMOD_REQD"; + case MONO_TYPE_CMOD_OPT: + return "MONO_TYPE_CMOD_OPT"; + case MONO_TYPE_INTERNAL: + return "MONO_TYPE_INTERNAL"; + case MONO_TYPE_MODIFIER: + return "MONO_TYPE_MODIFIER"; + case MONO_TYPE_SENTINEL: + return "MONO_TYPE_SENTINEL"; + case MONO_TYPE_PINNED: + return "MONO_TYPE_PINNED"; + default: + ; + } + return "unknown"; +} + +/*========================= End of Function ========================*/ + /*------------------------------------------------------------------*/ /* */ /* Name - decodeParm */ @@ -747,7 +870,7 @@ enum_parmtype: printf("[VALUETYPE:"); for (i = 0; i < size; i++) printf("%02x,", *((guint8 *)curParm+i)); - printf("]"); + printf("], "); break; } case MONO_TYPE_TYPEDBYREF: { @@ -759,7 +882,7 @@ enum_parmtype: break; } default : - printf("[?? - %d], ",simpleType); + printf("[%s], ",cvtMonoType(simpleType)); } } } @@ -801,7 +924,7 @@ enter_method (MonoMethod *method, RegParm *rParm, char *sp) sig = mono_method_signature (method); - cinfo = get_call_info (NULL, NULL, sig, sig->pinvoke); + cinfo = get_call_info (NULL, NULL, sig); if (cinfo->struct_ret) { printf ("[STRUCTRET:%p], ", (gpointer) rParm->gr[0]); @@ -811,24 +934,32 @@ enter_method (MonoMethod *method, RegParm *rParm, char *sp) if (sig->hasthis) { gpointer *this = (gpointer *) rParm->gr[iParm]; obj = (MonoObject *) this; - if (method->klass->valuetype) { + switch(method->klass->this_arg.type) { + case MONO_TYPE_VALUETYPE: if (obj) { - printf("this:[value:%p:%016lx], ", - this, *((guint64 *)(this+sizeof(MonoObject)))); + guint64 *value = (guint64 *) ((uintptr_t)this + sizeof(MonoObject)); + printf("this:[value:%p:%016lx], ", this, *value); } else printf ("this:[NULL], "); - } else { + break; + case MONO_TYPE_STRING: if (obj) { - class = obj->vtable->klass; - if (class == mono_defaults.string_class) { - printf ("this:[STRING:%p:%s], ", - obj, mono_string_to_utf8 ((MonoString *)obj)); - } else { - printf ("this:%p[%s.%s], ", - obj, class->name_space, class->name); - } + if (obj->vtable) { + class = obj->vtable->klass; + if (class == mono_defaults.string_class) { + printf ("this:[STRING:%p:%s], ", + obj, mono_string_to_utf8 ((MonoString *)obj)); + } else { + printf ("this:%p[%s.%s], ", + obj, class->name_space, class->name); + } + } else + printf("vtable:[NULL], "); } else - printf ("this:NULL, "); + printf ("this:[NULL], "); + break; + default : + printf("this[%s]: %p, ",cvtMonoType(method->klass->this_arg.type),this); } oParm++; } @@ -1184,6 +1315,8 @@ mono_arch_cpu_init (void) void mono_arch_init (void) { + guint8 *code; + #if 0 /* * When we do an architectural level set at z9 or better @@ -1199,6 +1332,16 @@ mono_arch_init (void) : "=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); + + code = (guint8 *) &breakpointCode; + s390_basr(code, s390_r13, 0); + s390_j(code, 6); + s390_llong(code, 0); + s390_lg(code, s390_r13, 0, s390_r13, 4); + s390_lg(code, s390_r0, 0, s390_r13, 0); } /*========================= End of Function ========================*/ @@ -1220,14 +1363,14 @@ mono_arch_cleanup (void) /*------------------------------------------------------------------*/ /* */ -/* Name - mono_arch_cpu_optimizazions */ +/* Name - mono_arch_cpu_optimizations */ /* */ /* Function - Returns the optimizations supported on this CPU */ /* */ /*------------------------------------------------------------------*/ guint32 -mono_arch_cpu_optimizazions (guint32 *exclude_mask) +mono_arch_cpu_optimizations (guint32 *exclude_mask) { guint32 opts = 0; @@ -1241,6 +1384,21 @@ mono_arch_cpu_optimizazions (guint32 *exclude_mask) /*========================= End of Function ========================*/ +/*------------------------------------------------------------------*/ +/* */ +/* Name - mono_arch_cpu_enumerate_simd_versions */ +/* */ +/* Function - Returns the SIMD instruction sets on this CPU */ +/* */ +/*------------------------------------------------------------------*/ +guint32 +mono_arch_cpu_enumerate_simd_versions (void) +{ + /* SIMD is currently unimplemented */ + return 0; +} +/*========================= End of Function ========================*/ + /*------------------------------------------------------------------*/ /* */ /* Name - */ @@ -1473,12 +1631,13 @@ add_float (guint *fr, size_data *sz, ArgInfo *ainfo) /*------------------------------------------------------------------*/ static CallInfo * -get_call_info (MonoCompile *cfg, MonoMemPool *mp, MonoMethodSignature *sig, gboolean is_pinvoke) +get_call_info (MonoCompile *cfg, MonoMemPool *mp, MonoMethodSignature *sig) { guint i, fr, gr, size, pstart; int nParm = sig->hasthis + sig->param_count; MonoType *ret_type; - guint32 simpletype, align; + guint32 simpleType, align; + gboolean is_pinvoke = sig->pinvoke; CallInfo *cinfo; size_data *sz; MonoGenericSharingContext *gsctx = cfg ? cfg->generic_sharing_context : NULL; @@ -1500,6 +1659,8 @@ get_call_info (MonoCompile *cfg, MonoMemPool *mp, MonoMethodSignature *sig, gboo sz->code_size = 0; sz->parm_size = 0; sz->local_size = 0; + align = 0; + size = 0; /*----------------------------------------------------------*/ /* We determine the size of the return code/stack in case we*/ @@ -1507,11 +1668,11 @@ get_call_info (MonoCompile *cfg, MonoMemPool *mp, MonoMethodSignature *sig, gboo /* area that the callee will use. */ /*----------------------------------------------------------*/ - ret_type = mono_type_get_underlying_type (sig->ret); + ret_type = mini_type_get_underlying_type (gsctx, sig->ret); ret_type = mini_get_basic_type_from_generic (gsctx, ret_type); - simpletype = ret_type->type; + simpleType = ret_type->type; enum_retvalue: - switch (simpletype) { + switch (simpleType) { case MONO_TYPE_BOOLEAN: case MONO_TYPE_I1: case MONO_TYPE_U1: @@ -1552,13 +1713,10 @@ enum_retvalue: case MONO_TYPE_VALUETYPE: { MonoClass *klass = mono_class_from_mono_type (sig->ret); if (klass->enumtype) { - simpletype = mono_class_enum_basetype (klass)->type; + simpleType = mono_class_enum_basetype (klass)->type; goto enum_retvalue; } - if (sig->pinvoke) - size = mono_class_native_size (klass, &align); - else - size = mono_class_value_size (klass, &align); + size = mini_type_stack_size_full (gsctx, &klass->byval_arg, NULL, sig->pinvoke); cinfo->struct_ret = 1; cinfo->ret.size = size; @@ -1618,6 +1776,7 @@ enum_retvalue: if ((sig->call_convention == MONO_CALL_VARARG) && (sig->param_count == 0)) { gr = S390_LAST_ARG_REG + 1; + fr = S390_LAST_FPARG_REG + 1; /* Emit the signature cookie just before the implicit arguments */ add_general (&gr, sz, &cinfo->sigCookie); @@ -1639,6 +1798,7 @@ enum_retvalue: if ((sig->call_convention == MONO_CALL_VARARG) && (i == sig->sentinelpos)) { gr = S390_LAST_ARG_REG + 1; + fr = S390_LAST_FPARG_REG + 1; add_general (&gr, sz, &cinfo->sigCookie); } @@ -1649,11 +1809,11 @@ enum_retvalue: continue; } - ptype = mono_type_get_underlying_type (sig->params [i]); - ptype = mini_get_basic_type_from_generic (gsctx, ptype); - simpletype = ptype->type; - cinfo->args[nParm].type = simpletype; - switch (simpletype) { + ptype = mini_type_get_underlying_type (gsctx, sig->params [i]); +// ptype = mini_get_basic_type_from_generic (gsctx, ptype); + simpleType = ptype->type; + cinfo->args[nParm].type = simpleType; + switch (simpleType) { case MONO_TYPE_BOOLEAN: case MONO_TYPE_I1: case MONO_TYPE_U1: @@ -1704,7 +1864,7 @@ enum_retvalue: nParm++; break; case MONO_TYPE_GENERICINST: - if (!mono_type_generic_inst_is_valuetype (sig->params [i])) { + if (!mono_type_generic_inst_is_valuetype (ptype)) { cinfo->args[nParm].size = sizeof(gpointer); add_general (&gr, sz, cinfo->args+nParm); nParm++; @@ -1713,30 +1873,29 @@ enum_retvalue: /* Fall through */ case MONO_TYPE_VALUETYPE: { MonoMarshalType *info; - MonoClass *klass = mono_class_from_mono_type (sig->params [i]); - if (sig->pinvoke) - size = mono_class_native_size (klass, &align); - else - size = mono_class_value_size (klass, &align); - - info = mono_marshal_load_type_info (klass); + MonoClass *klass = mono_class_from_mono_type (ptype); - if ((info->native_size == sizeof(float)) && - (info->num_fields == 1) && - (info->fields[0].field->type->type == MONO_TYPE_R4)) { - cinfo->args[nParm].size = sizeof(float); - add_float(&fr, sz, cinfo->args+nParm); - nParm ++; - break; - } + size = mini_type_stack_size_full(gsctx, &klass->byval_arg, NULL, sig->pinvoke); + if (simpleType != MONO_TYPE_GENERICINST) { + info = mono_marshal_load_type_info(klass); - if ((info->native_size == sizeof(double)) && - (info->num_fields == 1) && - (info->fields[0].field->type->type == MONO_TYPE_R8)) { - cinfo->args[nParm].size = sizeof(double); - add_float(&fr, sz, cinfo->args+nParm); - nParm ++; - break; + if ((info->native_size == sizeof(float)) && + (info->num_fields == 1) && + (info->fields[0].field->type->type == MONO_TYPE_R4)) { + cinfo->args[nParm].size = sizeof(float); + add_float(&fr, sz, cinfo->args+nParm); + nParm ++; + break; + } + + if ((info->native_size == sizeof(double)) && + (info->num_fields == 1) && + (info->fields[0].field->type->type == MONO_TYPE_R8)) { + cinfo->args[nParm].size = sizeof(double); + add_float(&fr, sz, cinfo->args+nParm); + nParm ++; + break; + } } cinfo->args[nParm].vtsize = 0; @@ -1795,7 +1954,7 @@ enum_retvalue: } break; default: - g_error ("Can't trampoline 0x%x", sig->params [i]->type); + g_error ("Can't trampoline 0x%x", ptype); } } @@ -1807,6 +1966,7 @@ enum_retvalue: (!sig->pinvoke) && (sig->param_count == sig->sentinelpos)) { gr = S390_LAST_ARG_REG + 1; + fr = S390_LAST_FPARG_REG + 1; add_general (&gr, sz, &cinfo->sigCookie); } @@ -1888,7 +2048,7 @@ mono_arch_allocate_vars (MonoCompile *cfg) sig = mono_method_signature (cfg->method); - cinfo = get_call_info (cfg, cfg->mempool, sig, sig->pinvoke); + cinfo = get_call_info (cfg, cfg->mempool, sig); if (!cinfo->struct_ret) { switch (mono_type_get_underlying_type (sig->ret)->type) { @@ -2027,16 +2187,21 @@ mono_arch_allocate_vars (MonoCompile *cfg) } break; } +#if 0 if ((sig->call_convention == MONO_CALL_VARARG) && (cinfo->args[iParm].regtype != RegTypeGeneral) && (iParm < sig->sentinelpos)) cfg->sig_cookie += size; +printf("%s %4d cookine %x\n",__FUNCTION__,__LINE__,cfg->sig_cookie); +#endif offset += MAX(size, 8); } curinst++; } + cfg->locals_min_stack_offset = offset; + curinst = cfg->locals_start; for (iVar = curinst; iVar < cfg->num_varinfo; ++iVar) { inst = cfg->varinfo [iVar]; @@ -2064,6 +2229,8 @@ mono_arch_allocate_vars (MonoCompile *cfg) iVar, inst->inst_offset, size)); } + cfg->locals_max_stack_offset = offset; + /*------------------------------------------------------*/ /* Allow space for the trace method stack area if needed*/ /*------------------------------------------------------*/ @@ -2110,7 +2277,7 @@ mono_arch_create_vars (MonoCompile *cfg) sig = mono_method_signature (cfg->method); - cinfo = get_call_info (cfg, cfg->mempool, sig, sig->pinvoke); + cinfo = get_call_info (cfg, cfg->mempool, sig); if (cinfo->struct_ret) { cfg->vret_addr = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_ARG); @@ -2225,7 +2392,7 @@ mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call) n = sig->param_count + sig->hasthis; DEBUG (g_print ("Call requires: %d parameters\n",n)); - cinfo = get_call_info (cfg, cfg->mempool, sig, sig->pinvoke); + cinfo = get_call_info (cfg, cfg->mempool, sig); stackSize = cinfo->sz.stack_size + cinfo->sz.local_size + cinfo->sz.parm_size + cinfo->sz.offset; @@ -2335,6 +2502,12 @@ mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call) frmReg, ainfo->offparm); MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, ainfo->reg, ainfo->offset, treg); + + if (cfg->compute_gc_maps) { + MonoInst *def; + + EMIT_NEW_GC_PARAM_SLOT_LIVENESS_DEF (cfg, def, ainfo->offset, t); + } } break; } @@ -2446,6 +2619,12 @@ mono_arch_emit_outarg_vt (MonoCompile *cfg, MonoInst *ins, MonoInst *src) MONO_EMIT_NEW_MOVE (cfg, srcReg, ainfo->offparm, src->dreg, 0, size); + + if (cfg->compute_gc_maps) { + MonoInst *def; + + EMIT_NEW_GC_PARAM_SLOT_LIVENESS_DEF (cfg, def, ainfo->offset, &ins->klass->byval_arg); + } } } @@ -3952,6 +4131,21 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) s390_ledbr (code, ins->dreg, ins->sreg1); } break; + case OP_TLS_GET: { + if (s390_is_imm16 (ins->inst_offset)) { + s390_lghi (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_ear (code, s390_r1, 0); + s390_sllg(code, s390_r1, s390_r1, 0, 32); + s390_ear (code, s390_r1, 1); + s390_lg (code, ins->dreg, s390_r13, s390_r1, 0); + } + break; case OP_JMP: { if (cfg->method->save_lmf) restoreLMF(code, cfg->frame_reg, cfg->stack_usage); @@ -3972,6 +4166,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) /* ensure ins->sreg1 is not NULL */ s390_lg (code, s390_r0, 0, ins->sreg1, 0); s390_ltgr (code, s390_r0, s390_r0); + EMIT_COND_SYSTEM_EXCEPTION (S390_CC_ZR, "NullReferenceException"); } break; case OP_ARGLIST: { @@ -4185,6 +4380,35 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) case OP_NOT_NULL: { } break; + case OP_SEQ_POINT: { + int i; + + if (cfg->compile_aot) + NOT_IMPLEMENTED; + + /* + * Read from the single stepping trigger page. This will cause a + * SIGSEGV when single stepping is enabled. + * We do this _before_ the breakpoint, so single stepping after + * a breakpoint is hit will step to the next IL offset. + */ + if (ins->flags & MONO_INST_SINGLE_STEP_LOC) { + breakpointCode.pTrigger = ss_trigger_page; + memcpy(code, (void *) &breakpointCode, BREAKPOINT_SIZE); + code += BREAKPOINT_SIZE; + } + + mono_add_seq_point (cfg, bb, ins, code - cfg->native_code); + + /* + * A placeholder for a possible breakpoint inserted by + * mono_arch_set_breakpoint (). + */ + for (i = 0; i < (BREAKPOINT_SIZE / S390X_NOP_SIZE); ++i) + s390_nop (code); + break; + } + case OP_BR: EMIT_UNCOND_BRANCH(ins); break; @@ -4315,7 +4539,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) /* floating point opcodes */ case OP_R8CONST: { - if (*((float *) ins->inst_p0) == 0) { + if (*((double *) ins->inst_p0) == 0) { s390_lzdr (code, ins->dreg); } else { s390_basr (code, s390_r13, 0); @@ -4684,6 +4908,15 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) case OP_MEMORY_BARRIER: { } break; + case OP_GC_LIVENESS_DEF: + case OP_GC_LIVENESS_USE: + case OP_GC_PARAM_SLOT_LIVENESS_DEF: + ins->backend.pc_offset = code - cfg->native_code; + break; + case OP_GC_SPILL_SLOT_LIVENESS_DEF: + ins->backend.pc_offset = code - cfg->native_code; + bb->spill_slot_defs = g_slist_prepend_mempool (cfg->mempool, bb->spill_slot_defs, ins); + break; default: g_warning ("unknown opcode %s in %s()\n", mono_inst_name (ins->opcode), __FUNCTION__); g_assert_not_reached (); @@ -4716,7 +4949,6 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) void mono_arch_register_lowlevel_calls (void) { - mono_register_jit_icall (mono_arch_get_lmf_addr, "mono_arch_get_lmf_addr", NULL, TRUE); } /*========================= End of Function ========================*/ @@ -4733,7 +4965,7 @@ mono_arch_register_lowlevel_calls (void) void mono_arch_patch_code (MonoMethod *method, MonoDomain *domain, - guint8 *code, MonoJumpInfo *ji, gboolean run_cctors) + guint8 *code, MonoJumpInfo *ji, MonoCodeManager *dyn_code_mp, gboolean run_cctors) { MonoJumpInfo *patch_info; @@ -4753,8 +4985,11 @@ mono_arch_patch_code (MonoMethod *method, MonoDomain *domain, case MONO_PATCH_INFO_EXC: case MONO_PATCH_INFO_ABS: 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_GENERIC_CLASS_INIT: s390_patch_addr (ip, (guint64) target); continue; case MONO_PATCH_INFO_SWITCH: @@ -4811,7 +5046,7 @@ emit_load_volatile_arguments (guint8 *code, MonoCompile *cfg) int pos = 0, i; CallInfo *cinfo; - cinfo = get_call_info (NULL, NULL, sig, sig->pinvoke); + cinfo = get_call_info (NULL, NULL, sig); if (cinfo->struct_ret) { ArgInfo *ainfo = &cinfo->ret; @@ -4965,6 +5200,15 @@ mono_arch_emit_prolog (MonoCompile *cfg) mono_emit_unwind_op_def_cfa_reg (cfg, code, cfg->frame_reg); + /* store runtime generic context */ + if (cfg->rgctx_var) { + g_assert (cfg->rgctx_var->opcode == OP_REGOFFSET); + + s390_stg (code, MONO_ARCH_RGCTX_REG, 0, + cfg->rgctx_var->inst_basereg, + cfg->rgctx_var->inst_offset); + } + /* compute max_offset in order to use short forward jumps * we always do it on s390 because the immediate displacement * for jumps is too small @@ -4985,7 +5229,7 @@ mono_arch_emit_prolog (MonoCompile *cfg) sig = mono_method_signature (method); pos = 0; - cinfo = get_call_info (cfg, cfg->mempool, sig, sig->pinvoke); + cinfo = get_call_info (cfg, cfg->mempool, sig); if (cinfo->struct_ret) { ArgInfo *ainfo = &cinfo->ret; @@ -5097,7 +5341,7 @@ mono_arch_emit_prolog (MonoCompile *cfg) if (method->save_lmf) { /*---------------------------------------------------------------*/ - /* we build the MonoLMF structure on the stack - see mini-s390.h */ + /* build the MonoLMF structure on the stack - see mini-s390x.h */ /*---------------------------------------------------------------*/ lmfOffset = alloc_size - sizeof(MonoLMF); @@ -5113,14 +5357,24 @@ mono_arch_emit_prolog (MonoCompile *cfg) /*---------------------------------------------------------------*/ /* On return from this call r2 have the address of the &lmf */ /*---------------------------------------------------------------*/ - 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); + 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); + } else { + /*-------------------------------------------------------*/ + /* Get LMF by getting value from thread level storage */ + /*-------------------------------------------------------*/ + s390_ear (code, s390_r1, 0); + s390_sllg(code, s390_r1, s390_r1, 0, 32); + s390_ear (code, s390_r1, 1); + s390_lg (code, s390_r2, 0, s390_r1, lmf_addr_tls_offset); + } /*---------------------------------------------------------------*/ /* Set lmf.lmf_addr = jit_tls->lmf */ @@ -5217,7 +5471,7 @@ mono_arch_emit_epilog (MonoCompile *cfg) while ((cfg->code_len + max_epilog_size) > (cfg->code_size - 16)) { cfg->code_size *= 2; cfg->native_code = g_realloc (cfg->native_code, cfg->code_size); - mono_jit_stats.code_reallocs++; + cfg->stat_code_reallocs++; } code = cfg->native_code + cfg->code_len; @@ -5280,7 +5534,7 @@ mono_arch_emit_exceptions (MonoCompile *cfg) while ((cfg->code_len + code_size) > (cfg->code_size - 16)) { cfg->code_size *= 2; cfg->native_code = g_realloc (cfg->native_code, cfg->code_size); - mono_jit_stats.code_reallocs++; + cfg->stat_code_reallocs++; } code = cfg->native_code + cfg->code_len; @@ -5364,44 +5618,18 @@ mono_arch_emit_exceptions (MonoCompile *cfg) /*------------------------------------------------------------------*/ /* */ -/* Name - mono_arch_setup_jit_tls_data */ +/* Name - mono_arch_finish_init */ /* */ /* Function - Setup the JIT's Thread Level Specific Data. */ /* */ /*------------------------------------------------------------------*/ void -mono_arch_setup_jit_tls_data (MonoJitTlsData *tls) +mono_arch_finish_init (void) { - if (!tls_offset_inited) { - tls_offset_inited = TRUE; - -#if HAVE_KW_THREAD -# if 0 - __asm__ ("\tear\t%r1,0\n" - "\tlr\t%0,%3\n" - "\tsr\t%0,%r1\n" - "\tlr\t%1,%4\n" - "\tsr\t%1,%r1\n" - "\tlr\t%2,%5\n" - "\tsr\t%2,%r1\n" - : "=r" (appdomain_tls_offset), - "=r" (thread_tls_offset), - "=r" (lmf_tls_offset) - : "r" (&tls_appdomain), - "r" (&tls_current_object), - "r" (&mono_lmf_addr) - : "1", "cc"); -# endif -#endif - } - - if (!lmf_addr_key_inited) { - lmf_addr_key_inited = TRUE; - pthread_key_create (&lmf_addr_key, NULL); - } - pthread_setspecific (lmf_addr_key, &tls->lmf); - + appdomain_tls_offset = mono_domain_get_tls_offset(); + lmf_tls_offset = mono_get_lmf_tls_offset(); + lmf_addr_tls_offset = mono_get_lmf_addr_tls_offset(); } /*========================= End of Function ========================*/ @@ -5607,24 +5835,6 @@ mono_arch_flush_register_windows (void) /*========================= End of Function ========================*/ -/*------------------------------------------------------------------*/ -/* */ -/* Name - mono_arch_get_lmf_addr */ -/* */ -/* Function - */ -/* */ -/* Returns - */ -/* */ -/*------------------------------------------------------------------*/ - -gpointer -mono_arch_get_lmf_addr (void) -{ - return pthread_getspecific (lmf_addr_key); -} - -/*========================= End of Function ========================*/ - /*------------------------------------------------------------------*/ /* */ /* Name - mono_arch_is_inst_imm */ @@ -5668,16 +5878,30 @@ mono_arch_get_patch_offset (guint8 *code) /* */ /* Function - */ /* */ -/* Returns - Offset for patch. */ +/* Returns - Return a register from the context. */ /* */ /*------------------------------------------------------------------*/ -gpointer +mgreg_t mono_arch_context_get_int_reg (MonoContext *ctx, int reg) { - /* FIXME: implement */ - g_assert_not_reached (); - return NULL; + return ((mgreg_t) ctx->uc_mcontext.gregs[reg]); +} + +/*========================= End of Function ========================*/ + +/*------------------------------------------------------------------*/ +/* */ +/* Name - mono_arch_context_set_int_reg. */ +/* */ +/* Function - Set a value in a specified register. */ +/* */ +/*------------------------------------------------------------------*/ + +void +mono_arch_context_set_int_reg (MonoContext *ctx, int reg, mgreg_t val) +{ + ctx->uc_mcontext.gregs[reg] = val; } /*========================= End of Function ========================*/ @@ -6024,3 +6248,218 @@ mono_arch_find_imt_method (mgreg_t *regs, guint8 *code) } /*========================= End of Function ========================*/ + +/*------------------------------------------------------------------*/ +/* */ +/* Name - mono_arch_find_static_call_vtable */ +/* */ +/* Function - Find the static call vtable. */ +/* */ +/*------------------------------------------------------------------*/ + +MonoVTable* +mono_arch_find_static_call_vtable (mgreg_t *regs, guint8 *code) +{ + mgreg_t *r = (mgreg_t*)regs; + + return (MonoVTable*)(gsize) r [MONO_ARCH_RGCTX_REG]; +} + +/*========================= End of Function ========================*/ + +/*------------------------------------------------------------------*/ +/* */ +/* Name - mono_arch_get_cie_program */ +/* */ +/* Function - Find the static call vtable. */ +/* */ +/*------------------------------------------------------------------*/ + +GSList* +mono_arch_get_cie_program (void) +{ + GSList *l = NULL; + + mono_add_unwind_op_def_cfa (l, NULL, NULL, STK_BASE, 0); + + return(l); +} + +/*========================= End of Function ========================*/ + +#ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED + +/*------------------------------------------------------------------*/ +/* */ +/* Name - mono_arch_set_breakpoint. */ +/* */ +/* Function - Set a breakpoint at the native code corresponding */ +/* to JI at NATIVE_OFFSET. The location should */ +/* contain code emitted by OP_SEQ_POINT. */ +/* */ +/*------------------------------------------------------------------*/ + +void +mono_arch_set_breakpoint (MonoJitInfo *ji, guint8 *ip) +{ + guint8 *code = ip; + + breakpointCode.pTrigger = bp_trigger_page; + memcpy(code, (void *) &breakpointCode, BREAKPOINT_SIZE); + code += BREAKPOINT_SIZE; +} + +/*========================= End of Function ========================*/ + +/*------------------------------------------------------------------*/ +/* */ +/* Name - mono_arch_clear_breakpoint. */ +/* */ +/* Function - Clear the breakpoint at IP. */ +/* */ +/*------------------------------------------------------------------*/ + +void +mono_arch_clear_breakpoint (MonoJitInfo *ji, guint8 *ip) +{ + guint8 *code = ip; + int i; + + for (i = 0; i < (BREAKPOINT_SIZE / S390X_NOP_SIZE); i++) + s390_nop(code); +} + +/*========================= End of Function ========================*/ + +/*------------------------------------------------------------------*/ +/* */ +/* Name - mono_arch_is_breakpoint_event. */ +/* */ +/* Function - */ +/* */ +/*------------------------------------------------------------------*/ + +gboolean +mono_arch_is_breakpoint_event (void *info, void *sigctx) +{ + siginfo_t* sinfo = (siginfo_t*) info; + /* Sometimes the address is off by 4 */ + if (sinfo->si_addr >= bp_trigger_page && (guint8*)sinfo->si_addr <= (guint8*)bp_trigger_page + 128) + return TRUE; + else + return FALSE; +} + +/*========================= End of Function ========================*/ + +/*------------------------------------------------------------------*/ +/* */ +/* Name - mono_arch_skip_breakpoint. */ +/* */ +/* Function - Modify the CTX so the IP is placed after the */ +/* breakpoint instruction, so when we resume, the */ +/* instruction is not executed again. */ +/* */ +/*------------------------------------------------------------------*/ + +void +mono_arch_skip_breakpoint (MonoContext *ctx, MonoJitInfo *ji) +{ + MONO_CONTEXT_SET_IP (ctx, (guint8*)MONO_CONTEXT_GET_IP (ctx) + BREAKPOINT_SIZE); +} + +/*========================= End of Function ========================*/ + +/*------------------------------------------------------------------*/ +/* */ +/* Name - mono_arch_start_single_stepping. */ +/* */ +/* Function - Start single stepping. */ +/* */ +/*------------------------------------------------------------------*/ + +void +mono_arch_start_single_stepping (void) +{ + mono_mprotect (ss_trigger_page, mono_pagesize (), 0); +} + +/*========================= End of Function ========================*/ + +/*------------------------------------------------------------------*/ +/* */ +/* Name - mono_arch_stop_single_stepping. */ +/* */ +/* Function - Stop single stepping. */ +/* */ +/*------------------------------------------------------------------*/ + +void +mono_arch_stop_single_stepping (void) +{ + mono_mprotect (ss_trigger_page, mono_pagesize (), MONO_MMAP_READ); +} + +/*========================= End of Function ========================*/ + +/*------------------------------------------------------------------*/ +/* */ +/* Name - mono_arch_is_single_step_event. */ +/* */ +/* Function - Return whether the machine state in sigctx cor- */ +/* responds to a single step event. */ +/* */ +/*------------------------------------------------------------------*/ + +gboolean +mono_arch_is_single_step_event (void *info, void *sigctx) +{ + siginfo_t* sinfo = (siginfo_t*) info; + + /* Sometimes the address is off by 4 */ + if (sinfo->si_addr >= ss_trigger_page && (guint8*)sinfo->si_addr <= (guint8*)ss_trigger_page + 128) + return TRUE; + else + return FALSE; +} + +/*========================= End of Function ========================*/ + +/*------------------------------------------------------------------*/ +/* */ +/* Name - mono_arch_skip_single_step. */ +/* */ +/* Function - Modify the ctx so the IP is placed after the */ +/* single step trigger instruction, so that the */ +/* instruction is not executed again. */ +/* */ +/*------------------------------------------------------------------*/ + +void +mono_arch_skip_single_step (MonoContext *ctx) +{ + MONO_CONTEXT_SET_IP (ctx, (guint8*)MONO_CONTEXT_GET_IP (ctx) + BREAKPOINT_SIZE); +} + +/*========================= End of Function ========================*/ + +/*------------------------------------------------------------------*/ +/* */ +/* Name - mono_arch_create_seq_point_info. */ +/* */ +/* Function - Return a pointer to a data struction which is */ +/* used by the sequence point implementation in */ +/* AOTed code. */ +/* */ +/*------------------------------------------------------------------*/ + +gpointer +mono_arch_get_seq_point_info (MonoDomain *domain, guint8 *code) +{ + NOT_IMPLEMENTED; + return NULL; +} + +/*========================= End of Function ========================*/ + +#endif