#define SIGNAL_STACK_SIZE (64 * 1024)
-static gpointer mono_arch_get_lmf_addr (void);
-
const char*
mono_arch_regname (int reg) {
switch (reg) {
x86_branch (code, cond, cfg->native_code + ins->inst_i0->inst_c0, sign); \
} else { \
mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_LABEL, ins->inst_i0); \
- x86_branch32 (code, cond, 0, sign); \
+ if ((cfg->opt & MONO_OPT_BRANCH) && \
+ x86_is_imm8 (ins->inst_i0->inst_c1 - cpos)) \
+ x86_branch8 (code, cond, 0, sign); \
+ else \
+ x86_branch32 (code, cond, 0, sign); \
} \
} else { \
if (ins->inst_true_bb->native_offset) { \
#endif
/* flags used in reginfo->flags */
-#define MONO_X86_FP_NEEDS_LOAD_SPILL 1
-#define MONO_X86_FP_NEEDS_SPILL 2
-#define MONO_X86_FP_NEEDS_LOAD 4
+enum {
+ MONO_X86_FP_NEEDS_LOAD_SPILL = 1 << 0,
+ MONO_X86_FP_NEEDS_SPILL = 1 << 1,
+ MONO_X86_FP_NEEDS_LOAD = 1 << 2,
+ MONO_X86_REG_NOT_ECX = 1 << 3,
+ MONO_X86_REG_EAX = 1 << 4,
+ MONO_X86_REG_EDX = 1 << 5,
+ MONO_X86_REG_ECX = 1 << 6
+};
+
+static int
+mono_x86_alloc_int_reg (MonoCompile *cfg, InstList *tmp, MonoInst *ins, guint32 dest_mask, int sym_reg, int flags)
+{
+ int val;
+ int test_mask = dest_mask;
+
+ if (flags & MONO_X86_REG_EAX)
+ test_mask &= (1 << X86_EAX);
+ else if (flags & MONO_X86_REG_EDX)
+ test_mask &= (1 << X86_EDX);
+ else if (flags & MONO_X86_REG_ECX)
+ test_mask &= (1 << X86_ECX);
+ else if (flags & MONO_X86_REG_NOT_ECX)
+ test_mask &= ~ (1 << X86_ECX);
+
+ val = mono_regstate_alloc_int (cfg->rs, test_mask);
+ if (val >= 0 && test_mask != dest_mask)
+ DEBUG(g_print ("\tUsed flag to allocate reg %s for R%u\n", mono_arch_regname (val), sym_reg));
+
+ if (val < 0 && (flags & MONO_X86_REG_NOT_ECX)) {
+ DEBUG(g_print ("\tFailed to allocate flag suggested mask (%u) but exluding ECX\n", test_mask));
+ val = mono_regstate_alloc_int (cfg->rs, (dest_mask & (~1 << X86_ECX)));
+ }
+
+ if (val < 0) {
+ val = mono_regstate_alloc_int (cfg->rs, dest_mask);
+ if (val < 0)
+ val = get_register_spilling (cfg, tmp, ins, dest_mask, sym_reg);
+ }
+
+ return val;
+}
+
/*#include "cprop.c"*/
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;
+
+ reginfo1 [ins->sreg1].flags |= MONO_X86_REG_EAX;
+ reginfo1 [ins->sreg1 + 1].flags |= MONO_X86_REG_EDX;
}
} else {
ins->sreg1 = -1;
if (reginfo2 [ins->sreg2 + 1].born_in == 0 || reginfo2 [ins->sreg2 + 1].born_in > i)
reginfo2 [ins->sreg2 + 1].born_in = i;
}
+ if (spec [MONO_INST_CLOB] == 's') {
+ reginfo2 [ins->sreg1].flags |= MONO_X86_REG_NOT_ECX;
+ reginfo2 [ins->sreg2].flags |= MONO_X86_REG_ECX;
+ }
} else {
ins->sreg2 = -1;
}
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;
- }
+
+ reginfod [ins->dreg].flags |= MONO_X86_REG_EAX;
+ reginfod [ins->dreg + 1].flags |= MONO_X86_REG_EDX;
+ }
} else {
ins->dreg = -1;
}
+
reversed = inst_list_prepend (cfg->mempool, reversed, ins);
++i;
ins = ins->next;
* copy from this to ECX.
*/
if (val == X86_ECX && ins->dreg != ins->sreg2) {
- int new_dest = mono_regstate_alloc_int (rs, dest_mask);
- if (new_dest < 0)
- new_dest = get_register_spilling (cfg, tmp, ins, dest_mask, ins->dreg);
+ int new_dest;
+ new_dest = mono_x86_alloc_int_reg (cfg, tmp, ins, dest_mask, ins->dreg, reginfo [ins->dreg].flags);
g_assert (new_dest >= 0);
DEBUG (g_print ("\tclob:s changing dreg R%d to %s from ECX\n", ins->dreg, mono_arch_regname (new_dest)));
src2_mask = 1 << X86_ECX;
}
if (spec [MONO_INST_DEST] == 'l') {
- if (!(rs->ifree_mask & (1 << X86_EAX))) {
+ int hreg;
+ val = rs->iassign [ins->dreg];
+ /* check special case when dreg have been moved from ecx (clob shift) */
+ if (spec [MONO_INST_CLOB] == 's' && clob_dreg != -1)
+ hreg = clob_dreg + 1;
+ else
+ hreg = ins->dreg + 1;
+
+ /* base prev_dreg on fixed hreg, handle clob case */
+ val = hreg - 1;
+
+ if (val != rs->isymbolic [X86_EAX] && !(rs->ifree_mask & (1 << X86_EAX))) {
DEBUG (g_print ("\t(long-low) forced spill of R%d\n", rs->isymbolic [X86_EAX]));
get_register_force_spilling (cfg, tmp, ins, rs->isymbolic [X86_EAX]);
mono_regstate_free_int (rs, X86_EAX);
}
- if (!(rs->ifree_mask & (1 << X86_EDX))) {
+ if (hreg != rs->isymbolic [X86_EDX] && !(rs->ifree_mask & (1 << X86_EDX))) {
DEBUG (g_print ("\t(long-high) forced spill of R%d\n", rs->isymbolic [X86_EDX]));
get_register_force_spilling (cfg, tmp, ins, rs->isymbolic [X86_EDX]);
mono_regstate_free_int (rs, X86_EDX);
/* the register gets spilled after this inst */
spill = -val -1;
}
- val = mono_regstate_alloc_int (rs, dest_mask);
- if (val < 0)
- val = get_register_spilling (cfg, tmp, ins, dest_mask, prev_dreg);
- rs->iassign [prev_dreg] = val;
+ val = mono_x86_alloc_int_reg (cfg, tmp, ins, dest_mask, ins->dreg, reginfo [ins->dreg].flags);
+ rs->iassign [ins->dreg] = val;
if (spill)
create_spilled_store (cfg, spill, val, prev_dreg, ins);
}
- DEBUG (g_print ("\tassigned dreg (long) %s to dest R%d\n", mono_arch_regname (val), prev_dreg));
-
- rs->isymbolic [val] = prev_dreg;
+ DEBUG (g_print ("\tassigned dreg (long) %s to dest R%d\n", mono_arch_regname (val), hreg - 1));
+
+ rs->isymbolic [val] = hreg - 1;
ins->dreg = val;
val = rs->iassign [hreg];
/* the register gets spilled after this inst */
spill = -val -1;
}
- val = mono_regstate_alloc_int (rs, dest_mask);
- if (val < 0)
- val = get_register_spilling (cfg, tmp, ins, dest_mask, hreg);
+ val = mono_x86_alloc_int_reg (cfg, tmp, ins, dest_mask, hreg, reginfo [hreg].flags);
rs->iassign [hreg] = val;
if (spill)
create_spilled_store (cfg, spill, val, hreg, ins);
/* save reg allocating into unused */
ins->unused = val;
- /* Free the extra reg if possible */
+ /* check if we can free our long reg */
if (reg_is_freeable (val) && hreg >= 0 && reginfo [hreg].born_in >= i) {
DEBUG (g_print ("\tfreeable %s (R%d) (born in %d)\n", mono_arch_regname (val), hreg, reginfo [hreg].born_in));
mono_regstate_free_int (rs, val);
/* the register gets spilled after this inst */
spill = -val -1;
}
- val = mono_regstate_alloc_int (rs, dest_mask);
- if (val < 0)
- val = get_register_spilling (cfg, tmp, ins, dest_mask, prev_dreg);
- rs->iassign [prev_dreg] = val;
+ val = mono_x86_alloc_int_reg (cfg, tmp, ins, dest_mask, ins->dreg, reginfo [ins->dreg].flags);
+ rs->iassign [ins->dreg] = val;
if (spill)
create_spilled_store (cfg, spill, val, prev_dreg, ins);
}
/* the register gets spilled after this inst */
spill = -val -1;
}
- val = mono_regstate_alloc_int (rs, dest_mask);
- if (val < 0)
- val = get_register_spilling (cfg, tmp, ins, dest_mask, hreg);
+ val = mono_x86_alloc_int_reg (cfg, tmp, ins, dest_mask, hreg, reginfo [hreg].flags);
rs->iassign [hreg] = val;
if (spill)
create_spilled_store (cfg, spill, val, hreg, ins);
DEBUG (g_print ("\tassigned sreg1 (long-high) %s to sreg1 R%d\n", mono_arch_regname (ins->unused), ins->sreg1 + 1));
ins->sreg1 = ins->dreg;
- /* no need for this, we know that src1=dest in this cases */
- /*ins->inst_c0 = ins->unused;*/
+ /*
+ * No need for saving the reg, we know that src1=dest in this cases
+ * ins->inst_c0 = ins->unused;
+ */
/* make sure that we remove them from free mask */
rs->ifree_mask &= ~ (1 << ins->dreg);
DEBUG (g_print ("\tfast assigned sreg1 %s to R%d\n", mono_arch_regname (val), ins->sreg1));
} else {
//g_assert (val == -1); /* source cannot be spilled */
- val = mono_regstate_alloc_int (rs, src1_mask);
- if (val < 0)
- val = get_register_spilling (cfg, tmp, ins, src1_mask, ins->sreg1);
+ val = mono_x86_alloc_int_reg (cfg, tmp, ins, src1_mask, ins->sreg1, reginfo [ins->sreg1].flags);
rs->iassign [ins->sreg1] = val;
DEBUG (g_print ("\tassigned sreg1 %s to R%d\n", mono_arch_regname (val), ins->sreg1));
}
/* the register gets spilled after this inst */
spill = -val -1;
}
- val = mono_regstate_alloc_int (rs, src2_mask);
- if (val < 0)
- val = get_register_spilling (cfg, tmp, ins, src2_mask, ins->sreg2);
+ val = mono_x86_alloc_int_reg (cfg, tmp, ins, src2_mask, ins->sreg2, reginfo [ins->sreg2].flags);
rs->iassign [ins->sreg2] = val;
DEBUG (g_print ("\tassigned sreg2 %s to R%d\n", mono_arch_regname (val), ins->sreg2));
if (spill)
x86_jump_code (code, cfg->native_code + ins->inst_i0->inst_c0);
} else {
mono_add_patch_info (cfg, offset, MONO_PATCH_INFO_LABEL, ins->inst_i0);
- x86_jump32 (code, 0);
+ if ((cfg->opt & MONO_OPT_BRANCH) &&
+ x86_is_imm8 (ins->inst_i0->inst_c1 - cpos))
+ x86_jump8 (code, 0);
+ else
+ x86_jump32 (code, 0);
}
} else {
if (ins->inst_target_bb->native_offset) {
break;
case OP_SIN:
x86_fsin (code);
+ x86_fldz (code);
+ x86_fp_op_reg (code, X86_FADD, 1, TRUE);
break;
case OP_COS:
x86_fcos (code);
+ x86_fldz (code);
+ x86_fp_op_reg (code, X86_FADD, 1, TRUE);
break;
case OP_ABS:
x86_fabs (code);
x86_fstp (code, 0); /* pop the 1.0 */
x86_patch (check_pos, code);
x86_patch (end_tan, code);
+ x86_fldz (code);
+ x86_fp_op_reg (code, X86_FADD, 1, TRUE);
x86_pop_reg (code, X86_EAX);
break;
}
case OP_ATAN:
x86_fld1 (code);
x86_fpatan (code);
+ x86_fldz (code);
+ x86_fp_op_reg (code, X86_FADD, 1, TRUE);
break;
case OP_SQRT:
x86_fsqrt (code);
void
mono_arch_register_lowlevel_calls (void)
{
- mono_register_jit_icall (mono_arch_get_lmf_addr, "mono_arch_get_lmf_addr", NULL, TRUE);
}
void
x86_mov_reg_membase (code, X86_EAX, X86_EAX, lmf_tls_offset, 4);
}
else {
-#ifdef HAVE_KW_THREAD
- mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
- (gpointer)"mono_arch_get_lmf_addr");
-#else
mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
(gpointer)"mono_get_lmf_addr");
-#endif
x86_call_code (code, 0);
}
max_offset += LOOP_ALIGNMENT;
while (ins) {
+ if (ins->opcode == OP_LABEL)
+ ins->inst_c1 = max_offset;
+
max_offset += ((guint8 *)ins_spec [ins->opcode])[MONO_INST_LEN];
ins = ins->next;
}
static gboolean tls_offset_inited = FALSE;
-#ifdef HAVE_KW_THREAD
-static __thread gpointer mono_lmf_addr;
-#endif
-
-static gpointer
-mono_arch_get_lmf_addr (void)
-{
-#ifdef HAVE_KW_THREAD
- return mono_lmf_addr;
-#else
- g_assert_not_reached ();
- return NULL;
-#endif
-}
-
void
mono_arch_setup_jit_tls_data (MonoJitTlsData *tls)
{
tls_offset_inited = TRUE;
+ code = (guint8*)mono_get_lmf_addr;
+
if (getenv ("MONO_NPTL")) {
/*
* Determine the offset of mono_lfm_addr inside the TLS structures
* by disassembling the function above.
*/
- code = (guint8*)&mono_arch_get_lmf_addr;
/* This is generated by gcc 3.3.2 */
if ((code [0] == 0x55) && (code [1] == 0x89) && (code [2] == 0xe5) &&
#else
#ifdef HAVE_PTHREAD_ATTR_GET_NP
pthread_attr_get_np( self, &attr );
+#elif defined(sun)
+ pthread_attr_init( &attr );
+ pthread_attr_getstacksize( &attr, &stsize );
#else
#error "Not implemented"
#endif
#endif
+#ifndef sun
pthread_attr_getstack( &attr, &staddr, &stsize );
+#endif
}
/*
sa.ss_flags = SS_ONSTACK;
sigaltstack (&sa, NULL);
#endif
-
-#ifdef HAVE_KW_THREAD
- mono_lmf_addr = &tls->lmf;
-#endif
}
void