#include <string.h>
#include <math.h>
+#ifdef HAVE_UNISTD_H
#include <unistd.h>
+#endif
#include <mono/metadata/appdomain.h>
#include <mono/metadata/debug-helpers.h>
#define DEBUG(a) MINI_DEBUG(cfg->verbose_level, 2, a;)
-#if defined(__x86_64__)
-const char * const amd64_desc [OP_LAST];
-static const char*const * ins_spec = amd64_desc;
-#elif defined(__sparc__) || defined(sparc)
-const char * const sparc_desc [OP_LAST];
-static const char*const * ins_spec = sparc_desc;
-#elif defined(__i386__)
-extern const char * const pentium_desc [OP_LAST];
-static const char*const * ins_spec = pentium_desc;
-#elif defined(__ia64__)
-const char * const ia64_desc [OP_LAST];
-static const char*const * ins_spec = ia64_desc;
-#elif defined(__arm__)
-const char * const arm_cpu_desc [OP_LAST];
-static const char*const * ins_spec = arm_cpu_desc;
-#elif defined(__s390x__)
-const char * const s390x_cpu_desc [OP_LAST];
-static const char*const * ins_spec = s390x_cpu_desc;
-#elif defined(__s390__)
-const char * const s390_cpu_desc [OP_LAST];
-static const char*const * ins_spec = s390_cpu_desc;
-#else
-#error "Not implemented"
-#endif
-
#define use_fpstack MONO_ARCH_USE_FPSTACK
static inline GSList*
g_slist_append_mempool (MonoMemPool *mp, GSList *list, gpointer data)
{
- GSList *new_list;
- GSList *last;
-
- new_list = mono_mempool_alloc (mp, sizeof (GSList));
- new_list->data = data;
- new_list->next = NULL;
-
- if (list) {
- last = list;
- while (last->next)
- last = last->next;
- last->next = new_list;
-
- return list;
- }
- else
- return new_list;
+ GSList *new_list;
+ GSList *last;
+
+ new_list = mono_mempool_alloc (mp, sizeof (GSList));
+ new_list->data = data;
+ new_list->next = NULL;
+
+ if (list) {
+ last = list;
+ while (last->next)
+ last = last->next;
+ last->next = new_list;
+
+ return list;
+ } else
+ return new_list;
}
/**
static inline void
mono_regstate2_reset (MonoRegState *rs) {
- rs->next_vireg = MONO_MAX_IREGS;
- rs->next_vfreg = MONO_MAX_FREGS;
+ rs->next_vreg = MONO_MAX_IREGS;
}
static inline MonoRegState*
static inline void
mono_regstate2_free (MonoRegState *rs) {
- g_free (rs->iassign);
- if (rs->iassign != rs->fassign)
- g_free (rs->fassign);
+ g_free (rs->vassign);
g_free (rs);
}
static inline void
-mono_regstate2_assign (MonoRegState *rs) {
- rs->max_ireg = -1;
-
- if (rs->next_vireg > rs->iassign_size) {
- g_free (rs->iassign);
- rs->iassign_size = MAX (rs->next_vireg, 256);
- rs->iassign = g_malloc (rs->iassign_size * sizeof (int));
+mono_regstate_assign (MonoRegState *rs) {
+ if (rs->next_vreg > rs->vassign_size) {
+ g_free (rs->vassign);
+ rs->vassign_size = MAX (rs->next_vreg, 256);
+ rs->vassign = g_malloc (rs->vassign_size * sizeof (int));
}
memset (rs->isymbolic, 0, MONO_MAX_IREGS * sizeof (rs->isymbolic [0]));
- memset (rs->iassign, -1, sizeof (rs->iassign [0]) * rs->next_vireg);
-
- if (rs->next_vfreg > rs->fassign_size) {
- g_free (rs->fassign);
- rs->fassign = g_malloc (MAX (MONO_MAX_FREGS, rs->next_vfreg) * sizeof (int));
- rs->fassign_size = rs->next_vfreg;
- }
+ memset (rs->vassign, -1, sizeof (rs->vassign [0]) * rs->next_vreg);
- if (rs->next_vfreg > MONO_MAX_FREGS) {
- memset (rs->fsymbolic, 0, MONO_MAX_IREGS * sizeof (rs->fsymbolic [0]));
- memset (rs->fassign, -1, sizeof (rs->fassign [0]) * rs->next_vfreg);
- }
+ memset (rs->fsymbolic, 0, MONO_MAX_FREGS * sizeof (rs->fsymbolic [0]));
}
static inline int
-mono_regstate2_alloc_int (MonoRegState *rs, regmask_t allow)
+mono_regstate_alloc_int (MonoRegState *rs, regmask_t allow)
{
- int i;
regmask_t mask = allow & rs->ifree_mask;
+
+#if defined(__x86_64__) && defined(__GNUC__)
+ {
+ guint64 i;
+
+ if (mask == 0)
+ return -1;
+
+ __asm__("bsfq %1,%0\n\t"
+ : "=r" (i) : "rm" (mask));
+
+ rs->ifree_mask &= ~ ((regmask_t)1 << i);
+ return i;
+ }
+#else
+ int i;
+
for (i = 0; i < MONO_MAX_IREGS; ++i) {
if (mask & ((regmask_t)1 << i)) {
rs->ifree_mask &= ~ ((regmask_t)1 << i);
- rs->max_ireg = MAX (rs->max_ireg, i);
return i;
}
}
return -1;
+#endif
}
static inline void
-mono_regstate2_free_int (MonoRegState *rs, int reg)
+mono_regstate_free_int (MonoRegState *rs, int reg)
{
if (reg >= 0) {
rs->ifree_mask |= (regmask_t)1 << reg;
}
static inline int
-mono_regstate2_alloc_float (MonoRegState *rs, regmask_t allow)
+mono_regstate_alloc_float (MonoRegState *rs, regmask_t allow)
{
int i;
regmask_t mask = allow & rs->ffree_mask;
}
static inline void
-mono_regstate2_free_float (MonoRegState *rs, int reg)
+mono_regstate_free_float (MonoRegState *rs, int reg)
{
if (reg >= 0) {
rs->ffree_mask |= (regmask_t)1 << reg;
static inline int
mono_regstate2_next_long (MonoRegState *rs)
{
- int rval = rs->next_vireg;
+ int rval = rs->next_vreg;
- rs->next_vireg += 2;
+ rs->next_vreg += 2;
return rval;
}
regpair = (((guint32)hreg) << 24) + vreg;
if (fp) {
+ g_assert (vreg >= MONO_MAX_FREGS);
+ g_assert (hreg < MONO_MAX_FREGS);
call->used_fregs |= 1 << hreg;
call->out_freg_args = g_slist_append_mempool (cfg->mempool, call->out_freg_args, (gpointer)(gssize)(regpair));
} else {
+ g_assert (vreg >= MONO_MAX_IREGS);
+ g_assert (hreg < MONO_MAX_IREGS);
call->used_iregs |= 1 << hreg;
call->out_ireg_args = g_slist_append_mempool (cfg->mempool, call->out_ireg_args, (gpointer)(gssize)(regpair));
}
* spill variable if necessary.
*/
static inline int
-mono_spillvar_offset (MonoCompile *cfg, int spillvar)
+mono_spillvar_offset_int (MonoCompile *cfg, int spillvar)
{
MonoSpillInfo *info;
+#if defined (__mips__)
+ g_assert_not_reached();
+#endif
if (G_UNLIKELY (spillvar >= cfg->spill_info_len)) {
resize_spill_info (cfg, FALSE);
g_assert (spillvar < cfg->spill_info_len);
info = &cfg->spill_info [spillvar];
if (info->offset == -1) {
+ cfg->stack_offset += sizeof (gpointer) - 1;
+ cfg->stack_offset &= ~(sizeof (gpointer) - 1);
+
if (cfg->flags & MONO_CFG_HAS_SPILLUP) {
info->offset = cfg->stack_offset;
cfg->stack_offset += sizeof (gpointer);
return info->offset;
}
-#if MONO_ARCH_USE_FPSTACK
-
/*
* returns the offset used by spillvar. It allocates a new
* spill float variable if necessary.
{
MonoSpillInfo *info;
+#if defined (__mips__)
+ g_assert_not_reached();
+#endif
if (G_UNLIKELY (spillvar >= cfg->spill_info_float_len)) {
resize_spill_info (cfg, TRUE);
g_assert (spillvar < cfg->spill_info_float_len);
info = &cfg->spill_info_float [spillvar];
if (info->offset == -1) {
+ cfg->stack_offset += sizeof (double) - 1;
+ cfg->stack_offset &= ~(sizeof (double) - 1);
+
if (cfg->flags & MONO_CFG_HAS_SPILLUP) {
- cfg->stack_offset += 7;
- cfg->stack_offset &= ~7;
info->offset = cfg->stack_offset;
cfg->stack_offset += sizeof (double);
} else {
- /* FIXME: align */
cfg->stack_offset += sizeof (double);
info->offset = - cfg->stack_offset;
}
return info->offset;
}
+static inline int
+mono_spillvar_offset (MonoCompile *cfg, int spillvar, gboolean fp)
+{
+ if (fp)
+ return mono_spillvar_offset_float (cfg, spillvar);
+ else
+ return mono_spillvar_offset_int (cfg, spillvar);
+}
+
+#if MONO_ARCH_USE_FPSTACK
+
/*
* Creates a store for spilled floating point items
*/
#define reg_is_freeable(r,fp) ((fp) ? freg_is_freeable ((r)) : ireg_is_freeable ((r)))
#define is_hard_reg(r,fp) ((fp) ? ((r) < MONO_MAX_FREGS) : ((r) < MONO_MAX_IREGS))
#define is_soft_reg(r,fp) (!is_hard_reg((r),(fp)))
-#define rassign(cfg,reg,fp) ((fp) ? (cfg)->rs->fassign [(reg)] : (cfg)->rs->iassign [(reg)])
-
-#define sreg1_is_fp(spec) (spec [MONO_INST_SRC1] == 'f')
-#define sreg2_is_fp(spec) (spec [MONO_INST_SRC2] == 'f')
+#define rassign(cfg,reg,fp) ((cfg)->rs->vassign [(reg)])
#ifdef MONO_ARCH_INST_IS_FLOAT
#define dreg_is_fp(spec) (MONO_ARCH_INST_IS_FLOAT (spec [MONO_INST_DEST]))
+#define sreg1_is_fp(spec) (MONO_ARCH_INST_IS_FLOAT (spec [MONO_INST_SRC1]))
+#define sreg2_is_fp(spec) (MONO_ARCH_INST_IS_FLOAT (spec [MONO_INST_SRC2]))
#else
+#define sreg1_is_fp(spec) (spec [MONO_INST_SRC1] == 'f')
+#define sreg2_is_fp(spec) (spec [MONO_INST_SRC2] == 'f')
#define dreg_is_fp(spec) (spec [MONO_INST_DEST] == 'f')
#endif
-#define sreg1_is_fp_ins(ins) (sreg1_is_fp (ins_spec [(ins)->opcode]))
-#define sreg2_is_fp_ins(ins) (sreg2_is_fp (ins_spec [(ins)->opcode]))
-#define dreg_is_fp_ins(ins) (dreg_is_fp (ins_spec [(ins)->opcode]))
+#define sreg1_is_fp_ins(ins) (sreg1_is_fp (ins_get_spec ((ins)->opcode)))
+#define sreg2_is_fp_ins(ins) (sreg2_is_fp (ins_get_spec ((ins)->opcode)))
+#define dreg_is_fp_ins(ins) (dreg_is_fp (ins_get_spec ((ins)->opcode)))
#define regpair_reg2_mask(desc,hreg1) ((MONO_ARCH_INST_REGPAIR_REG2 (desc,hreg1) != -1) ? (regmask (MONO_ARCH_INST_REGPAIR_REG2 (desc,hreg1))) : MONO_ARCH_CALLEE_REGS)
} RegTrack;
#ifndef DISABLE_LOGGING
-static void
-print_ins (int i, MonoInst *ins)
+void
+mono_print_ins (int i, MonoInst *ins)
{
- const char *spec = ins_spec [ins->opcode];
+ const char *spec = ins_get_spec (ins->opcode);
printf ("\t%-2d %s", i, mono_inst_name (ins->opcode));
if (!spec)
g_error ("Unknown opcode: %s\n", mono_inst_name (ins->opcode));
static inline InstList*
inst_list_prepend (guint8 *mem, InstList *list, MonoInst *data)
{
- InstList *item = (InstList*)mem;
+ InstList *item = (InstList*)(gpointer)mem;
item->data = data;
item->prev = NULL;
item->next = list;
int i, sel, spill;
int *assign, *symbolic;
- if (fp) {
- assign = cfg->rs->fassign;
+ assign = cfg->rs->vassign;
+ if (fp)
symbolic = cfg->rs->fsymbolic;
- }
- else {
- assign = cfg->rs->iassign;
+ else
symbolic = cfg->rs->isymbolic;
- }
- sel = assign [reg];
+ sel = cfg->rs->vassign [reg];
/*i = cfg->rs->isymbolic [sel];
g_assert (i == reg);*/
i = reg;
spill = ++cfg->spill_count;
assign [i] = -spill - 1;
if (fp)
- mono_regstate2_free_float (cfg->rs, sel);
+ mono_regstate_free_float (cfg->rs, sel);
else
- mono_regstate2_free_int (cfg->rs, sel);
+ mono_regstate_free_int (cfg->rs, sel);
/* we need to create a spill var and insert a load to sel after the current instruction */
if (fp)
MONO_INST_NEW (cfg, load, OP_LOADR8_MEMBASE);
MONO_INST_NEW (cfg, load, OP_LOAD_MEMBASE);
load->dreg = sel;
load->inst_basereg = cfg->frame_reg;
- load->inst_offset = mono_spillvar_offset (cfg, spill);
+ load->inst_offset = mono_spillvar_offset (cfg, spill, fp);
insert_after_ins (ins, item, load);
DEBUG (printf ("SPILLED LOAD (%d at 0x%08lx(%%ebp)) R%d (freed %s)\n", spill, (long)load->inst_offset, i, mono_regname_full (sel, fp)));
if (fp)
- i = mono_regstate2_alloc_float (cfg->rs, regmask (sel));
+ i = mono_regstate_alloc_float (cfg->rs, regmask (sel));
else
- i = mono_regstate2_alloc_int (cfg->rs, regmask (sel));
+ i = mono_regstate_alloc_int (cfg->rs, regmask (sel));
g_assert (i == sel);
return sel;
int i, sel, spill;
int *assign, *symbolic;
- if (fp) {
- assign = cfg->rs->fassign;
+ assign = cfg->rs->vassign;
+ if (fp)
symbolic = cfg->rs->fsymbolic;
- }
- else {
- assign = cfg->rs->iassign;
+ else
symbolic = cfg->rs->isymbolic;
- }
DEBUG (printf ("\tstart regmask to assign R%d: 0x%08" G_GUINT64_FORMAT " (R%d <- R%d R%d)\n", reg, (guint64)regmask, ins->dreg, ins->sreg1, ins->sreg2));
/* exclude the registers in the current instruction */
i = cfg->rs->fsymbolic [sel];
spill = ++cfg->spill_count;
- cfg->rs->fassign [i] = -spill - 1;
- mono_regstate2_free_float (cfg->rs, sel);
+ cfg->rs->vassign [i] = -spill - 1;
+ mono_regstate_free_float (cfg->rs, sel);
}
else {
for (i = 0; i < MONO_MAX_IREGS; ++i) {
i = cfg->rs->isymbolic [sel];
spill = ++cfg->spill_count;
- cfg->rs->iassign [i] = -spill - 1;
- mono_regstate2_free_int (cfg->rs, sel);
+ cfg->rs->vassign [i] = -spill - 1;
+ mono_regstate_free_int (cfg->rs, sel);
}
/* we need to create a spill var and insert a load to sel after the current instruction */
MONO_INST_NEW (cfg, load, fp ? OP_LOADR8_MEMBASE : OP_LOAD_MEMBASE);
load->dreg = sel;
load->inst_basereg = cfg->frame_reg;
- load->inst_offset = mono_spillvar_offset (cfg, spill);
+ load->inst_offset = mono_spillvar_offset (cfg, spill, fp);
insert_after_ins (ins, item, load);
DEBUG (printf ("\tSPILLED LOAD (%d at 0x%08lx(%%ebp)) R%d (freed %s)\n", spill, (long)load->inst_offset, i, mono_regname_full (sel, fp)));
if (fp)
- i = mono_regstate2_alloc_float (cfg->rs, regmask (sel));
+ i = mono_regstate_alloc_float (cfg->rs, regmask (sel));
else
- i = mono_regstate2_alloc_int (cfg->rs, regmask (sel));
+ i = mono_regstate_alloc_int (cfg->rs, regmask (sel));
g_assert (i == sel);
return sel;
if (!(cfg->rs->ifree_mask & (regmask (hreg)))) {
DEBUG (printf ("\tforced spill of R%d\n", cfg->rs->isymbolic [hreg]));
get_register_force_spilling (cfg, item, ins, cfg->rs->isymbolic [hreg], FALSE);
- mono_regstate2_free_int (cfg->rs, hreg);
+ mono_regstate_free_int (cfg->rs, hreg);
}
}
if (!(cfg->rs->ffree_mask & (regmask (hreg)))) {
DEBUG (printf ("\tforced spill of R%d\n", cfg->rs->isymbolic [hreg]));
get_register_force_spilling (cfg, item, ins, cfg->rs->isymbolic [hreg], fp);
- mono_regstate2_free_float (cfg->rs, hreg);
+ mono_regstate_free_float (cfg->rs, hreg);
}
}
else {
if (!(cfg->rs->ifree_mask & (regmask (hreg)))) {
DEBUG (printf ("\tforced spill of R%d\n", cfg->rs->isymbolic [hreg]));
get_register_force_spilling (cfg, item, ins, cfg->rs->isymbolic [hreg], fp);
- mono_regstate2_free_int (cfg->rs, hreg);
+ mono_regstate_free_int (cfg->rs, hreg);
}
}
}
MONO_INST_NEW (cfg, store, fp ? OP_STORER8_MEMBASE_REG : OP_STORE_MEMBASE_REG);
store->sreg1 = reg;
store->inst_destbasereg = cfg->frame_reg;
- store->inst_offset = mono_spillvar_offset (cfg, spill);
+ store->inst_offset = mono_spillvar_offset (cfg, spill, fp);
if (ins) {
store->next = ins->next;
ins->next = store;
int val;
if (info && info->preferred_mask) {
- val = mono_regstate2_alloc_int (cfg->rs, info->preferred_mask & dest_mask);
+ val = mono_regstate_alloc_int (cfg->rs, info->preferred_mask & dest_mask);
if (val >= 0) {
DEBUG (printf ("\tallocated preferred reg R%d to %s\n", sym_reg, mono_arch_regname (val)));
return val;
}
}
- val = mono_regstate2_alloc_int (cfg->rs, dest_mask);
+ val = mono_regstate_alloc_int (cfg->rs, dest_mask);
if (val < 0)
val = get_register_spilling (cfg, tmp, ins, dest_mask, sym_reg, FALSE);
{
int val;
- val = mono_regstate2_alloc_float (cfg->rs, dest_mask);
+ val = mono_regstate_alloc_float (cfg->rs, dest_mask);
if (val < 0) {
val = get_register_spilling (cfg, tmp, ins, dest_mask, sym_reg, TRUE);
g_assert (hreg < MONO_MAX_FREGS);
g_assert (! is_global_freg (hreg));
- rs->fassign [reg] = hreg;
+ rs->vassign [reg] = hreg;
rs->fsymbolic [hreg] = reg;
rs->ffree_mask &= ~ (regmask (hreg));
}
else {
g_assert (reg >= MONO_MAX_IREGS);
g_assert (hreg < MONO_MAX_IREGS);
+#ifndef __arm__
+ /* this seems to trigger a gcc compilation bug sometime (hreg is 0) */
g_assert (! is_global_ireg (hreg));
+#endif
- rs->iassign [reg] = hreg;
+ rs->vassign [reg] = hreg;
rs->isymbolic [hreg] = reg;
rs->ifree_mask &= ~ (regmask (hreg));
}
MonoInst *ins;
MonoRegState *rs = cfg->rs;
int i, val, fpcount, ins_count;
- RegTrack *reginfo, *reginfof;
- RegTrack *reginfo1, *reginfo2, *reginfod;
+ RegTrack *reginfo;
InstList *tmp, *reversed = NULL;
const char *spec;
GList *fspill_list = NULL;
int fspill = 0;
guint8 *inst_list, *mem;
#if MONO_ARCH_USE_FPSTACK
- gboolean need_fpstack = (use_fpstack && bb->max_freg > MONO_MAX_FREGS);
+ gboolean need_fpstack = use_fpstack;
#endif
if (!bb->code)
return;
- rs->next_vireg = bb->max_ireg;
- rs->next_vfreg = bb->max_freg;
- mono_regstate2_assign (rs);
+ rs->next_vreg = bb->max_vreg;
+ mono_regstate_assign (rs);
rs->ifree_mask = MONO_ARCH_CALLEE_REGS;
rs->ffree_mask = MONO_ARCH_CALLEE_FREGS;
/*if (cfg->opt & MONO_OPT_COPYPROP)
local_copy_prop (cfg, ins);*/
- if (cfg->reginfo && cfg->reginfo_len < rs->next_vireg) {
+ if (cfg->reginfo && cfg->reginfo_len < rs->next_vreg) {
cfg->reginfo = NULL;
}
reginfo = cfg->reginfo;
if (!reginfo) {
- cfg->reginfo_len = MAX (256, rs->next_vireg * 2);
+ cfg->reginfo_len = MAX (256, rs->next_vreg * 2);
reginfo = cfg->reginfo = mono_mempool_alloc (cfg->mempool, sizeof (RegTrack) * cfg->reginfo_len);
}
else
- g_assert (cfg->reginfo_len >= rs->next_vireg);
-
- if (cfg->reginfof && cfg->reginfof_len < rs->next_vfreg) {
- cfg->reginfof = NULL;
- }
- reginfof = cfg->reginfof;
- if (!reginfof) {
- cfg->reginfof_len = MAX (256, rs->next_vireg * 2);
- reginfof = cfg->reginfof = mono_mempool_alloc (cfg->mempool, sizeof (RegTrack) * cfg->reginfof_len);
- }
- else
- g_assert (cfg->reginfof_len >= rs->next_vfreg);
+ g_assert (cfg->reginfo_len >= rs->next_vreg);
- memset (reginfo, 0, rs->next_vireg * sizeof (RegTrack));
- memset (reginfof, 0, rs->next_vfreg * sizeof (RegTrack));
+ memset (reginfo, 0, rs->next_vreg * sizeof (RegTrack));
ins_count = 0;
for (ins = bb->code; ins; ins = ins->next) {
- spec = ins_spec [ins->opcode];
-
ins_count ++;
}
i = 1;
fpcount = 0;
- DEBUG (printf ("LOCAL REGALLOC: BASIC BLOCK: %d\n", bb->block_num));
+ DEBUG (printf ("\nLOCAL REGALLOC: BASIC BLOCK: %d\n", bb->block_num));
/* forward pass on the instructions to collect register liveness info */
for (ins = bb->code; ins; ins = ins->next) {
- spec = ins_spec [ins->opcode];
+ spec = ins_get_spec (ins->opcode);
- if (G_UNLIKELY (!spec)) {
+ if (G_UNLIKELY (spec == MONO_ARCH_CPU_SPEC)) {
g_error ("Opcode '%s' missing from machine description file.", mono_inst_name (ins->opcode));
}
- DEBUG (print_ins (i, ins));
+ DEBUG (mono_print_ins (i, ins));
/*
* TRACK FP STACK
if (spec [MONO_INST_SRC1] == 'f') {
spill = g_list_first (fspill_list);
if (spill && fpcount < MONO_ARCH_FPSTACK_SIZE) {
- reginfof [ins->sreg1].flags |= MONO_FP_NEEDS_LOAD;
+ reginfo [ins->sreg1].flags |= MONO_FP_NEEDS_LOAD;
fspill_list = g_list_remove (fspill_list, spill->data);
} else
fpcount--;
if (spec [MONO_INST_SRC2] == 'f') {
spill = g_list_first (fspill_list);
if (spill) {
- reginfof [ins->sreg2].flags |= MONO_FP_NEEDS_LOAD;
+ reginfo [ins->sreg2].flags |= MONO_FP_NEEDS_LOAD;
fspill_list = g_list_remove (fspill_list, spill->data);
if (fpcount >= MONO_ARCH_FPSTACK_SIZE) {
fspill++;
fspill_list = g_list_prepend (fspill_list, GINT_TO_POINTER(fspill));
- reginfof [ins->sreg2].flags |= MONO_FP_NEEDS_LOAD_SPILL;
+ reginfo [ins->sreg2].flags |= MONO_FP_NEEDS_LOAD_SPILL;
}
} else
fpcount--;
if (dreg_is_fp (spec)) {
if (use_fpstack && (spec [MONO_INST_CLOB] != 'm')) {
if (fpcount >= MONO_ARCH_FPSTACK_SIZE) {
- reginfof [ins->dreg].flags |= MONO_FP_NEEDS_SPILL;
+ reginfo [ins->dreg].flags |= MONO_FP_NEEDS_SPILL;
fspill++;
fspill_list = g_list_prepend (fspill_list, GINT_TO_POINTER(fspill));
fpcount--;
#endif
if (spec [MONO_INST_SRC1]) {
- if (spec [MONO_INST_SRC1] == 'f')
- reginfo1 = reginfof;
- else
- reginfo1 = reginfo;
- //reginfo1 [ins->sreg1].prev_use = reginfo1 [ins->sreg1].last_use;
- //reginfo1 [ins->sreg1].last_use = i;
+ //reginfo [ins->sreg1].prev_use = reginfo [ins->sreg1].last_use;
+ //reginfo [ins->sreg1].last_use = i;
if (MONO_ARCH_INST_IS_REGPAIR (spec [MONO_INST_SRC2])) {
/* The virtual register is allocated sequentially */
- //reginfo1 [ins->sreg1 + 1].prev_use = reginfo1 [ins->sreg1 + 1].last_use;
- //reginfo1 [ins->sreg1 + 1].last_use = i;
- if (reginfo1 [ins->sreg1 + 1].born_in == 0 || reginfo1 [ins->sreg1 + 1].born_in > i)
- reginfo1 [ins->sreg1 + 1].born_in = i;
+ //reginfo [ins->sreg1 + 1].prev_use = reginfo [ins->sreg1 + 1].last_use;
+ //reginfo [ins->sreg1 + 1].last_use = i;
+ if (reginfo [ins->sreg1 + 1].born_in == 0 || reginfo [ins->sreg1 + 1].born_in > i)
+ reginfo [ins->sreg1 + 1].born_in = i;
}
} else {
ins->sreg1 = -1;
}
if (spec [MONO_INST_SRC2]) {
- if (spec [MONO_INST_SRC2] == 'f')
- reginfo2 = reginfof;
- else
- reginfo2 = reginfo;
- //reginfo2 [ins->sreg2].prev_use = reginfo2 [ins->sreg2].last_use;
- //reginfo2 [ins->sreg2].last_use = i;
+ //reginfo [ins->sreg2].prev_use = reginfo [ins->sreg2].last_use;
+ //reginfo [ins->sreg2].last_use = i;
if (MONO_ARCH_INST_IS_REGPAIR (spec [MONO_INST_SRC2])) {
/* The virtual register is allocated sequentially */
- //reginfo2 [ins->sreg2 + 1].prev_use = reginfo2 [ins->sreg2 + 1].last_use;
- //reginfo2 [ins->sreg2 + 1].last_use = i;
- if (reginfo2 [ins->sreg2 + 1].born_in == 0 || reginfo2 [ins->sreg2 + 1].born_in > i)
- reginfo2 [ins->sreg2 + 1].born_in = i;
+ //reginfo [ins->sreg2 + 1].prev_use = reginfo [ins->sreg2 + 1].last_use;
+ //reginfo [ins->sreg2 + 1].last_use = i;
+ if (reginfo [ins->sreg2 + 1].born_in == 0 || reginfo [ins->sreg2 + 1].born_in > i)
+ reginfo [ins->sreg2 + 1].born_in = i;
}
} else {
ins->sreg2 = -1;
if (spec [MONO_INST_DEST]) {
int dest_dreg;
- if (dreg_is_fp (spec))
- reginfod = reginfof;
- else
- reginfod = reginfo;
if (spec [MONO_INST_DEST] != 'b') /* it's not just a base register */
- reginfod [ins->dreg].killed_in = i;
- //reginfod [ins->dreg].prev_use = reginfod [ins->dreg].last_use;
- //reginfod [ins->dreg].last_use = i;
- if (reginfod [ins->dreg].born_in == 0 || reginfod [ins->dreg].born_in > i)
- reginfod [ins->dreg].born_in = i;
+ reginfo [ins->dreg].killed_in = i;
+ //reginfo [ins->dreg].prev_use = reginfo [ins->dreg].last_use;
+ //reginfo [ins->dreg].last_use = i;
+ if (reginfo [ins->dreg].born_in == 0 || reginfo [ins->dreg].born_in > i)
+ reginfo [ins->dreg].born_in = i;
dest_dreg = MONO_ARCH_INST_FIXED_REG (spec [MONO_INST_DEST]);
if (dest_dreg != -1)
- reginfod [ins->dreg].preferred_mask = (regmask (dest_dreg));
+ reginfo [ins->dreg].preferred_mask = (regmask (dest_dreg));
if (MONO_ARCH_INST_IS_REGPAIR (spec [MONO_INST_DEST])) {
/* The virtual register is allocated sequentially */
- //reginfod [ins->dreg + 1].prev_use = reginfod [ins->dreg + 1].last_use;
- //reginfod [ins->dreg + 1].last_use = i;
- if (reginfod [ins->dreg + 1].born_in == 0 || reginfod [ins->dreg + 1].born_in > i)
- reginfod [ins->dreg + 1].born_in = i;
+ //reginfo [ins->dreg + 1].prev_use = reginfo [ins->dreg + 1].last_use;
+ //reginfo [ins->dreg + 1].last_use = i;
+ if (reginfo [ins->dreg + 1].born_in == 0 || reginfo [ins->dreg + 1].born_in > i)
+ reginfo [ins->dreg + 1].born_in = i;
if (MONO_ARCH_INST_REGPAIR_REG2 (spec [MONO_INST_DEST], -1) != -1)
- reginfod [ins->dreg + 1].preferred_mask = regpair_reg2_mask (spec [MONO_INST_DEST], -1);
+ reginfo [ins->dreg + 1].preferred_mask = regpair_reg2_mask (spec [MONO_INST_DEST], -1);
}
} else {
ins->dreg = -1;
hreg = regpair >> 24;
reg = regpair & 0xffffff;
- //reginfof [reg].prev_use = reginfof [reg].last_use;
- //reginfof [reg].last_use = i;
+ //reginfo [reg].prev_use = reginfo [reg].last_use;
+ //reginfo [reg].last_use = i;
list = g_slist_next (list);
}
// todo: check if we have anything left on fp stack, in verify mode?
fspill = 0;
- DEBUG (print_regtrack (reginfo, rs->next_vireg));
- DEBUG (print_regtrack (reginfof, rs->next_vfreg));
+ DEBUG (print_regtrack (reginfo, rs->next_vreg));
tmp = reversed;
while (tmp) {
int prev_dreg, prev_sreg1, prev_sreg2, clob_dreg;
const unsigned char *ip;
--i;
ins = tmp->data;
- spec = ins_spec [ins->opcode];
+ spec = ins_get_spec (ins->opcode);
prev_dreg = -1;
prev_sreg2 = -1;
clob_dreg = -1;
dest_dreg = -1;
dest_sreg1 = -1;
dest_sreg2 = -1;
+ prev_sreg1 = -1;
+ dreg_high = -1;
+ sreg1_high = -1;
dreg_mask = dreg_is_fp (spec) ? MONO_ARCH_CALLEE_FREGS : MONO_ARCH_CALLEE_REGS;
sreg1_mask = sreg1_is_fp (spec) ? MONO_ARCH_CALLEE_FREGS : MONO_ARCH_CALLEE_REGS;
sreg2_mask = sreg2_is_fp (spec) ? MONO_ARCH_CALLEE_FREGS : MONO_ARCH_CALLEE_REGS;
DEBUG (printf ("processing:"));
- DEBUG (print_ins (i, ins));
+ DEBUG (mono_print_ins (i, ins));
ip = ins->cil_code;
#if MONO_ARCH_USE_FPSTACK
if (need_fpstack && (spec [MONO_INST_CLOB] != 'm')) {
if (dreg_is_fp (spec)) {
- if (reginfof [ins->dreg].flags & MONO_FP_NEEDS_SPILL) {
+ if (reginfo [ins->dreg].flags & MONO_FP_NEEDS_SPILL) {
GList *spill_node;
MonoInst *store;
spill_node = g_list_first (fspill_list);
}
if (spec [MONO_INST_SRC1] == 'f') {
- if (reginfof [ins->sreg1].flags & MONO_FP_NEEDS_LOAD) {
+ if (reginfo [ins->sreg1].flags & MONO_FP_NEEDS_LOAD) {
MonoInst *load;
MonoInst *store = NULL;
- if (reginfof [ins->sreg1].flags & MONO_FP_NEEDS_LOAD_SPILL) {
+ if (reginfo [ins->sreg1].flags & MONO_FP_NEEDS_LOAD_SPILL) {
GList *spill_node;
spill_node = g_list_first (fspill_list);
g_assert (spill_node);
}
if (spec [MONO_INST_SRC2] == 'f') {
- if (reginfof [ins->sreg2].flags & MONO_FP_NEEDS_LOAD) {
+ if (reginfo [ins->sreg2].flags & MONO_FP_NEEDS_LOAD) {
MonoInst *load;
MonoInst *store = NULL;
- if (reginfof [ins->sreg2].flags & MONO_FP_NEEDS_LOAD_SPILL) {
+ if (reginfo [ins->sreg2].flags & MONO_FP_NEEDS_LOAD_SPILL) {
GList *spill_node;
spill_node = g_list_first (fspill_list);
g_assert (spill_node);
- if (spec [MONO_INST_SRC1] == 'f' && (reginfof [ins->sreg2].flags & MONO_FP_NEEDS_LOAD_SPILL))
+ if (spec [MONO_INST_SRC1] == 'f' && (reginfo [ins->sreg2].flags & MONO_FP_NEEDS_LOAD_SPILL))
spill_node = g_list_next (spill_node);
store = create_spilled_store_float (cfg, GPOINTER_TO_INT (spill_node->data), ins->sreg2, ins);
insert_before_ins (ins, tmp, copy);
}
else {
- DEBUG (printf ("\tshortcut assignment of R%d to %s\n", ins->sreg2, mono_arch_regname (dest_sreg2)));
- assign_ireg (cfg, rs, ins->sreg2, dest_sreg2);
+ val = rs->vassign [ins->sreg2];
+ if (val == -1) {
+ DEBUG (printf ("\tshortcut assignment of R%d to %s\n", ins->sreg2, mono_arch_regname (dest_sreg2)));
+ assign_reg (cfg, rs, ins->sreg2, dest_sreg2, FALSE);
+ } else if (val < -1) {
+ /* FIXME: */
+ g_assert_not_reached ();
+ } else {
+ /* Argument already in hard reg, need to copy */
+ MonoInst *copy = create_copy_ins (cfg, dest_sreg2, val, NULL, ip, FALSE);
+ insert_before_ins (ins, tmp, copy);
+ }
}
} else {
int need_spill = TRUE;
* First check if dreg is assigned to dest_sreg2, since we
* can't spill a dreg.
*/
- val = rs->iassign [ins->dreg];
+ val = rs->vassign [ins->dreg];
if (val == dest_sreg2 && ins->dreg != ins->sreg2) {
/*
* the destination register is already assigned to
assign_ireg (cfg, rs, ins->dreg, new_dest);
clob_dreg = ins->dreg;
create_copy_ins (cfg, dest_sreg2, new_dest, ins, ip, FALSE);
+ mono_regstate_free_int (rs, dest_sreg2);
need_spill = FALSE;
}
insert_before_ins (ins, tmp, copy);
}
else {
- val = rs->iassign [ins->sreg2];
+ val = rs->vassign [ins->sreg2];
if (val == dest_sreg2) {
/* sreg2 is already assigned to the correct register */
need_spill = FALSE;
if (need_spill) {
DEBUG (printf ("\tforced spill of R%d\n", rs->isymbolic [dest_sreg2]));
get_register_force_spilling (cfg, tmp, ins, rs->isymbolic [dest_sreg2], FALSE);
- mono_regstate2_free_int (rs, dest_sreg2);
+ mono_regstate_free_int (rs, dest_sreg2);
}
if (!is_global_ireg (ins->sreg2))
if (is_soft_reg (ins->dreg, fp) && (val >= 0) && (!(regmask (val) & dreg_mask))) {
/* DREG is already allocated to a register needed for sreg1 */
get_register_force_spilling (cfg, tmp, ins, ins->dreg, FALSE);
- mono_regstate2_free_int (rs, val);
+ mono_regstate_free_int (rs, val);
}
}
g_assert (is_soft_reg (ins->dreg, fp));
if (dest_dreg != -1) {
- if (rs->iassign [ins->dreg] != dest_dreg)
+ if (rs->vassign [ins->dreg] != dest_dreg)
free_up_ireg (cfg, tmp, ins, dest_dreg);
dreg2 = ins->dreg + 1;
dest_dreg2 = MONO_ARCH_INST_REGPAIR_REG2 (spec [MONO_INST_DEST], dest_dreg);
if (dest_dreg2 != -1) {
- if (rs->iassign [dreg2] != dest_dreg2)
+ if (rs->vassign [dreg2] != dest_dreg2)
free_up_ireg (cfg, tmp, ins, dest_dreg2);
}
}
* The argument is already in a hard reg, but that reg is
* not usable by this instruction, so allocate a new one.
*/
- val = mono_regstate2_alloc_int (rs, dreg_fixed_mask);
+ val = mono_regstate_alloc_int (rs, dreg_fixed_mask);
if (val < 0)
val = get_register_spilling (cfg, tmp, ins, dreg_fixed_mask, -1, fp);
- mono_regstate2_free_int (rs, val);
+ mono_regstate_free_int (rs, val);
dest_dreg = val;
/* Fall through */
g_assert (!fp);
g_assert (prev_dreg > -1);
- g_assert (!is_global_ireg (rs->iassign [prev_dreg]));
- mask = regpair_reg2_mask (spec [MONO_INST_DEST], rs->iassign [prev_dreg]);
- val = rs->iassign [reg2];
+ g_assert (!is_global_ireg (rs->vassign [prev_dreg]));
+ mask = regpair_reg2_mask (spec [MONO_INST_DEST], rs->vassign [prev_dreg]);
+#ifdef __i386__
+ /* bug #80489 */
+ mask &= ~regmask (X86_ECX);
+#endif
+ val = rs->vassign [reg2];
if (val < 0) {
int spill = 0;
if (val < -1) {
/* the register gets spilled after this inst */
spill = -val -1;
}
- val = mono_regstate2_alloc_int (rs, mask);
+ val = mono_regstate_alloc_int (rs, mask);
if (val < 0)
val = get_register_spilling (cfg, tmp, ins, mask, reg2, fp);
if (spill)
}
else {
if (! (mask & (regmask (val)))) {
- val = mono_regstate2_alloc_int (rs, mask);
+ val = mono_regstate_alloc_int (rs, mask);
if (val < 0)
val = get_register_spilling (cfg, tmp, ins, mask, reg2, fp);
/* Reallocate hreg to the correct register */
- create_copy_ins (cfg, rs->iassign [reg2], val, ins, ip, fp);
+ create_copy_ins (cfg, rs->vassign [reg2], val, ins, ip, fp);
- mono_regstate2_free_int (rs, rs->iassign [reg2]);
+ mono_regstate_free_int (rs, rs->vassign [reg2]);
}
}
assign_reg (cfg, rs, reg2, val, fp);
dreg_high = val;
- ins->unused = val;
+ ins->backend.reg3 = val;
if (reg_is_freeable (val, fp) && reg2 >= 0 && (reginfo [reg2].born_in >= i)) {
DEBUG (printf ("\tfreeable %s (R%d)\n", mono_arch_regname (val), reg2));
- mono_regstate2_free_int (rs, val);
+ mono_regstate_free_int (rs, val);
}
}
- if ((!fp || (fp && !use_fpstack)) && prev_dreg >= 0 && is_soft_reg (prev_dreg, fp) && (fp ? reginfof : reginfo) [prev_dreg].born_in >= i) {
+ if ((!fp || (fp && !use_fpstack)) && prev_dreg >= 0 && is_soft_reg (prev_dreg, fp) && reginfo [prev_dreg].born_in >= i) {
/*
* In theory, we could free up the hreg even if the vreg is alive,
* but branches inside bblocks force us to assign the same hreg
*/
int dreg = rassign (cfg, prev_dreg, fp);
g_assert (dreg >= 0);
- DEBUG (printf ("\tfreeable %s (R%d) (born in %d)\n", mono_regname_full (dreg, fp), prev_dreg, (fp ? reginfof : reginfo) [prev_dreg].born_in));
+ DEBUG (printf ("\tfreeable %s (R%d) (born in %d)\n", mono_regname_full (dreg, fp), prev_dreg, reginfo [prev_dreg].born_in));
if (fp)
- mono_regstate2_free_float (rs, dreg);
+ mono_regstate_free_float (rs, dreg);
else
- mono_regstate2_free_int (rs, dreg);
+ mono_regstate_free_int (rs, dreg);
}
if ((dest_dreg != -1) && (ins->dreg != dest_dreg)) {
if ((clob_reg != -1) && (!(rs->ifree_mask & (regmask (clob_reg))))) {
DEBUG (printf ("\tforced spill of clobbered reg R%d\n", rs->isymbolic [clob_reg]));
get_register_force_spilling (cfg, tmp, ins, rs->isymbolic [clob_reg], FALSE);
- mono_regstate2_free_int (rs, clob_reg);
+ mono_regstate_free_int (rs, clob_reg);
}
if (spec [MONO_INST_CLOB] == 'c') {
s = regmask (j);
if ((clob_mask & s) && !(rs->ifree_mask & s) && (j != ins->sreg1) && (j != dreg) && (j != dreg2)) {
get_register_force_spilling (cfg, tmp, ins, rs->isymbolic [j], FALSE);
- mono_regstate2_free_int (rs, j);
+ mono_regstate_free_int (rs, j);
}
}
s = regmask (j);
if ((clob_mask & s) && !(rs->ffree_mask & s) && (j != ins->sreg1) && (j != dreg)) {
get_register_force_spilling (cfg, tmp, ins, rs->fsymbolic [j], TRUE);
- mono_regstate2_free_float (rs, j);
+ mono_regstate_free_float (rs, j);
}
}
}
/* To simplify things, we allocate the same regpair to sreg1 and dreg */
if (dest_sreg1 != -1)
g_assert (dest_sreg1 == ins->dreg);
- val = mono_regstate2_alloc_int (rs, regmask (ins->dreg));
+ val = mono_regstate_alloc_int (rs, regmask (ins->dreg));
g_assert (val >= 0);
assign_reg (cfg, rs, ins->sreg1, val, fp);
DEBUG (printf ("\tassigned sreg1-low %s to R%d\n", mono_regname_full (val, fp), ins->sreg1));
g_assert ((regmask (dreg_high)) & regpair_reg2_mask (spec [MONO_INST_SRC1], ins->dreg));
- val = mono_regstate2_alloc_int (rs, regmask (dreg_high));
+ val = mono_regstate_alloc_int (rs, regmask (dreg_high));
g_assert (val >= 0);
assign_reg (cfg, rs, ins->sreg1 + 1, val, fp);
* The argument is already in a hard reg, but that reg is
* not usable by this instruction, so allocate a new one.
*/
- val = mono_regstate2_alloc_int (rs, sreg1_fixed_mask);
+ val = mono_regstate_alloc_int (rs, sreg1_fixed_mask);
if (val < 0)
val = get_register_spilling (cfg, tmp, ins, sreg1_fixed_mask, -1, fp);
- mono_regstate2_free_int (rs, val);
+ mono_regstate_free_int (rs, val);
dest_sreg1 = val;
/* Fall through to the dest_sreg1 != -1 case */
if (!(rs->ifree_mask & (regmask (dest_sreg1)))) {
DEBUG (printf ("\tforced spill of R%d\n", rs->isymbolic [dest_sreg1]));
get_register_force_spilling (cfg, tmp, ins, rs->isymbolic [dest_sreg1], FALSE);
- mono_regstate2_free_int (rs, dest_sreg1);
+ mono_regstate_free_int (rs, dest_sreg1);
}
if (is_global_ireg (ins->sreg1)) {
/* The argument is already in a hard reg, need to copy */
spill = -val -1;
}
- if (((ins->opcode == OP_MOVE) || (ins->opcode == OP_SETREG)) && !spill && !fp && (!is_global_ireg (ins->dreg) && (rs->ifree_mask & (regmask (ins->dreg))))) {
+ if (((ins->opcode == OP_MOVE) || (ins->opcode == OP_SETREG)) && !spill && !fp && (is_local_ireg (ins->dreg) && (rs->ifree_mask & (regmask (ins->dreg))))) {
/*
* Allocate the same hreg to sreg1 as well so the
* peephole can get rid of the move.
g_assert (!fp);
g_assert (prev_sreg1 > -1);
- g_assert (!is_global_ireg (rs->iassign [prev_sreg1]));
- mask = regpair_reg2_mask (spec [MONO_INST_SRC1], rs->iassign [prev_sreg1]);
- val = rs->iassign [reg2];
+ g_assert (!is_global_ireg (rs->vassign [prev_sreg1]));
+ mask = regpair_reg2_mask (spec [MONO_INST_SRC1], rs->vassign [prev_sreg1]);
+ val = rs->vassign [reg2];
if (val < 0) {
int spill = 0;
if (val < -1) {
/* the register gets spilled after this inst */
spill = -val -1;
}
- val = mono_regstate2_alloc_int (rs, mask);
+ val = mono_regstate_alloc_int (rs, mask);
if (val < 0)
val = get_register_spilling (cfg, tmp, ins, mask, reg2, fp);
if (spill)
/* FIXME: */
g_assert_not_reached ();
#if 0
- val = mono_regstate2_alloc_int (rs, mask);
+ val = mono_regstate_alloc_int (rs, mask);
if (val < 0)
val = get_register_spilling (cfg, tmp, ins, mask, reg2, fp);
/* Reallocate hreg to the correct register */
- create_copy_ins (cfg, rs->iassign [reg2], val, ins, ip, fp);
+ create_copy_ins (cfg, rs->vassign [reg2], val, ins, ip, fp);
- mono_regstate2_free_int (rs, rs->iassign [reg2]);
+ mono_regstate_free_int (rs, rs->vassign [reg2]);
#endif
}
}
prev_sreg2 = ins->sreg2 = reg2;
if (fp)
- mono_regstate2_free_float (rs, reg2);
+ mono_regstate_free_float (rs, reg2);
else
- mono_regstate2_free_int (rs, reg2);
+ mono_regstate_free_int (rs, reg2);
}
if (MONO_ARCH_INST_IS_REGPAIR (spec [MONO_INST_SRC1])) {
/* Copying sreg1_high to dreg could also clobber sreg2 */
- if (rs->iassign [prev_sreg1 + 1] == ins->sreg2)
+ if (rs->vassign [prev_sreg1 + 1] == ins->sreg2)
/* FIXME: */
g_assert_not_reached ();
val = alloc_reg (cfg, tmp, ins, sreg2_mask, ins->sreg2, ®info [ins->sreg2], fp);
assign_reg (cfg, rs, ins->sreg2, val, fp);
DEBUG (printf ("\tassigned sreg2 %s to R%d\n", mono_regname_full (val, fp), ins->sreg2));
- if (spill)
- create_spilled_store (cfg, spill, val, prev_sreg2, ins, fp);
+ if (spill) {
+ MonoInst *store = create_spilled_store (cfg, spill, val, prev_sreg2, NULL, fp);
+ /*
+ * Need to insert before the instruction since it can
+ * overwrite sreg2.
+ */
+ insert_before_ins (ins, tmp, store);
+ }
}
ins->sreg2 = val;
}
/*if (reg_is_freeable (ins->sreg1) && prev_sreg1 >= 0 && reginfo [prev_sreg1].born_in >= i) {
DEBUG (printf ("freeable %s\n", mono_arch_regname (ins->sreg1)));
- mono_regstate2_free_int (rs, ins->sreg1);
+ mono_regstate_free_int (rs, ins->sreg1);
}
if (reg_is_freeable (ins->sreg2) && prev_sreg2 >= 0 && reginfo [prev_sreg2].born_in >= i) {
DEBUG (printf ("freeable %s\n", mono_arch_regname (ins->sreg2)));
- mono_regstate2_free_int (rs, ins->sreg2);
+ mono_regstate_free_int (rs, ins->sreg2);
}*/
- DEBUG (print_ins (i, ins));
+ DEBUG (mono_print_ins (i, ins));
/* this may result from a insert_before call */
if (!tmp->next)
bb->code = tmp->data;
g_list_free (fspill_list);
}
+
+CompRelation
+mono_opcode_to_cond (int opcode)
+{
+ switch (opcode) {
+ case CEE_BEQ:
+ case OP_CEQ:
+ case OP_IBEQ:
+ case OP_ICEQ:
+ case OP_LBEQ:
+ case OP_LCEQ:
+ case OP_FBEQ:
+ case OP_FCEQ:
+ case OP_COND_EXC_EQ:
+ case OP_COND_EXC_IEQ:
+ return CMP_EQ;
+ case CEE_BNE_UN:
+ case OP_IBNE_UN:
+ case OP_LBNE_UN:
+ case OP_FBNE_UN:
+ case OP_COND_EXC_NE_UN:
+ case OP_COND_EXC_INE_UN:
+ return CMP_NE;
+ case CEE_BLE:
+ case OP_IBLE:
+ case OP_LBLE:
+ case OP_FBLE:
+ return CMP_LE;
+ case CEE_BGE:
+ case OP_IBGE:
+ case OP_LBGE:
+ case OP_FBGE:
+ return CMP_GE;
+ case CEE_BLT:
+ case OP_CLT:
+ case OP_IBLT:
+ case OP_ICLT:
+ case OP_LBLT:
+ case OP_LCLT:
+ case OP_FBLT:
+ case OP_FCLT:
+ case OP_COND_EXC_LT:
+ case OP_COND_EXC_ILT:
+ return CMP_LT;
+ case CEE_BGT:
+ case OP_CGT:
+ case OP_IBGT:
+ case OP_ICGT:
+ case OP_LBGT:
+ case OP_LCGT:
+ case OP_FBGT:
+ case OP_FCGT:
+ case OP_COND_EXC_GT:
+ case OP_COND_EXC_IGT:
+ return CMP_GT;
+
+ case CEE_BLE_UN:
+ case OP_IBLE_UN:
+ case OP_LBLE_UN:
+ case OP_FBLE_UN:
+ case OP_COND_EXC_LE_UN:
+ case OP_COND_EXC_ILE_UN:
+ return CMP_LE_UN;
+ case CEE_BGE_UN:
+ case OP_IBGE_UN:
+ case OP_LBGE_UN:
+ case OP_FBGE_UN:
+ return CMP_GE_UN;
+ case CEE_BLT_UN:
+ case OP_CLT_UN:
+ case OP_IBLT_UN:
+ case OP_ICLT_UN:
+ case OP_LBLT_UN:
+ case OP_LCLT_UN:
+ case OP_FBLT_UN:
+ case OP_FCLT_UN:
+ case OP_COND_EXC_LT_UN:
+ case OP_COND_EXC_ILT_UN:
+ return CMP_LT_UN;
+ case CEE_BGT_UN:
+ case OP_CGT_UN:
+ case OP_IBGT_UN:
+ case OP_ICGT_UN:
+ case OP_LBGT_UN:
+ case OP_LCGT_UN:
+ case OP_FCGT_UN:
+ case OP_FBGT_UN:
+ case OP_COND_EXC_GT_UN:
+ case OP_COND_EXC_IGT_UN:
+ return CMP_GT_UN;
+ default:
+ printf ("%s\n", mono_inst_name (opcode));
+ g_assert_not_reached ();
+ }
+}
+
+CompType
+mono_opcode_to_type (int opcode, int cmp_opcode)
+{
+ if ((opcode >= CEE_BEQ) && (opcode <= CEE_BLT_UN))
+ return CMP_TYPE_L;
+ else if ((opcode >= OP_CEQ) && (opcode <= OP_CLT_UN))
+ return CMP_TYPE_L;
+ else if ((opcode >= OP_IBEQ) && (opcode <= OP_IBLT_UN))
+ return CMP_TYPE_I;
+ else if ((opcode >= OP_ICEQ) && (opcode <= OP_ICLT_UN))
+ return CMP_TYPE_I;
+ else if ((opcode >= OP_LBEQ) && (opcode <= OP_LBLT_UN))
+ return CMP_TYPE_L;
+ else if ((opcode >= OP_LCEQ) && (opcode <= OP_LCLT_UN))
+ return CMP_TYPE_L;
+ else if ((opcode >= OP_FBEQ) && (opcode <= OP_FBLT_UN))
+ return CMP_TYPE_F;
+ else if ((opcode >= OP_FCEQ) && (opcode <= OP_FCLT_UN))
+ return CMP_TYPE_F;
+ else if ((opcode >= OP_COND_EXC_IEQ) && (opcode <= OP_COND_EXC_ILT_UN))
+ return CMP_TYPE_I;
+ else if ((opcode >= OP_COND_EXC_EQ) && (opcode <= OP_COND_EXC_LT_UN)) {
+ switch (cmp_opcode) {
+ case OP_ICOMPARE:
+ case OP_ICOMPARE_IMM:
+ return CMP_TYPE_I;
+ default:
+ return CMP_TYPE_L;
+ }
+ } else {
+ g_error ("Unknown opcode '%s' in opcode_to_type", mono_inst_name (opcode));
+ return 0;
+ }
+}
+
+gboolean
+mono_is_regsize_var (MonoType *t)
+{
+ if (t->byref)
+ return TRUE;
+ t = mono_type_get_underlying_type (t);
+ switch (t->type) {
+ 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_FNPTR:
+#if SIZEOF_VOID_P == 8
+ case MONO_TYPE_I8:
+ case MONO_TYPE_U8:
+#endif
+ return TRUE;
+ case MONO_TYPE_OBJECT:
+ case MONO_TYPE_STRING:
+ case MONO_TYPE_CLASS:
+ case MONO_TYPE_SZARRAY:
+ case MONO_TYPE_ARRAY:
+ return TRUE;
+ case MONO_TYPE_GENERICINST:
+ if (!mono_type_generic_inst_is_valuetype (t))
+ return TRUE;
+ return FALSE;
+ case MONO_TYPE_VALUETYPE:
+ return FALSE;
+ }
+ return FALSE;
+}