From d211a9804e44881a186c01635d96a3f778016c36 Mon Sep 17 00:00:00 2001 From: Neale Ferguson Date: Wed, 17 Nov 2004 03:05:28 +0000 Subject: [PATCH] Add support for siginfo_t as a parameter to mono_arch_is_int_overflow. Support this routine in s390. svn path=/trunk/mono/; revision=36188 --- mono/arch/s390/ChangeLog | 5 +- mono/arch/s390/s390-codegen.h | 6 +- mono/mini/ChangeLog | 7 ++ mono/mini/cpu-s390.md | 2 +- mono/mini/exceptions-s390.c | 69 +++++++++++- mono/mini/mini-amd64.c | 2 +- mono/mini/mini-s390.c | 238 ++++++++++++++++++++---------------------- mono/mini/mini-s390.h | 54 ++++++++++ mono/mini/mini-x86.c | 2 +- mono/mini/mini.c | 5 +- mono/mini/mini.h | 2 +- mono/mini/tramp-s390.c | 79 ++++++++++++-- 12 files changed, 321 insertions(+), 150 deletions(-) diff --git a/mono/arch/s390/ChangeLog b/mono/arch/s390/ChangeLog index 6d033e72eea..1f01e893f19 100644 --- a/mono/arch/s390/ChangeLog +++ b/mono/arch/s390/ChangeLog @@ -1,4 +1,7 @@ +2004-11-15 Neale Ferguson + + * s390-codegen.h: Minor macro modifications + 2004-07-30 Neale Ferguson * s390-codegen.h: reworked macros for code generation. - diff --git a/mono/arch/s390/s390-codegen.h b/mono/arch/s390/s390-codegen.h index c1cabb57196..1742d20e2fb 100644 --- a/mono/arch/s390/s390-codegen.h +++ b/mono/arch/s390/s390-codegen.h @@ -137,9 +137,9 @@ typedef enum { #define s390_is_imm16(val) ((gint)val >= (gint)-(1<<15) && \ (gint)val <= (gint)((1<<15)-1)) -#define s390_is_uimm16(val) ((gint)val >= 0 && (gint)val <= 65535) +#define s390_is_uimm16(val) ((gint)val >= 0 && (gint)val <= 32767) #define s390_is_imm12(val) ((gint)val >= (gint)-(1<<11) && \ - (gint)val <= (gint)((1<<15)-1)) + (gint)val <= (gint)((1<<11)-1)) #define s390_is_uimm12(val) ((gint)val >= 0 && (gint)val <= 4095) #define STK_BASE s390_r15 @@ -573,6 +573,8 @@ typedef struct { #define s390_alr(c, r1, r2) S390_RR(c, 0x1e, r1, r2) #define s390_a(c, r, x, b, d) S390_RX(c, 0x5a, r, x, b, d) #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_slb(c, r, x, b, d) S390_RXY(c, 0xe399, r, x, b, d) #define s390_slbr(c, r1, r2) S390_RRE(c, 0xb999, r1, r2) #define s390_sr(c, r1, r2) S390_RR(c, 0x1b, r1, r2) #define s390_slr(c, r1, r2) S390_RR(c, 0x1f, r1, r2) diff --git a/mono/mini/ChangeLog b/mono/mini/ChangeLog index b7a9c5d8b42..cf4f14edbac 100644 --- a/mono/mini/ChangeLog +++ b/mono/mini/ChangeLog @@ -1,3 +1,10 @@ +2004-11-15 Nelae Ferguson + + * mini.c, mini-x86.c, mini-amd64.c, exceptions-s390.c: Add siginfo_t parameter + to mono_arch_is_int_overflow. + * exceptions-s390.c: Add mono_arch_is_int_overflow routine to discern between + SIGFPE events. + 2004-11-15 Sebastien Pouliot * declsec.c|h: New files to support declarative security attributes. diff --git a/mono/mini/cpu-s390.md b/mono/mini/cpu-s390.md index e5256040458..c1c66eb294d 100644 --- a/mono/mini/cpu-s390.md +++ b/mono/mini/cpu-s390.md @@ -417,6 +417,7 @@ not: dest:i src1:i len:8 clob:1 op_bigmul: len:2 dest:l src1:a src2:i op_bigmul_un: len:2 dest:l src1:a src2:i op_endfilter: src1:i len:12 +op_rethrow: src1:i len:8 oparglist: src1:i len:18 or: dest:i src1:i src2:i len:4 clob:1 or_imm: dest:i src1:i len:16 @@ -446,7 +447,6 @@ rem_un_imm: dest:i src1:i src2:i len:24 rename: ret: retarg: -rethrow: src1:i len:8 s390_move: len:48 dest:b src1:b s390_setf4ret: dest:f src1:f len:4 clob:r sbb: dest:i src1:i src2:i len:6 diff --git a/mono/mini/exceptions-s390.c b/mono/mini/exceptions-s390.c index 045a881e38a..246ac9dbce1 100644 --- a/mono/mini/exceptions-s390.c +++ b/mono/mini/exceptions-s390.c @@ -262,7 +262,6 @@ throw_exception (MonoObject *exc, unsigned long ip, unsigned long sp, gulong *int_regs, gdouble *fp_regs, gulong *acc_regs, guint fpc, gboolean rethrow) { - static void (*restore_context) (MonoContext *); MonoContext ctx; int iReg; @@ -514,8 +513,6 @@ mono_arch_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls, { MonoJitInfo *ji; gpointer ip = MONO_CONTEXT_GET_IP (ctx); - unsigned long *ptr; - char *p; MonoS390StackFrame *sframe; if (prev_ji && @@ -537,7 +534,6 @@ mono_arch_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls, if (ji != NULL) { char *source_location, *tmpaddr, *fname; gint32 address, iloffset; - int offset; *new_ctx = *ctx; @@ -825,7 +821,7 @@ mono_arch_handle_exception (void *uc, gpointer obj, gboolean test_only) if (mono_object_isinst (obj, mono_defaults.exception_class)) { mono_ex = (MonoException*)obj; - mono_ex->stack_trace = NULL; + initialStackTrace = mono_ex->stack_trace; } else { mono_ex = NULL; } @@ -997,3 +993,66 @@ mono_arch_ip_from_context (void *sigctx) /*========================= End of Function ========================*/ + +/*------------------------------------------------------------------*/ +/* */ +/* Name - mono_arch_is_int_overflow */ +/* */ +/* Function - Inspect the code that raised the SIGFPE signal */ +/* to see if the DivideByZero or Arithmetic exception*/ +/* should be raised. */ +/* */ +/*------------------------------------------------------------------*/ + +gboolean +mono_arch_is_int_overflow (void *uc, void *info) +{ + MonoContext *ctx; + guint8 *code; + guint32 *operand; + gboolean arithExc = TRUE; + gint regNo, + offset; + + ctx = (MonoContext *) uc; + code = (guint8 *) ((siginfo_t *)info)->si_addr; + /*----------------------------------------------------------*/ + /* Divide operations are the only ones that will give the */ + /* divide by zero exception so just check for these ops. */ + /*----------------------------------------------------------*/ + switch (code[0]) { + case 0x1d : /* Divide Register */ + regNo = code[1] & 0x0f; + if (ctx->uc_mcontext.gregs[regNo] == 0) + arithExc = FALSE; + break; + case 0x5d : /* Divide */ + regNo = (code[2] & 0xf0 >> 8); + offset = *((guint16 *) code+2) & 0x0fff; + operand = ctx->uc_mcontext.gregs[regNo] + offset; + if (*operand == 0) + arithExc = FALSE; + break; + case 0xb9 : /* Divide logical Register? */ + if (code[1] == 0x97) { + regNo = (code[2] & 0xf0 >> 8); + if (ctx->uc_mcontext.gregs[regNo] == 0) + arithExc = FALSE; + } + break; + case 0xe3 : /* Divide logical? */ + if (code[1] == 0x97) { + regNo = (code[2] & 0xf0 >> 8); + offset = *((guint32 *) code+1) & 0x000fffff; + operand = ctx->uc_mcontext.gregs[regNo] + offset; + if (*operand == 0) + arithExc = FALSE; + } + break; + default: + arithExc = TRUE; + } + return (arithExc); +} + +/*========================= End of Function ========================*/ diff --git a/mono/mini/mini-amd64.c b/mono/mini/mini-amd64.c index 805ba7a6464..f80360193b8 100644 --- a/mono/mini/mini-amd64.c +++ b/mono/mini/mini-amd64.c @@ -5279,7 +5279,7 @@ static int reg_to_ucontext_reg [] = { * integer overflow. */ gboolean -mono_arch_is_int_overflow (void *sigctx) +mono_arch_is_int_overflow (void *sigctx, void *info) { ucontext_t *ctx = (ucontext_t*)sigctx; guint8* rip; diff --git a/mono/mini/mini-s390.c b/mono/mini/mini-s390.c index c4b1f3555c1..cc377e1ca10 100644 --- a/mono/mini/mini-s390.c +++ b/mono/mini/mini-s390.c @@ -209,7 +209,6 @@ typedef struct { static guint32 * emit_memcpy (guint8 *, int, int, int, int, int); static void indent (int); -static guint8 * restoreLMF(MonoCompile *, guint8 *); static guint8 * backUpStackPtr(MonoCompile *, guint8 *); static void decodeParm (MonoType *, void *, int); static void enter_method (MonoMethod *, RegParm *, char *); @@ -392,48 +391,6 @@ mono_arch_get_argument_info (MonoMethodSignature *csig, /*------------------------------------------------------------------*/ /* */ -/* Name - restoreLMF */ -/* */ -/* Function - Restore the LMF state prior to exiting a method. */ -/* */ -/*------------------------------------------------------------------*/ - -static inline guint8 * -restoreLMF(MonoCompile *cfg, guint8 *code) -{ - int lmfOffset = 0; - - s390_lr (code, s390_r13, cfg->frame_reg); - - lmfOffset = cfg->stack_usage - sizeof(MonoLMF); - - /*-------------------------------------------------*/ - /* r13 = my lmf */ - /*-------------------------------------------------*/ - s390_ahi (code, s390_r13, lmfOffset); - - /*-------------------------------------------------*/ - /* r6 = &jit_tls->lmf */ - /*-------------------------------------------------*/ - s390_l (code, s390_r6, 0, s390_r13, G_STRUCT_OFFSET(MonoLMF, lmf_addr)); - - /*-------------------------------------------------*/ - /* r0 = lmf.previous_lmf */ - /*-------------------------------------------------*/ - s390_l (code, s390_r0, 0, s390_r13, G_STRUCT_OFFSET(MonoLMF, previous_lmf)); - - /*-------------------------------------------------*/ - /* jit_tls->lmf = previous_lmf */ - /*-------------------------------------------------*/ - s390_l (code, s390_r13, 0, s390_r6, 0); - s390_st (code, s390_r0, 0, s390_r6, 0); - return (code); -} - -/*========================= End of Function ========================*/ - -/*------------------------------------------------------------------*/ -/* */ /* Name - backStackPtr. */ /* */ /* Function - Restore Stack Pointer to previous frame. */ @@ -445,7 +402,7 @@ backUpStackPtr(MonoCompile *cfg, guint8 *code) { int stackSize = cfg->stack_usage; - if (s390_is_imm16 (cfg->stack_usage)) { + if (s390_is_uimm16 (cfg->stack_usage)) { s390_ahi (code, STK_BASE, cfg->stack_usage); } else { while (stackSize > 32767) { @@ -3092,7 +3049,7 @@ guint8 cond; break; case OP_STORE_MEMBASE_IMM: case OP_STOREI4_MEMBASE_IMM: { - if (s390_is_imm16(ins->inst_imm)) { + if (s390_is_uimm16(ins->inst_imm)) { s390_lhi (code, s390_r0, ins->inst_imm); } else { s390_basr (code, s390_r13, 0); @@ -3167,7 +3124,7 @@ guint8 cond; if (s390_is_uimm12(ins->inst_offset)) s390_l (code, ins->dreg, 0, ins->inst_basereg, ins->inst_offset); else { - if (s390_is_imm16(ins->inst_offset)) { + if (s390_is_uimm16(ins->inst_offset)) { s390_lhi (code, s390_r13, ins->inst_offset); s390_l (code, ins->dreg, s390_r13, ins->inst_basereg, 0); } else { @@ -3299,7 +3256,7 @@ guint8 cond; } break; case OP_COMPARE_IMM: { - if (s390_is_imm16 (ins->inst_imm)) { + if (s390_is_uimm16 (ins->inst_imm)) { s390_lhi (code, s390_r0, ins->inst_imm); if ((ins->next) && ((ins->next->opcode >= CEE_BNE_UN) && @@ -3370,7 +3327,7 @@ guint8 cond; } s390_al (code, ins->dreg, 0, s390_r13, 4); } else { - if (s390_is_imm16 (ins->inst_imm)) { + if (s390_is_uimm16 (ins->inst_imm)) { if (ins->dreg != ins->sreg1) { s390_lr (code, ins->dreg, ins->sreg1); } @@ -3388,7 +3345,7 @@ guint8 cond; } break; case OP_ADC_IMM: { - if (s390_is_imm16 (ins->inst_imm)) { + if (s390_is_uimm16 (ins->inst_imm)) { if (ins->dreg != ins->sreg1) { s390_lr (code, ins->dreg, ins->sreg1); } @@ -3461,9 +3418,25 @@ guint8 cond; s390_slbr (code, ins->dreg, ins->sreg2); } break; - case OP_SUBCC_IMM: + case OP_SUBCC_IMM: { + if (s390_is_uimm16 (-ins->inst_imm)) { + if (ins->dreg != ins->sreg1) { + s390_lr (code, ins->dreg, ins->sreg1); + } + s390_ahi (code, ins->dreg, -ins->inst_imm); + } else { + s390_basr (code, s390_r13, 0); + s390_j (code, 4); + s390_word (code, ins->inst_imm); + if (ins->dreg != ins->sreg1) { + s390_lr (code, ins->dreg, ins->sreg1); + } + s390_sl (code, ins->dreg, 0, s390_r13, 4); + } + } + break; case OP_SUB_IMM: { - if (s390_is_imm16 (-ins->inst_imm)) { + if (s390_is_uimm16 (-ins->inst_imm)) { if (ins->dreg != ins->sreg1) { s390_lr (code, ins->dreg, ins->sreg1); } @@ -3480,10 +3453,18 @@ guint8 cond; } break; case OP_SBB_IMM: { - s390_basr (code, s390_r13, 0); - s390_j (code, 4); - s390_word (code, ins->inst_imm); - s390_sl (code, ins->dreg, 0, s390_r13, 4); + if (ins->dreg != ins->sreg1) { + s390_lr (code, ins->dreg, ins->sreg1); + } + if (s390_is_uimm16 (-ins->inst_imm)) { + s390_lhi (code, s390_r0, ins->inst_imm); + s390_slbr (code, ins->dreg, s390_r0); + } else { + s390_basr (code, s390_r13, 0); + s390_j (code, 4); + s390_word (code, ins->inst_imm); + s390_slb (code, ins->dreg, 0, s390_r13, 4); + } } break; case CEE_SUB_OVF: { @@ -3539,7 +3520,7 @@ guint8 cond; } break; case OP_AND_IMM: { - if (s390_is_imm16 (ins->inst_imm)) { + if (s390_is_uimm16 (ins->inst_imm)) { s390_lhi (code, s390_r0, ins->inst_imm); if (ins->dreg != ins->sreg1) { s390_lr (code, ins->dreg, ins->sreg1); @@ -3571,7 +3552,7 @@ guint8 cond; } break; case OP_DIV_IMM: { - if (s390_is_imm16 (ins->inst_imm)) { + if (s390_is_uimm16 (ins->inst_imm)) { s390_lhi (code, s390_r13, ins->inst_imm); s390_lr (code, s390_r0, ins->sreg1); } else { @@ -3600,7 +3581,7 @@ guint8 cond; } break; case OP_REM_IMM: { - if (s390_is_imm16 (ins->inst_imm)) { + if (s390_is_uimm16 (ins->inst_imm)) { s390_lhi (code, s390_r13, ins->inst_imm); s390_lr (code, s390_r0, ins->sreg1); } else { @@ -3631,7 +3612,7 @@ guint8 cond; } break; case OP_OR_IMM: { - if (s390_is_imm16 (ins->inst_imm)) { + if (s390_is_uimm16 (ins->inst_imm)) { s390_lhi (code, s390_r0, ins->inst_imm); if (ins->dreg != ins->sreg1) { s390_lr (code, ins->dreg, ins->sreg1); @@ -3664,7 +3645,7 @@ guint8 cond; } break; case OP_XOR_IMM: { - if (s390_is_imm16 (ins->inst_imm)) { + if (s390_is_uimm16 (ins->inst_imm)) { s390_lhi (code, s390_r0, ins->inst_imm); if (ins->dreg != ins->sreg1) { s390_lr (code, ins->dreg, ins->sreg1); @@ -3751,7 +3732,7 @@ guint8 cond; } break; case OP_MUL_IMM: { - if (s390_is_imm16 (ins->inst_imm)) { + if (s390_is_uimm16 (ins->inst_imm)) { s390_lhi (code, s390_r13, ins->inst_imm); } else { s390_basr (code, s390_r13, 0); @@ -3810,7 +3791,7 @@ guint8 cond; break; case OP_ICONST: case OP_SETREGIMM: { - if (s390_is_imm16(ins->inst_c0)) { + if (s390_is_uimm16(ins->inst_c0)) { s390_lhi (code, ins->dreg, ins->inst_c0); } else { s390_basr (code, s390_r13, 0); @@ -3870,7 +3851,7 @@ guint8 cond; case CEE_JMP: { int fParm; if (cfg->method->save_lmf) - code = restoreLMF(cfg, code); + restoreLMF(code, cfg->frame_reg, cfg->stack_usage); if (cfg->flags & MONO_CFG_HAS_TAIL) { s390_lm (code, s390_r2, s390_r5, STK_BASE, @@ -3989,7 +3970,7 @@ guint8 cond; s390_brasl (code, s390_r14, 0); } break; - case CEE_RETHROW: { + case OP_RETHROW: { s390_lr (code, s390_r2, ins->sreg1); mono_add_patch_info (cfg, code-cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD, (gpointer)"mono_arch_rethrow_exception"); @@ -4273,17 +4254,18 @@ guint8 cond; case OP_LCONV_TO_OVF_I: { /* Valid ints: 0xffffffff:8000000 to 00000000:0x7f000000 */ short int *o[5]; - s390_ltr (code, ins->sreg2, ins->sreg2); - s390_jnl (code, 0); CODEPTR(code, o[0]); s390_ltr (code, ins->sreg1, ins->sreg1); + s390_jnl (code, 0); CODEPTR(code, o[0]); + s390_ltr (code, ins->sreg2, ins->sreg2); s390_jnl (code, 0); CODEPTR(code, o[1]); s390_lhi (code, s390_r13, -1); - s390_cr (code, ins->sreg1, s390_r13); + s390_cr (code, ins->sreg2, s390_r13); s390_jnz (code, 0); CODEPTR(code, o[2]); - if (ins->dreg != ins->sreg2) - s390_lr (code, ins->dreg, ins->sreg2); + if (ins->dreg != ins->sreg1) + s390_lr (code, ins->dreg, ins->sreg1); s390_j (code, 0); CODEPTR(code, o[3]); PTRSLOT(code, o[0]); + s390_ltr (code, ins->sreg2, ins->sreg2); s390_jz (code, 0); CODEPTR(code, o[4]); PTRSLOT(code, o[1]); PTRSLOT(code, o[2]); @@ -4440,7 +4422,7 @@ guint8 cond; ins->inst_offset, ins->sreg1, ins->inst_imm); } else { s390_lr (code, s390_r0, ins->dreg); - if (s390_is_imm16 (ins->inst_offset)) { + if (s390_is_uimm16 (ins->inst_offset)) { s390_ahi (code, s390_r0, ins->inst_offset); } else { s390_basr (code, s390_r13, 0); @@ -4450,7 +4432,7 @@ guint8 cond; } s390_lr (code, s390_r14, s390_r12); s390_lr (code, s390_r12, ins->sreg1); - if (s390_is_imm16 (ins->inst_imm)) { + if (s390_is_uimm16 (ins->inst_imm)) { s390_ahi (code, s390_r12, ins->inst_imm); } else { s390_basr (code, s390_r13, 0); @@ -4734,11 +4716,12 @@ mono_arch_emit_prolog (MonoCompile *cfg) MonoBasicBlock *bb; MonoMethodSignature *sig; MonoInst *inst; - int alloc_size, pos, max_offset, i, lmfOffset; + int alloc_size, pos, max_offset, i; guint8 *code; CallInfo *cinfo; size_data sz; int tracing = 0; + int lmfOffset; \ if (mono_jit_trace_calls != NULL && mono_trace_eval (method)) tracing = 1; @@ -4763,7 +4746,7 @@ mono_arch_emit_prolog (MonoCompile *cfg) cfg->stack_usage = alloc_size; s390_lr (code, s390_r11, STK_BASE); - if (s390_is_imm16 (-alloc_size)) { + if (s390_is_uimm16 (alloc_size)) { s390_ahi (code, STK_BASE, -alloc_size); } else { int stackSize = alloc_size; @@ -4934,56 +4917,61 @@ mono_arch_emit_prolog (MonoCompile *cfg) /*---------------------------------------------------------------*/ /* we build the MonoLMF structure on the stack - see mini-s390.h */ /*---------------------------------------------------------------*/ - lmfOffset = alloc_size - sizeof(MonoLMF); - - s390_lr (code, s390_r13, cfg->frame_reg); - s390_ahi (code, s390_r13, lmfOffset); - - /*---------------------------------------------------------------*/ - /* Set lmf.lmf_addr = jit_tls->lmf */ - /*---------------------------------------------------------------*/ - s390_st (code, s390_r2, 0, s390_r13, G_STRUCT_OFFSET(MonoLMF, lmf_addr)); - - /*---------------------------------------------------------------*/ - /* Get current lmf */ - /*---------------------------------------------------------------*/ - s390_l (code, s390_r0, 0, s390_r2, 0); - - /*---------------------------------------------------------------*/ - /* Set our lmf as the current lmf */ - /*---------------------------------------------------------------*/ - s390_st (code, s390_r13, 0, s390_r2, 0); - - /*---------------------------------------------------------------*/ - /* Have our lmf.previous_lmf point to the last lmf */ - /*---------------------------------------------------------------*/ - s390_st (code, s390_r0, 0, s390_r13, G_STRUCT_OFFSET(MonoLMF, previous_lmf)); - - /*---------------------------------------------------------------*/ - /* save method info */ - /*---------------------------------------------------------------*/ - s390_basr (code, s390_r1, 0); - s390_j (code, 4); - s390_word (code, method); - s390_l (code, s390_r1, 0, s390_r1, 4); - s390_st (code, s390_r1, 0, s390_r13, G_STRUCT_OFFSET(MonoLMF, method)); - - /*---------------------------------------------------------------*/ - /* save the current IP */ - /*---------------------------------------------------------------*/ + lmfOffset = alloc_size - sizeof(MonoLMF); + + s390_lr (code, s390_r13, cfg->frame_reg); + s390_ahi (code, s390_r13, lmfOffset); + + /*---------------------------------------------------------------*/ + /* Set lmf.lmf_addr = jit_tls->lmf */ + /*---------------------------------------------------------------*/ + s390_st (code, s390_r2, 0, s390_r13, + G_STRUCT_OFFSET(MonoLMF, lmf_addr)); + + /*---------------------------------------------------------------*/ + /* Get current lmf */ + /*---------------------------------------------------------------*/ + s390_l (code, s390_r0, 0, s390_r2, 0); + + /*---------------------------------------------------------------*/ + /* Set our lmf as the current lmf */ + /*---------------------------------------------------------------*/ + s390_st (code, s390_r13, 0, s390_r2, 0); + + /*---------------------------------------------------------------*/ + /* Have our lmf.previous_lmf point to the last lmf */ + /*---------------------------------------------------------------*/ + s390_st (code, s390_r0, 0, s390_r13, + G_STRUCT_OFFSET(MonoLMF, previous_lmf)); + + /*---------------------------------------------------------------*/ + /* save method info */ + /*---------------------------------------------------------------*/ + s390_basr (code, s390_r1, 0); + s390_j (code, 4); + s390_word (code, method); + s390_l (code, s390_r1, 0, s390_r1, 4); + s390_st (code, s390_r1, 0, s390_r13, + G_STRUCT_OFFSET(MonoLMF, method)); + + /*---------------------------------------------------------------*/ + /* save the current IP */ + /*---------------------------------------------------------------*/ s390_lr (code, s390_r1, cfg->frame_reg); - s390_st (code, s390_r1, 0, s390_r13, G_STRUCT_OFFSET(MonoLMF, ebp)); - s390_l (code, s390_r1, 0, s390_r1, S390_RET_ADDR_OFFSET); - s390_la (code, s390_r1, 0, s390_r1, 0); - s390_st (code, s390_r1, 0, s390_r13, G_STRUCT_OFFSET(MonoLMF, eip)); - - /*---------------------------------------------------------------*/ - /* Save general and floating point registers */ - /*---------------------------------------------------------------*/ - s390_stm (code, s390_r2, s390_r12, s390_r13, G_STRUCT_OFFSET(MonoLMF, gregs[2])); - for (i = 0; i < 16; i++) { - s390_std (code, i, 0, s390_r13, G_STRUCT_OFFSET(MonoLMF, fregs[i])); - } + s390_st (code, s390_r1, 0, s390_r13, G_STRUCT_OFFSET(MonoLMF, ebp)); + s390_l (code, s390_r1, 0, s390_r1, S390_RET_ADDR_OFFSET); + s390_la (code, s390_r1, 0, s390_r1, 0); + s390_st (code, s390_r1, 0, s390_r13, G_STRUCT_OFFSET(MonoLMF, eip)); + + /*---------------------------------------------------------------*/ + /* Save general and floating point registers */ + /*---------------------------------------------------------------*/ + s390_stm (code, s390_r2, s390_r12, s390_r13, + G_STRUCT_OFFSET(MonoLMF, gregs[2])); + for (i = 0; i < 16; i++) { + s390_std (code, i, 0, s390_r13, + G_STRUCT_OFFSET(MonoLMF, fregs[i])); + } /*---------------------------------------------------------------*/ /* Restore the parameter registers now that we've set up the lmf */ @@ -5018,9 +5006,7 @@ mono_arch_emit_epilog (MonoCompile *cfg) { MonoJumpInfo *patch_info; MonoMethod *method = cfg->method; - MonoMethodSignature *sig = method->signature; - MonoInst *inst; - int i, tracing = 0; + int tracing = 0; guint8 *code; code = cfg->native_code + cfg->code_len; @@ -5031,7 +5017,7 @@ mono_arch_emit_epilog (MonoCompile *cfg) } if (method->save_lmf) - code = restoreLMF(cfg, code); + restoreLMF(code, cfg->frame_reg, cfg->stack_usage); if (cfg->flags & MONO_CFG_HAS_ALLOCA) s390_l (code, STK_BASE, 0, STK_BASE, 0); diff --git a/mono/mini/mini-s390.h b/mono/mini/mini-s390.h index 8a400e0299f..fc302349412 100644 --- a/mono/mini/mini-s390.h +++ b/mono/mini/mini-s390.h @@ -122,6 +122,8 @@ typedef struct MonoCompileArch { #define MONO_ARCH_EMULATE_LCONV_TO_R4 1 #define MONO_ARCH_EMULATE_LCONV_TO_R8_UN 1 #define MONO_ARCH_EMULATE_LMUL 1 +#define MONO_ARCH_HAVE_IS_INT_OVERFLOW 1 +#define MONO_ARCH_NEED_DIV_CHECK 1 #define MONO_ARCH_USE_SIGACTION 1 @@ -145,6 +147,14 @@ typedef struct MonoCompileArch { #define S390_CC_EQ 8 #define S390_ALIGN(v, a) (((a) > 0 ? (((v) + ((a) - 1)) & ~((a) - 1)) : (v))) +/*------------------------------------------------------------------*/ +/* */ +/* Name - s390_patch */ +/* */ +/* Function - Patch the code with a given value. */ +/* */ +/*------------------------------------------------------------------*/ + static void inline s390_patch (guchar *code, gint32 target) { @@ -155,4 +165,48 @@ s390_patch (guchar *code, gint32 target) } } +/*========================= End of Function ========================*/ + +/*------------------------------------------------------------------*/ +/* */ +/* Name - restoreLMF */ +/* */ +/* Function - Restore the LMF state prior to exiting a method. */ +/* */ +/*------------------------------------------------------------------*/ + +#define restoreLMF(code, frame_reg, stack_usage) do \ +{ \ + int lmfOffset = 0; \ + \ + s390_lr (code, s390_r13, frame_reg); \ + \ + lmfOffset = stack_usage - sizeof(MonoLMF); \ + \ + /*-------------------------------------------------*/ \ + /* r13 = my lmf */ \ + /*-------------------------------------------------*/ \ + s390_ahi (code, s390_r13, lmfOffset); \ + \ + /*-------------------------------------------------*/ \ + /* r6 = &jit_tls->lmf */ \ + /*-------------------------------------------------*/ \ + s390_l (code, s390_r6, 0, s390_r13, \ + G_STRUCT_OFFSET(MonoLMF, lmf_addr)); \ + \ + /*-------------------------------------------------*/ \ + /* r0 = lmf.previous_lmf */ \ + /*-------------------------------------------------*/ \ + s390_l (code, s390_r0, 0, s390_r13, \ + G_STRUCT_OFFSET(MonoLMF, previous_lmf)); \ + \ + /*-------------------------------------------------*/ \ + /* jit_tls->lmf = previous_lmf */ \ + /*-------------------------------------------------*/ \ + s390_l (code, s390_r13, 0, s390_r6, 0); \ + s390_st (code, s390_r0, 0, s390_r6, 0); \ +} while (0) + +/*========================= End of Function ========================*/ + #endif /* __MONO_MINI_S390_H__ */ diff --git a/mono/mini/mini-x86.c b/mono/mini/mini-x86.c index 8fe4bfbf341..ae3e50bd10a 100644 --- a/mono/mini/mini-x86.c +++ b/mono/mini/mini-x86.c @@ -214,7 +214,7 @@ mono_arch_cpu_optimizazions (guint32 *exclude_mask) * integer overflow. */ gboolean -mono_arch_is_int_overflow (void *sigctx) +mono_arch_is_int_overflow (void *sigctx, void *info) { struct sigcontext *ctx = (struct sigcontext*)sigctx; guint8* ip; diff --git a/mono/mini/mini.c b/mono/mini/mini.c index 364349f578b..e4893ffb73c 100644 --- a/mono/mini/mini.c +++ b/mono/mini/mini.c @@ -8189,10 +8189,13 @@ static void SIG_HANDLER_SIGNATURE (sigfpe_signal_handler) { MonoException *exc = NULL; +#ifndef MONO_ARCH_USE_SIGACTION + void *info = NULL; +#endif GET_CONTEXT; #if defined(MONO_ARCH_HAVE_IS_INT_OVERFLOW) - if (mono_arch_is_int_overflow (ctx)) + if (mono_arch_is_int_overflow (ctx, info)) exc = mono_get_exception_arithmetic (); else exc = mono_get_exception_divide_by_zero (); diff --git a/mono/mini/mini.h b/mono/mini/mini.h index 268fa55969a..8cb23a0c251 100644 --- a/mono/mini/mini.h +++ b/mono/mini/mini.h @@ -794,7 +794,7 @@ void mono_arch_flush_register_windows (void); gboolean mono_arch_is_inst_imm (gint64 imm); MonoInst* mono_arch_get_domain_intrinsic (MonoCompile* cfg); MonoInst* mono_arch_get_thread_intrinsic (MonoCompile* cfg); -gboolean mono_arch_is_int_overflow (void *sigctx); +gboolean mono_arch_is_int_overflow (void *sigctx, void *info); void mono_arch_invalidate_method (MonoJitInfo *ji, void *func, gpointer func_arg); /* Exception handling */ diff --git a/mono/mini/tramp-s390.c b/mono/mini/tramp-s390.c index 23ca8b3268a..77281803413 100644 --- a/mono/mini/tramp-s390.c +++ b/mono/mini/tramp-s390.c @@ -22,10 +22,10 @@ #define GR_SAVE_SIZE 4*sizeof(long) #define FP_SAVE_SIZE 16*sizeof(double) -#define CREATE_STACK_SIZE (S390_MINIMAL_STACK_SIZE+GR_SAVE_SIZE+FP_SAVE_SIZE+2*sizeof(long)) #define CREATE_GR_OFFSET S390_MINIMAL_STACK_SIZE #define CREATE_FP_OFFSET CREATE_GR_OFFSET+GR_SAVE_SIZE #define CREATE_LMF_OFFSET CREATE_FP_OFFSET+FP_SAVE_SIZE +#define CREATE_STACK_SIZE (CREATE_LMF_OFFSET+2*sizeof(long)+sizeof(MonoLMF)) #define METHOD_SAVE_OFFSET S390_RET_ADDR_OFFSET-4 /*------------------------------------------------------------------*/ @@ -263,7 +263,7 @@ create_trampoline_code (MonoTrampolineType tramp_type) guint8 *buf, *code = NULL; static guint8* generic_jump_trampoline = NULL; static guint8 *generic_class_init_trampoline = NULL; - int i, offset; + int i, offset, lmfOffset; switch (tramp_type) { case MONO_TRAMPOLINE_GENERIC: @@ -317,12 +317,71 @@ create_trampoline_code (MonoTrampolineType tramp_type) s390_l (buf, s390_r1, 0, s390_r13, 4); s390_basr (buf, s390_r14, s390_r1); - /* XXX Update LMF !!! */ - - /*---------------------------------------------------------- - STEP 2: call 's390_magic_trampoline()', who will compile the - code and fix the method vtable entry for us - ----------------------------------------------------------*/ + /*---------------------------------------------------------------*/ + /* we build the MonoLMF structure on the stack - see mini-s390.h */ + /* Keep in sync with the code in mono_arch_emit_prolog */ + /*---------------------------------------------------------------*/ + lmfOffset = CREATE_STACK_SIZE - sizeof(MonoLMF); + + s390_lr (buf, s390_r13, STK_BASE); + s390_ahi (buf, s390_r13, lmfOffset); + + /*---------------------------------------------------------------*/ + /* Set lmf.lmf_addr = jit_tls->lmf */ + /*---------------------------------------------------------------*/ + s390_st (buf, s390_r2, 0, s390_r13, + G_STRUCT_OFFSET(MonoLMF, lmf_addr)); + + /*---------------------------------------------------------------*/ + /* Get current lmf */ + /*---------------------------------------------------------------*/ + s390_l (buf, s390_r0, 0, s390_r2, 0); + + /*---------------------------------------------------------------*/ + /* Set our lmf as the current lmf */ + /*---------------------------------------------------------------*/ + s390_st (buf, s390_r13, 0, s390_r2, 0); + + /*---------------------------------------------------------------*/ + /* Have our lmf.previous_lmf point to the last lmf */ + /*---------------------------------------------------------------*/ + s390_st (buf, s390_r0, 0, s390_r13, + G_STRUCT_OFFSET(MonoLMF, previous_lmf)); + + /*---------------------------------------------------------------*/ + /* save method info */ + /*---------------------------------------------------------------*/ + s390_l (buf, s390_r1, 0, s390_r11, METHOD_SAVE_OFFSET); + s390_st (buf, s390_r1, 0, s390_r13, + G_STRUCT_OFFSET(MonoLMF, method)); + + /*---------------------------------------------------------------*/ + /* save the current IP */ + /*---------------------------------------------------------------*/ + s390_l (buf, s390_r1, 0, STK_BASE, 0); + s390_st (buf, s390_r1, 0, s390_r13, G_STRUCT_OFFSET(MonoLMF, ebp)); + if (tramp_type == MONO_TRAMPOLINE_JUMP) { + s390_lhi (buf, s390_r1, 0); + } else { + s390_l (buf, s390_r1, 0, s390_r1, S390_RET_ADDR_OFFSET); + s390_la (buf, s390_r1, 0, s390_r1, 0); + } + s390_st (buf, s390_r1, 0, s390_r13, G_STRUCT_OFFSET(MonoLMF, eip)); + + /*---------------------------------------------------------------*/ + /* Save general and floating point registers */ + /*---------------------------------------------------------------*/ + s390_stm (buf, s390_r2, s390_r12, s390_r13, + G_STRUCT_OFFSET(MonoLMF, gregs[2])); + for (i = 0; i < 16; i++) { + s390_std (buf, i, 0, s390_r13, + G_STRUCT_OFFSET(MonoLMF, fregs[i])); + } + + /*---------------------------------------------------------------*/ + /* STEP 2: call 's390_magic_trampoline()', who will compile the */ + /* code and fix the method vtable entry for us */ + /*---------------------------------------------------------------*/ /* Set arguments */ @@ -356,13 +415,11 @@ create_trampoline_code (MonoTrampolineType tramp_type) /* OK, code address is now on r2. Move it to r1, so that we can restore r2 and use it from r1 later */ s390_lr (buf, s390_r1, s390_r2); - /*---------------------------------------------------------- STEP 3: Restore the LMF ----------------------------------------------------------*/ - - /* XXX Do it !!! */ + restoreLMF(buf, STK_BASE, CREATE_STACK_SIZE); /*---------------------------------------------------------- STEP 4: call the compiled method -- 2.11.4.GIT