return OP_LSUB;
case OP_IMUL_IMM:
return OP_IMUL;
+ case OP_LMUL_IMM:
+ return OP_LMUL;
case OP_AND_IMM:
#if SIZEOF_REGISTER == 4
return OP_IAND;
return OP_LSHR_UN;
case OP_IDIV_IMM:
return OP_IDIV;
+ case OP_LDIV_IMM:
+ return OP_LDIV;
case OP_IDIV_UN_IMM:
return OP_IDIV_UN;
+ case OP_LDIV_UN_IMM:
+ return OP_LDIV_UN;
case OP_IREM_UN_IMM:
return OP_IREM_UN;
+ case OP_LREM_UN_IMM:
+ return OP_LREM_UN;
case OP_IREM_IMM:
return OP_IREM;
case OP_LREM_IMM:
return OP_ICOMPARE;
case OP_LOCALLOC_IMM:
return OP_LOCALLOC;
- default:
- printf ("%s\n", mono_inst_name (opcode));
- g_assert_not_reached ();
- return -1;
}
+
+ return -1;
}
/*
void
mono_decompose_op_imm (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst *ins)
{
+ int opcode2 = mono_op_imm_to_op (ins->opcode);
MonoInst *temp;
+ guint32 dreg;
+ const char *spec = INS_INFO (ins->opcode);
+
+ if (spec [MONO_INST_SRC2] == 'l') {
+ dreg = mono_alloc_lreg (cfg);
+
+ /* Load the 64bit constant using decomposed ops */
+ MONO_INST_NEW (cfg, temp, OP_ICONST);
+ temp->inst_c0 = ins->inst_ls_word;
+ temp->dreg = MONO_LVREG_LS (dreg);
+ mono_bblock_insert_before_ins (bb, ins, temp);
+
+ MONO_INST_NEW (cfg, temp, OP_ICONST);
+ temp->inst_c0 = ins->inst_ms_word;
+ temp->dreg = MONO_LVREG_MS (dreg);
+ } else {
+ dreg = mono_alloc_ireg (cfg);
+
+ MONO_INST_NEW (cfg, temp, OP_ICONST);
+ temp->inst_c0 = ins->inst_imm;
+ temp->dreg = dreg;
+ }
- MONO_INST_NEW (cfg, temp, OP_ICONST);
- temp->inst_c0 = ins->inst_imm;
- temp->dreg = mono_alloc_ireg (cfg);
mono_bblock_insert_before_ins (bb, ins, temp);
- ins->opcode = mono_op_imm_to_op (ins->opcode);
+
+ if (opcode2 == -1)
+ g_error ("mono_op_imm_to_op failed for %s\n", mono_inst_name (ins->opcode));
+ ins->opcode = opcode2;
+
if (ins->opcode == OP_LOCALLOC)
- ins->sreg1 = temp->dreg;
+ ins->sreg1 = dreg;
else
- ins->sreg2 = temp->dreg;
+ ins->sreg2 = dreg;
bb->max_vreg = MAX (bb->max_vreg, cfg->next_vreg);
}
*/
if (cfg->verbose_level >= 4) {
- printf (" Create LVAR R%d (R%d, R%d)\n", inst->dreg, inst->dreg + 1, inst->dreg + 2);
+ printf (" Create LVAR R%d (R%d, R%d)\n", inst->dreg, MONO_LVREG_LS (inst->dreg), MONO_LVREG_MS (inst->dreg));
}
if (mono_arch_is_soft_float () && cfg->opt & MONO_OPT_SSA) {
/* Allocate a dummy MonoInst for the first vreg */
MONO_INST_NEW (cfg, tree, OP_LOCAL);
- tree->dreg = inst->dreg + 1;
+ tree->dreg = MONO_LVREG_LS (inst->dreg);
if (cfg->opt & MONO_OPT_SSA)
tree->flags = MONO_INST_VOLATILE;
tree->inst_c0 = num;
tree->inst_vtype = &mono_defaults.int32_class->byval_arg;
tree->klass = mono_class_from_mono_type (tree->inst_vtype);
- set_vreg_to_inst (cfg, inst->dreg + 1, tree);
+ set_vreg_to_inst (cfg, MONO_LVREG_LS (inst->dreg), tree);
/* Allocate a dummy MonoInst for the second vreg */
MONO_INST_NEW (cfg, tree, OP_LOCAL);
- tree->dreg = inst->dreg + 2;
+ tree->dreg = MONO_LVREG_MS (inst->dreg);
if (cfg->opt & MONO_OPT_SSA)
tree->flags = MONO_INST_VOLATILE;
tree->inst_c0 = num;
tree->inst_vtype = &mono_defaults.int32_class->byval_arg;
tree->klass = mono_class_from_mono_type (tree->inst_vtype);
- set_vreg_to_inst (cfg, inst->dreg + 2, tree);
+ set_vreg_to_inst (cfg, MONO_LVREG_MS (inst->dreg), tree);
}
cfg->num_varinfo++;
if (cfg->verbose_level > 2)
g_print ("locals done\n");
+#ifdef ENABLE_LLVM
if (COMPILE_LLVM (cfg))
mono_llvm_create_vars (cfg);
else
mono_arch_create_vars (cfg);
+#else
+ mono_arch_create_vars (cfg);
+#endif
if (cfg->method->save_lmf && cfg->create_lmf_var) {
MonoInst *lmf_var = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL);
if (cfg->verbose_level > 0) {
char* nm = mono_method_full_name (cfg->method, TRUE);
- g_print ("Method %s emitted at %p to %p (code length %d) [%s]\n",
+ char *opt_descr = mono_opt_descr (cfg->opt);
+ g_print ("Method %s emitted at %p to %p (code length %d) [%s] with opts %s\n",
nm,
- cfg->native_code, cfg->native_code + cfg->code_len, cfg->code_len, cfg->domain->friendly_name);
+ cfg->native_code, cfg->native_code + cfg->code_len, cfg->code_len, cfg->domain->friendly_name,
+ opt_descr);
g_free (nm);
+ g_free (opt_descr);
}
{
cfg->extend_live_ranges = TRUE;
- /* Temporarily disable this when running in the debugger until we have support
- * for this in the debugger. */
- /* This is no longer needed with sdb */
- //cfg->disable_omit_fp = TRUE;
-
/* The debugger needs all locals to be on the stack or in a global register */
cfg->disable_vreg_to_lvreg = TRUE;
* may still want to view them. */
cfg->disable_deadce_vars = TRUE;
- // cfg->opt |= MONO_OPT_SHARED;
cfg->opt &= ~MONO_OPT_DEADCE;
cfg->opt &= ~MONO_OPT_INLINE;
cfg->opt &= ~MONO_OPT_COPYPROP;
cfg->opt &= ~MONO_OPT_CONSPROP;
- /* This is no longer needed with sdb */
- //cfg->opt &= ~MONO_OPT_GSHARED;
/* This is needed for the soft debugger, which doesn't like code after the epilog */
cfg->disable_out_of_line_bblocks = TRUE;
/* Should be done before branch opts */
if (cfg->opt & (MONO_OPT_CONSPROP | MONO_OPT_COPYPROP))
mono_local_cprop (cfg);
-
+ /*
+ * Should be done after cprop which can do strength reduction on
+ * some of these ops, after propagating immediates.
+ */
+ if (cfg->has_emulated_ops)
+ mono_local_emulate_ops (cfg);
if (cfg->opt & MONO_OPT_BRANCH)
mono_optimize_branches (cfg);