-/*
- * mini-mips.c: MIPS backend for the Mono code generator
+/**
+ * \file
+ * MIPS backend for the Mono code generator
*
* Authors:
* Mark Mason (mason@broadcom.com)
#include <mono/metadata/appdomain.h>
#include <mono/metadata/debug-helpers.h>
#include <mono/utils/mono-mmap.h>
-#include <mono/utils/mono-hwcap-mips.h>
+#include <mono/utils/mono-hwcap.h>
+#include <mono/utils/unlocked.h>
#include <mono/arch/mips/mips-codegen.h>
static mono_mutex_t mini_arch_mutex;
int mono_exc_esp_offset = 0;
-static int tls_mode = TLS_MODE_DETECT;
-static int lmf_pthread_key = -1;
-static int monothread_key = -1;
/* Whenever the host is little-endian */
static int little_endian;
cfg->bb_exit->max_offset += 16; \
} while (0)
-
-#define emit_linuxthreads_tls(code,dreg,key) do {\
- int off1, off2; \
- off1 = offsets_from_pthread_key ((key), &off2); \
- g_assert_not_reached (); \
- ppc_lwz ((code), (dreg), off1, ppc_r2); \
- ppc_lwz ((code), (dreg), off2, (dreg)); \
- } while (0);
-
-
-#define emit_tls_access(code,dreg,key) do { \
- switch (tls_mode) { \
- case TLS_MODE_LTHREADS: emit_linuxthreads_tls(code,dreg,key); break; \
- default: g_assert_not_reached (); \
- } \
- } while (0)
-
#define MONO_EMIT_NEW_LOAD_R8(cfg,dr,addr) do { \
MonoInst *inst; \
MONO_INST_NEW ((cfg), (inst), OP_R8CONST); \
}
}
-#if 0
-static int
-offsets_from_pthread_key (guint32 key, int *offset2)
-{
- int idx1 = key / 32;
- int idx2 = key % 32;
- *offset2 = idx2 * sizeof (gpointer);
- return 284 + idx1 * sizeof (gpointer);
-}
-#endif
-
static void mono_arch_compute_omit_fp (MonoCompile *cfg);
const char*
{
mono_os_mutex_init_recursive (&mini_arch_mutex);
- ss_trigger_page = mono_valloc (NULL, mono_pagesize (), MONO_MMAP_READ|MONO_MMAP_32BIT);
- bp_trigger_page = mono_valloc (NULL, mono_pagesize (), MONO_MMAP_READ|MONO_MMAP_32BIT);
+ ss_trigger_page = mono_valloc (NULL, mono_pagesize (), MONO_MMAP_READ|MONO_MMAP_32BIT, MONO_MEM_ACCOUNT_OTHER);
+ bp_trigger_page = mono_valloc (NULL, mono_pagesize (), MONO_MMAP_READ|MONO_MMAP_32BIT, MONO_MEM_ACCOUNT_OTHER);
mono_mprotect (bp_trigger_page, mono_pagesize (), 0);
}
mono_os_mutex_destroy (&mini_arch_mutex);
}
+gboolean
+mono_arch_have_fast_tls (void)
+{
+ return FALSE;
+}
+
/*
* This function returns the optimizations supported on this cpu.
*/
DEBUG(printf("param %d: ", i));
simpletype = mini_get_underlying_type (sig->params [i]);
switch (simpletype->type) {
- case MONO_TYPE_BOOLEAN:
case MONO_TYPE_I1:
case MONO_TYPE_U1:
DEBUG(printf("1 byte\n"));
add_int32_arg (cinfo, &cinfo->args[n]);
n++;
break;
- case MONO_TYPE_CHAR:
case MONO_TYPE_I2:
case MONO_TYPE_U2:
DEBUG(printf("2 bytes\n"));
case MONO_TYPE_U:
case MONO_TYPE_PTR:
case MONO_TYPE_FNPTR:
- case MONO_TYPE_CLASS:
case MONO_TYPE_OBJECT:
- case MONO_TYPE_STRING:
- case MONO_TYPE_SZARRAY:
- case MONO_TYPE_ARRAY:
cinfo->args [n].size = sizeof (gpointer);
add_int32_arg (cinfo, &cinfo->args[n]);
n++;
{
simpletype = mini_get_underlying_type (sig->ret);
switch (simpletype->type) {
- case MONO_TYPE_BOOLEAN:
case MONO_TYPE_I1:
case MONO_TYPE_U1:
case MONO_TYPE_I2:
case MONO_TYPE_U2:
- case MONO_TYPE_CHAR:
case MONO_TYPE_I4:
case MONO_TYPE_U4:
case MONO_TYPE_I:
case MONO_TYPE_U:
case MONO_TYPE_PTR:
case MONO_TYPE_FNPTR:
- case MONO_TYPE_CLASS:
case MONO_TYPE_OBJECT:
- case MONO_TYPE_SZARRAY:
- case MONO_TYPE_ARRAY:
- case MONO_TYPE_STRING:
cinfo->ret.reg = mips_v0;
break;
case MONO_TYPE_U8:
/**
* mono_arch_compute_omit_fp:
- *
- * Determine whenever the frame pointer can be eliminated.
+ * Determine whether the frame pointer can be eliminated.
*/
static void
mono_arch_compute_omit_fp (MonoCompile *cfg)
cfg->arch.omit_fp = FALSE;
if (!sig->pinvoke && (sig->call_convention == MONO_CALL_VARARG))
cfg->arch.omit_fp = FALSE;
- if ((mono_jit_trace_calls != NULL && mono_trace_eval (cfg->method)) ||
- (cfg->prof_options & MONO_PROFILE_ENTER_LEAVE))
+ if ((mono_jit_trace_calls != NULL && mono_trace_eval (cfg->method)))
cfg->arch.omit_fp = FALSE;
/*
* On MIPS, fp points to the bottom of the frame, so it can be eliminated even if
soffset += SIZEOF_REGISTER;
}
if (ovf_size != 0) {
- mini_emit_memcpy (cfg, mips_sp, doffset, src->dreg, soffset, ovf_size * sizeof (gpointer), 0);
+ mini_emit_memcpy (cfg, mips_sp, doffset, src->dreg, soffset, ovf_size * sizeof (gpointer), SIZEOF_VOID_P);
}
} else if (ainfo->storage == ArgInFReg) {
int tmpr = mono_alloc_freg (cfg);
g_assert (ovf_size > 0);
EMIT_NEW_VARLOADA (cfg, load, vtcopy, vtcopy->inst_vtype);
- mini_emit_memcpy (cfg, load->dreg, 0, src->dreg, 0, size, 0);
+ mini_emit_memcpy (cfg, load->dreg, 0, src->dreg, 0, size, SIZEOF_VOID_P);
if (ainfo->offset)
MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, mips_at, ainfo->offset, load->dreg);
int tmp5 = -1;
switch (ins->opcode) {
-#if 0
- case OP_LCOMPARE:
- case OP_LCOMPARE_IMM:
- mono_print_ins (ins);
- g_assert_not_reached ();
-#endif
case OP_LADD:
tmp1 = mono_alloc_ireg (cfg);
MONO_EMIT_NEW_BIALU (cfg, OP_IADD, ins->dreg+1, ins->sreg1+1, ins->sreg2+1);
NULLIFY_INS(ins);
break;
- case OP_LMUL:
- case OP_LDIV:
- case OP_LDIV_UN:
- case OP_LREM:
- case OP_LREM_UN:
- case OP_LSHL:
- case OP_LSHR:
- case OP_LSHR_UN:
- mono_print_ins (ins);
- g_assert_not_reached ();
-
case OP_LNEG:
tmp1 = mono_alloc_ireg (cfg);
MONO_EMIT_NEW_BIALU (cfg, OP_ISUB, ins->dreg+1, mips_zero, ins->sreg1+1);
NULLIFY_INS(ins);
break;
-#if 0
- case OP_LNOT:
-#endif
-#if 0
- case OP_LCONV_TO_I1:
- case OP_LCONV_TO_I2:
- case OP_LCONV_TO_I4:
- case OP_LCONV_TO_I8:
- case OP_LCONV_TO_R4:
- case OP_LCONV_TO_R8:
- case OP_LCONV_TO_U4:
- case OP_LCONV_TO_U8:
- case OP_LCONV_TO_U2:
- case OP_LCONV_TO_U1:
- case OP_LCONV_TO_I:
- case OP_LCONV_TO_OVF_I:
- case OP_LCONV_TO_OVF_U:
-#endif
- mono_print_ins (ins);
- g_assert_not_reached ();
-
case OP_LADD_OVF:
tmp1 = mono_alloc_ireg (cfg);
tmp2 = mono_alloc_ireg (cfg);
NULLIFY_INS(ins);
break;
- case OP_LMUL_OVF:
- case OP_LMUL_OVF_UN:
- mono_print_ins (ins);
- g_assert_not_reached ();
-
case OP_LSUB_OVF:
tmp1 = mono_alloc_ireg (cfg);
tmp2 = mono_alloc_ireg (cfg);
MONO_EMIT_NEW_COMPARE_EXC (cfg, NE_UN, tmp2, mips_zero, "OverflowException");
NULLIFY_INS(ins);
break;
-#if 0
- case OP_LCONV_TO_OVF_I1_UN:
- case OP_LCONV_TO_OVF_I2_UN:
- case OP_LCONV_TO_OVF_I4_UN:
- case OP_LCONV_TO_OVF_I8_UN:
- case OP_LCONV_TO_OVF_U1_UN:
- case OP_LCONV_TO_OVF_U2_UN:
- case OP_LCONV_TO_OVF_U4_UN:
- case OP_LCONV_TO_OVF_U8_UN:
- case OP_LCONV_TO_OVF_I_UN:
- case OP_LCONV_TO_OVF_U_UN:
- case OP_LCONV_TO_OVF_I1:
- case OP_LCONV_TO_OVF_U1:
- case OP_LCONV_TO_OVF_I2:
- case OP_LCONV_TO_OVF_U2:
- case OP_LCONV_TO_OVF_I4:
- case OP_LCONV_TO_OVF_U4:
- case OP_LCONV_TO_OVF_I8:
- case OP_LCONV_TO_OVF_U8:
-#endif
- case OP_LCEQ:
- case OP_LCGT:
- case OP_LCGT_UN:
- case OP_LCLT:
- case OP_LCLT_UN:
-#if 0
- case OP_LCONV_TO_R_UN:
- case OP_LCONV_TO_U:
-#endif
- case OP_LMUL_IMM:
- case OP_LSHL_IMM:
- case OP_LSHR_IMM:
- case OP_LSHR_UN_IMM:
- case OP_LDIV_IMM:
- case OP_LDIV_UN_IMM:
- case OP_LREM_IMM:
- case OP_LREM_UN_IMM:
- case OP_LBEQ:
- case OP_LBGE:
- case OP_LBGT:
- case OP_LBLE:
- case OP_LBLT:
- case OP_LBNE_UN:
- case OP_LBGE_UN:
- case OP_LBGT_UN:
- case OP_LBLE_UN:
- case OP_LBLT_UN:
- mono_print_ins (ins);
- g_assert_not_reached ();
-#if 0
- case OP_LCONV_TO_R8_2:
- case OP_LCONV_TO_R4_2:
- case OP_LCONV_TO_R_UN_2:
-#endif
case OP_LCONV_TO_OVF_I4_2:
tmp1 = mono_alloc_ireg (cfg);
MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, ins->dreg, ins->sreg1);
NULLIFY_INS(ins);
break;
-
- case OP_LMIN_UN:
- case OP_LMAX_UN:
- case OP_LMIN:
- case OP_LMAX:
- mono_print_ins (ins);
- g_assert_not_reached ();
-
default:
break;
}
cpos = bb->max_offset;
-#if 0
- if (cfg->prof_options & MONO_PROFILE_COVERAGE) {
- MonoCoverageInfo *cov = mono_get_coverage_info (cfg->method);
- g_assert (!mono_compile_aot);
- cpos += 20;
- if (bb->cil_code)
- cov->data [bb->dfn].iloffset = bb->cil_code - cfg->cil_code;
- /* this is not thread save, but good enough */
- /* fixme: howto handle overflows? */
- mips_load_const (code, mips_at, &cov->data [bb->dfn].count);
- mips_lw (code, mips_temp, mips_at, 0);
- mips_addiu (code, mips_temp, mips_temp, 1);
- mips_sw (code, mips_temp, mips_at, 0);
- }
-#endif
MONO_BB_FOR_EACH_INS (bb, ins) {
offset = code - cfg->native_code;
mips_nop (code);
break;
}
- case OP_TLS_GET:
- g_assert_not_reached();
-#if 0
- emit_tls_access (code, ins->dreg, ins->inst_offset);
-#endif
- break;
case OP_BIGMUL:
mips_mult (code, ins->sreg1, ins->sreg2);
mips_mflo (code, ins->dreg);
{
MonoJumpInfo *patch_info;
- mono_error_init (error);
+ error_init (error);
for (patch_info = ji; patch_info; patch_info = patch_info->next) {
unsigned char *ip = patch_info->ip.i + code;
MonoInst *ins = bb->code;
bb->max_offset = max_offset;
- if (cfg->prof_options & MONO_PROFILE_COVERAGE)
- max_offset += 6;
-
MONO_BB_FOR_EACH_INS (bb, ins)
max_offset += ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
}
mips_load_const (code, mips_at, MIPS_LMF_MAGIC1);
mips_sw (code, mips_at, mips_sp, lmf_offset + G_STRUCT_OFFSET(MonoLMF, magic));
- if (lmf_pthread_key != -1) {
- g_assert_not_reached();
-#if 0
- emit_tls_access (code, mips_temp, lmf_pthread_key);
-#endif
- if (G_STRUCT_OFFSET (MonoJitTlsData, lmf)) {
- int offset = G_STRUCT_OFFSET (MonoJitTlsData, lmf);
- g_assert (mips_is_imm16(offset));
- mips_addiu (code, mips_a0, mips_temp, offset);
- }
- } else {
- /* This can/will clobber the a0-a3 registers */
- mips_call (code, mips_t9, (gpointer)mono_get_lmf_addr);
- }
+ /* This can/will clobber the a0-a3 registers */
+ mips_call (code, mips_t9, (gpointer)mono_get_lmf_addr);
/* mips_v0 is the result from mono_get_lmf_addr () (MonoLMF **) */
g_assert (mips_is_imm16(lmf_offset + G_STRUCT_OFFSET(MonoLMF, lmf_addr)));
if (mono_jit_trace_calls != NULL)
max_epilog_size += 50;
- if (cfg->prof_options & MONO_PROFILE_ENTER_LEAVE)
- max_epilog_size += 50;
-
if (code)
pos = code - cfg->native_code;
while (cfg->code_len + max_epilog_size > (cfg->code_size - 16)) {
#endif
}
-/*
- * Thread local storage support
- */
-static void
-setup_tls_access (void)
-{
- guint32 ptk;
- //guint32 *ins, *code;
-
- if (tls_mode == TLS_MODE_FAILED)
- return;
-
- if (g_getenv ("MONO_NO_TLS")) {
- tls_mode = TLS_MODE_FAILED;
- return;
- }
-
- if (tls_mode == TLS_MODE_DETECT) {
- /* XXX */
- tls_mode = TLS_MODE_FAILED;
- return;
-#if 0
-
- ins = (guint32*)pthread_getspecific;
- /* uncond branch to the real method */
- if ((*ins >> 26) == 18) {
- gint32 val;
- val = (*ins & ~3) << 6;
- val >>= 6;
- if (*ins & 2) {
- /* absolute */
- ins = (guint32*)val;
- } else {
- ins = (guint32*) ((char*)ins + val);
- }
- }
- code = &cmplwi_1023;
- ppc_cmpli (code, 0, 0, ppc_r3, 1023);
- code = &li_0x48;
- ppc_li (code, ppc_r4, 0x48);
- code = &blr_ins;
- ppc_blr (code);
- if (*ins == cmplwi_1023) {
- int found_lwz_284 = 0;
- for (ptk = 0; ptk < 20; ++ptk) {
- ++ins;
- if (!*ins || *ins == blr_ins)
- break;
- if ((guint16)*ins == 284 && (*ins >> 26) == 32) {
- found_lwz_284 = 1;
- break;
- }
- }
- if (!found_lwz_284) {
- tls_mode = TLS_MODE_FAILED;
- return;
- }
- tls_mode = TLS_MODE_LTHREADS;
- } else if (*ins == li_0x48) {
- ++ins;
- /* uncond branch to the real method */
- if ((*ins >> 26) == 18) {
- gint32 val;
- val = (*ins & ~3) << 6;
- val >>= 6;
- if (*ins & 2) {
- /* absolute */
- ins = (guint32*)val;
- } else {
- ins = (guint32*) ((char*)ins + val);
- }
- code = &val;
- ppc_li (code, ppc_r0, 0x7FF2);
- if (ins [1] == val) {
- /* Darwin on G4, implement */
- tls_mode = TLS_MODE_FAILED;
- return;
- } else {
- code = &val;
- ppc_mfspr (code, ppc_r3, 104);
- if (ins [1] != val) {
- tls_mode = TLS_MODE_FAILED;
- return;
- }
- tls_mode = TLS_MODE_DARWIN_G5;
- }
- } else {
- tls_mode = TLS_MODE_FAILED;
- return;
- }
- } else {
- tls_mode = TLS_MODE_FAILED;
- return;
- }
-#endif
- }
- if (lmf_pthread_key == -1) {
- ptk = mono_jit_tls_id;
- if (ptk < 1024) {
- /*g_print ("MonoLMF at: %d\n", ptk);*/
- /*if (!try_offset_access (mono_get_lmf_addr (), ptk)) {
- init_tls_failed = 1;
- return;
- }*/
- lmf_pthread_key = ptk;
- }
- }
- if (monothread_key == -1) {
- ptk = mono_thread_get_tls_key ();
- if (ptk < 1024) {
- monothread_key = ptk;
- /*g_print ("thread inited: %d\n", ptk);*/
- } else {
- /*g_print ("thread not inited yet %d\n", ptk);*/
- }
- }
-}
-
void
mono_arch_finish_init (void)
{
- setup_tls_access ();
}
void
return NULL;
}
-gboolean
-mono_arch_print_tree (MonoInst *tree, int arity)
-{
- return 0;
-}
-
mgreg_t
mono_arch_context_get_int_reg (MonoContext *ctx, int reg)
{
* LOCKING: called with the domain lock held
*/
gpointer
-mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckItem **imt_entries, int count,
- gpointer fail_tramp)
+mono_arch_build_imt_trampoline (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckItem **imt_entries, int count,
+ gpointer fail_tramp)
{
int i;
int size = 0;
/* the initial load of the vtable address */
size += MIPS_LOAD_SEQUENCE_LENGTH;
if (fail_tramp) {
- code = mono_method_alloc_generic_virtual_thunk (domain, size);
+ code = mono_method_alloc_generic_virtual_trampoline (domain, size);
} else {
code = mono_domain_code_reserve (domain, size);
}
}
if (!fail_tramp)
- mono_stats.imt_thunks_size += code - start;
+ UnlockedAdd (&mono_stats.imt_trampolines_size, code - start);
g_assert (code - start <= size);
mono_arch_flush_icache (start, size);