X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmini%2Fdecompose.c;h=25dd97da870ef5c821a31e1b0c15a3c3dc6aa438;hb=52a8a9b92d9e7747f7c4ab94fa9bd62151275ce3;hp=07242d86138e0ce371119ddffa80e7d85e9861fe;hpb=f0d2ee46f839cc3cebcdaa674b3a31d9a3e22863;p=mono.git diff --git a/mono/mini/decompose.c b/mono/mini/decompose.c index 07242d86138..25dd97da870 100644 --- a/mono/mini/decompose.c +++ b/mono/mini/decompose.c @@ -299,7 +299,7 @@ decompose_long_opcode (MonoCompile *cfg, MonoInst *ins, MonoInst **repl_ins) * Sets the cfg exception if an opcode is not supported. */ MonoInst* -mono_decompose_opcode (MonoCompile *cfg, MonoInst *ins) +mono_decompose_opcode (MonoCompile *cfg, MonoInst *ins, MonoBasicBlock **out_cbb) { MonoInst *repl = NULL; int type = ins->type; @@ -466,11 +466,11 @@ mono_decompose_opcode (MonoCompile *cfg, MonoInst *ins) MONO_EMIT_NEW_UNALU (cfg, OP_ICEQ, reg2, -1); MONO_EMIT_NEW_BIALU (cfg, OP_IAND, reg1, reg1, reg2); MONO_EMIT_NEW_ICOMPARE_IMM (cfg, reg1, 1); - MONO_EMIT_NEW_COND_EXC (cfg, IEQ, "DivideByZeroException"); + MONO_EMIT_NEW_COND_EXC (cfg, IEQ, "OverflowException"); } #endif MONO_EMIT_NEW_BIALU (cfg, ins->opcode, ins->dreg, ins->sreg1, ins->sreg2); - ins->opcode = OP_NOP; + NULLIFY_INS (ins); } else { emulate = TRUE; } @@ -486,6 +486,9 @@ mono_decompose_opcode (MonoCompile *cfg, MonoInst *ins) ins->opcode = OP_ICONST; MONO_INST_NULLIFY_SREGS (ins); ins->inst_c0 = 0; +#if __s390__ + } +#else } else if ((ins->inst_imm > 0) && (ins->inst_imm < (1LL << 32)) && (power != -1)) { gboolean is_long = ins->opcode == OP_LREM_IMM; int compensator_reg = alloc_ireg (cfg); @@ -497,12 +500,12 @@ mono_decompose_opcode (MonoCompile *cfg, MonoInst *ins) if (power > 1) { intermediate_reg = compensator_reg; - MONO_EMIT_NEW_BIALU_IMM (cfg, is_long ? OP_LSHR_IMM : OP_SHR_IMM, intermediate_reg, ins->sreg1, is_long ? 63 : 31); + MONO_EMIT_NEW_BIALU_IMM (cfg, is_long ? OP_LSHR_IMM : OP_ISHR_IMM, intermediate_reg, ins->sreg1, is_long ? 63 : 31); } else { intermediate_reg = ins->sreg1; } - MONO_EMIT_NEW_BIALU_IMM (cfg, is_long ? OP_LSHR_UN_IMM : OP_SHR_UN_IMM, compensator_reg, intermediate_reg, (is_long ? 64 : 32) - power); + MONO_EMIT_NEW_BIALU_IMM (cfg, is_long ? OP_LSHR_UN_IMM : OP_ISHR_UN_IMM, compensator_reg, intermediate_reg, (is_long ? 64 : 32) - power); MONO_EMIT_NEW_BIALU (cfg, is_long ? OP_LADD : OP_IADD, ins->dreg, ins->sreg1, compensator_reg); /* Compute remainder */ MONO_EMIT_NEW_BIALU_IMM (cfg, is_long ? OP_LAND_IMM : OP_AND_IMM, ins->dreg, ins->dreg, (1 << power) - 1); @@ -511,6 +514,7 @@ mono_decompose_opcode (MonoCompile *cfg, MonoInst *ins) NULLIFY_INS (ins); } +#endif break; } @@ -552,7 +556,7 @@ mono_decompose_opcode (MonoCompile *cfg, MonoInst *ins) } } - call = mono_emit_native_call (cfg, mono_icall_get_wrapper (info), info->sig, args); + call = mono_emit_jit_icall_by_info (cfg, info, args, out_cbb); call->dreg = ins->dreg; NULLIFY_INS (ins); @@ -625,14 +629,13 @@ mono_decompose_long_opts (MonoCompile *cfg) first_bb = cfg->cbb; for (bb = cfg->bb_entry; bb; bb = bb->next_bb) { - MonoInst *tree = bb->code; + MonoInst *tree = mono_bb_first_inst(bb, FILTER_IL_SEQ_POINT); MonoInst *prev = NULL; /* mono_print_bb (bb, "BEFORE LOWER_LONG_OPTS"); */ - tree = bb->code; cfg->cbb->code = cfg->cbb->last_ins = NULL; while (tree) { @@ -963,7 +966,7 @@ mono_decompose_long_opts (MonoCompile *cfg) break; case OP_LCOMPARE: { - MonoInst *next = tree->next; + MonoInst *next = mono_inst_next (tree, FILTER_IL_SEQ_POINT); g_assert (next); @@ -980,7 +983,7 @@ mono_decompose_long_opts (MonoCompile *cfg) MONO_EMIT_NEW_BIALU (cfg, OP_IOR, d1, d1, d2); MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ICOMPARE_IMM, -1, d1, 0); MONO_EMIT_NEW_BRANCH_BLOCK2 (cfg, next->opcode == OP_LBEQ ? OP_IBEQ : OP_IBNE_UN, next->inst_true_bb, next->inst_false_bb); - next->opcode = OP_NOP; + NULLIFY_INS (next); break; } case OP_LBGE: @@ -998,7 +1001,7 @@ mono_decompose_long_opts (MonoCompile *cfg) MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBNE_UN, next->inst_false_bb); MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, tree->sreg1 + 1, tree->sreg2 + 1); MONO_EMIT_NEW_BRANCH_BLOCK2 (cfg, lbr_decomp [next->opcode - OP_LBEQ][1], next->inst_true_bb, next->inst_false_bb); - next->opcode = OP_NOP; + NULLIFY_INS (next); break; case OP_LCEQ: { int d1, d2; @@ -1012,7 +1015,7 @@ mono_decompose_long_opts (MonoCompile *cfg) MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ICOMPARE_IMM, -1, d1, 0); MONO_EMIT_NEW_UNALU (cfg, OP_ICEQ, next->dreg, -1); - next->opcode = OP_NOP; + NULLIFY_INS (next); break; } case OP_LCLT: @@ -1034,7 +1037,7 @@ mono_decompose_long_opts (MonoCompile *cfg) MONO_START_BB (cfg, set_to_1); MONO_EMIT_NEW_ICONST (cfg, next->dreg, 1); MONO_START_BB (cfg, set_to_0); - next->opcode = OP_NOP; + NULLIFY_INS (next); break; } default: @@ -1045,7 +1048,7 @@ mono_decompose_long_opts (MonoCompile *cfg) /* Not yet used, since lcompare is decomposed before local cprop */ case OP_LCOMPARE_IMM: { - MonoInst *next = tree->next; + MonoInst *next = mono_inst_next (tree, FILTER_IL_SEQ_POINT); guint32 low_imm = tree->inst_ls_word; guint32 high_imm = tree->inst_ms_word; int low_reg = tree->sreg1 + 1; @@ -1066,7 +1069,7 @@ mono_decompose_long_opts (MonoCompile *cfg) MONO_EMIT_NEW_BIALU (cfg, OP_IOR, d1, d1, d2); MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ICOMPARE_IMM, -1, d1, 0); MONO_EMIT_NEW_BRANCH_BLOCK2 (cfg, next->opcode == OP_LBEQ ? OP_IBEQ : OP_IBNE_UN, next->inst_true_bb, next->inst_false_bb); - next->opcode = OP_NOP; + NULLIFY_INS (next); break; } @@ -1085,7 +1088,7 @@ mono_decompose_long_opts (MonoCompile *cfg) MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBNE_UN, next->inst_false_bb); MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, low_reg, low_imm); MONO_EMIT_NEW_BRANCH_BLOCK2 (cfg, lbr_decomp [next->opcode - OP_LBEQ][1], next->inst_true_bb, next->inst_false_bb); - next->opcode = OP_NOP; + NULLIFY_INS (next); break; case OP_LCEQ: { int d1, d2; @@ -1099,7 +1102,7 @@ mono_decompose_long_opts (MonoCompile *cfg) MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ICOMPARE_IMM, -1, d1, 0); MONO_EMIT_NEW_UNALU (cfg, OP_ICEQ, next->dreg, -1); - next->opcode = OP_NOP; + NULLIFY_INS (next); break; } case OP_LCLT: @@ -1121,7 +1124,7 @@ mono_decompose_long_opts (MonoCompile *cfg) MONO_START_BB (cfg, set_to_1); MONO_EMIT_NEW_ICONST (cfg, next->dreg, 1); MONO_START_BB (cfg, set_to_0); - next->opcode = OP_NOP; + NULLIFY_INS (next); break; } default: @@ -1145,9 +1148,9 @@ mono_decompose_long_opts (MonoCompile *cfg) /* Process the newly added ops again since they can be long ops too */ if (prev) - tree = prev->next; + tree = mono_inst_next (prev, FILTER_IL_SEQ_POINT); else - tree = bb->code; + tree = mono_bb_first_inst (bb, FILTER_IL_SEQ_POINT); first_bb->code = first_bb->last_ins = NULL; first_bb->in_count = first_bb->out_count = 0; @@ -1155,7 +1158,7 @@ mono_decompose_long_opts (MonoCompile *cfg) } else { prev = tree; - tree = tree->next; + tree = mono_inst_next (tree, FILTER_IL_SEQ_POINT); } } } @@ -1330,18 +1333,18 @@ mono_decompose_vtype_opts (MonoCompile *cfg) if (call->vret_in_reg) { MonoCallInst *call2; - /* Replace the vcall with an integer call */ + /* Replace the vcall with a scalar call */ MONO_INST_NEW_CALL (cfg, call2, OP_NOP); memcpy (call2, call, sizeof (MonoCallInst)); switch (ins->opcode) { case OP_VCALL: - call2->inst.opcode = OP_CALL; + call2->inst.opcode = call->vret_in_reg_fp ? OP_FCALL : OP_CALL; break; case OP_VCALL_REG: - call2->inst.opcode = OP_CALL_REG; + call2->inst.opcode = call->vret_in_reg_fp ? OP_FCALL_REG : OP_CALL_REG; break; case OP_VCALL_MEMBASE: - call2->inst.opcode = OP_CALL_MEMBASE; + call2->inst.opcode = call->vret_in_reg_fp ? OP_FCALL_MEMBASE : OP_CALL_MEMBASE; break; } call2->inst.dreg = alloc_preg (cfg); @@ -1367,12 +1370,19 @@ mono_decompose_vtype_opts (MonoCompile *cfg) break; case 3: case 4: - MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, dest->dreg, 0, call2->inst.dreg); + if (call->vret_in_reg_fp) + MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER4_MEMBASE_REG, dest->dreg, 0, call2->inst.dreg); + else + MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, dest->dreg, 0, call2->inst.dreg); break; case 5: case 6: case 7: case 8: + if (call->vret_in_reg_fp) { + MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER8_MEMBASE_REG, dest->dreg, 0, call2->inst.dreg); + break; + } #if SIZEOF_REGISTER == 4 /* FIXME Other ABIs might return in different regs than the ones used for LCALL.