#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/arch/mips/mips-codegen.h>
#include "ir-emit.h"
#define SAVE_FP_REGS 0
-#define EXTRA_STACK_SPACE 0 /* suppresses some s-reg corruption issues */
-#define ALWAYS_USE_FP 1
#define ALWAYS_SAVE_RA 1 /* call-handler & switch currently clobber ra */
#define PROMOTE_R4_TO_R8 1 /* promote single values in registers to doubles */
-#define USE_MUL 1 /* use mul instead of mult/mflo for multiply */
+#define USE_MUL 0 /* use mul instead of mult/mflo for multiply
+ remember to update cpu-mips.md if you change this */
/* Emit a call sequence to 'v', using 'D' as a scratch register if necessary */
#define mips_call(c,D,v) do { \
static int tls_mode = TLS_MODE_DETECT;
static int lmf_pthread_key = -1;
static int monothread_key = -1;
-static int monodomain_key = -1;
/* Whenever the host is little-endian */
static int little_endian;
* Returns the size of the activation frame.
*/
int
-mono_arch_get_argument_info (MonoMethodSignature *csig, int param_count, MonoJitArgumentInfo *arg_info)
+mono_arch_get_argument_info (MonoGenericSharingContext *gsctx, MonoMethodSignature *csig, int param_count, MonoJitArgumentInfo *arg_info)
{
int k, frame_size = 0;
guint32 size, align, pad;
guint8 *code;
guint32 code_len;
int i;
+ char *tramp_name;
code = get_delegate_invoke_impl (TRUE, 0, &code_len);
- res = g_slist_prepend (res, mono_tramp_info_create (g_strdup ("delegate_invoke_impl_has_target"), code, code_len, NULL, NULL));
+ res = g_slist_prepend (res, mono_tramp_info_create ("delegate_invoke_impl_has_target", code, code_len, NULL, NULL));
for (i = 0; i <= MAX_ARCH_DELEGATE_PARAMS; ++i) {
code = get_delegate_invoke_impl (FALSE, i, &code_len);
- res = g_slist_prepend (res, mono_tramp_info_create (g_strdup_printf ("delegate_invoke_impl_target_%d", i), code, code_len, NULL, NULL));
+ tramp_name = g_strdup_printf ("delegate_invoke_impl_target_%d", i);
+ res = g_slist_prepend (res, mono_tramp_info_create (tramp_name, code, code_len, NULL, NULL));
+ g_free (tramp_name);
}
return res;
* This function returns the optimizations supported on this cpu.
*/
guint32
-mono_arch_cpu_optimizazions (guint32 *exclude_mask)
+mono_arch_cpu_optimizations (guint32 *exclude_mask)
{
guint32 opts = 0;
return opts;
}
+/*
+ * This function test for all SIMD functions supported.
+ *
+ * Returns a bitmask corresponding to all supported versions.
+ *
+ */
+guint32
+mono_arch_cpu_enumerate_simd_versions (void)
+{
+ /* SIMD is currently unimplemented */
+ return 0;
+}
+
GList *
mono_arch_get_allocatable_int_vars (MonoCompile *cfg)
{
* are sometimes made using calli without sig->hasthis set, like in the delegate
* invoke wrappers.
*/
- if (cinfo->vtype_retaddr && !is_pinvoke && (sig->hasthis || (sig->param_count > 0 && MONO_TYPE_IS_REFERENCE (mini_type_get_underlying_type (NULL, sig->params [0]))))) {
+ if (cinfo->vtype_retaddr && !is_pinvoke && (sig->hasthis || (sig->param_count > 0 && MONO_TYPE_IS_REFERENCE (mini_type_get_underlying_type (gsctx, sig->params [0]))))) {
if (sig->hasthis) {
add_int32_arg (cinfo, cinfo->args + n);
n ++;
add_int32_arg (cinfo, &cinfo->sig_cookie);
}
DEBUG(printf("param %d: ", i));
- simpletype = mini_type_get_underlying_type (NULL, sig->params [i]);
+ simpletype = mini_type_get_underlying_type (gsctx, sig->params [i]);
switch (simpletype->type) {
case MONO_TYPE_BOOLEAN:
case MONO_TYPE_I1:
}
{
- simpletype = mono_type_get_underlying_type (sig->ret);
+ simpletype = mini_type_get_underlying_type (gsctx, sig->ret);
switch (simpletype->type) {
case MONO_TYPE_BOOLEAN:
case MONO_TYPE_I1:
return cinfo;
}
-G_GNUC_UNUSED static void
-break_count (void)
-{
-}
-
-G_GNUC_UNUSED static gboolean
-debug_count (void)
-{
- static int count = 0;
- count ++;
-
- if (!getenv ("COUNT"))
- return TRUE;
-
- if (count == atoi (getenv ("COUNT"))) {
- break_count ();
- }
-
- if (count > atoi (getenv ("COUNT"))) {
- return FALSE;
- }
-
- return TRUE;
-}
-
static gboolean
debug_omit_fp (void)
{
#if 0
- return debug_count ();
+ return mono_debug_count ();
#else
return TRUE;
#endif
curinst = 0;
if (!MONO_TYPE_ISSTRUCT (sig->ret)) {
/* FIXME: handle long and FP values */
- switch (mono_type_get_underlying_type (sig->ret)->type) {
+ switch (mini_type_get_underlying_type (cfg->generic_sharing_context, sig->ret)->type) {
case MONO_TYPE_VOID:
break;
case MONO_TYPE_R4:
offset += size;
}
- /*
- * FIXME: - Saved S-regs seem to be getting clobbered by some calls with struct
- * args or return vals. Extra stack space avoids this in a lot of cases.
- */
- offset += EXTRA_STACK_SPACE;
offset += SIZEOF_REGISTER - 1;
offset &= ~(SIZEOF_REGISTER - 1);
mips_addiu (code, ins->dreg, mips_sp, area_offset);
if (ins->flags & MONO_INST_INIT) {
+ guint32 *buf;
+
+ buf = (guint32*)(void*)code;
+ mips_beq (code, mips_at, mips_zero, 0);
+ mips_nop (code);
+
mips_move (code, mips_temp, ins->dreg);
mips_sb (code, mips_zero, mips_temp, 0);
mips_addiu (code, mips_at, mips_at, -1);
mips_bne (code, mips_at, mips_zero, -3);
mips_addiu (code, mips_temp, mips_temp, 1);
+
+ mips_patch (buf, (guint32)code);
}
break;
}
}
}
-#if 0
-static
-void
-mono_trace_lmf_prolog (MonoLMF *new_lmf)
-{
-}
-
-static
-void
-mono_trace_lmf_epilog (MonoLMF *old_lmf)
-{
-}
-#endif
-
/*
* Allow tracing to work with this interface (with an optional argument)
*
mips_nop (code);
mips_nop (code);
- /* For N32, need to know for each stack slot if it's an integer
- * or float argument, and save/restore the appropriate register
- */
MIPS_SW (code, mips_a0, mips_sp, offset + 0*SIZEOF_REGISTER);
MIPS_SW (code, mips_a1, mips_sp, offset + 1*SIZEOF_REGISTER);
MIPS_SW (code, mips_a2, mips_sp, offset + 2*SIZEOF_REGISTER);
MIPS_SW (code, mips_a3, mips_sp, offset + 3*SIZEOF_REGISTER);
#if _MIPS_SIM == _ABIN32
+ NOT_IMPLEMENTED;
+ /* FIXME: Need a separate region for these */
MIPS_SW (code, mips_a4, mips_sp, offset + 4*SIZEOF_REGISTER);
MIPS_SW (code, mips_a5, mips_sp, offset + 5*SIZEOF_REGISTER);
MIPS_SW (code, mips_a6, mips_sp, offset + 6*SIZEOF_REGISTER);
MIPS_SW (code, mips_a7, mips_sp, offset + 7*SIZEOF_REGISTER);
+ */
#endif
mips_load_const (code, mips_a0, cfg->method);
mips_addiu (code, mips_a1, mips_sp, offset);
mips_call (code, mips_t9, func);
+ mips_nop (code);
MIPS_LW (code, mips_a0, mips_sp, offset + 0*SIZEOF_REGISTER);
MIPS_LW (code, mips_a1, mips_sp, offset + 1*SIZEOF_REGISTER);
MIPS_LW (code, mips_a2, mips_sp, offset + 2*SIZEOF_REGISTER);
MIPS_LW (code, mips_a3, mips_sp, offset + 3*SIZEOF_REGISTER);
#if _MIPS_SIM == _ABIN32
+ NOT_IMPLEMENTED;
+ /*
MIPS_LW (code, mips_a4, mips_sp, offset + 4*SIZEOF_REGISTER);
MIPS_LW (code, mips_a5, mips_sp, offset + 5*SIZEOF_REGISTER);
MIPS_LW (code, mips_a6, mips_sp, offset + 6*SIZEOF_REGISTER);
MIPS_LW (code, mips_a7, mips_sp, offset + 7*SIZEOF_REGISTER);
+ */
#endif
mips_nop (code);
if (max_offset > 0xffff)
cfg->arch.long_branch = TRUE;
- if (tracing) {
-#if _MIPS_SIM == _ABIO32
- cfg->arch.tracing_offset = cfg->stack_offset;
-#elif _MIPS_SIM == _ABIN32
- /* no stack slots by default for argument regs, reserve a special block */
- cfg->arch.tracing_offset = cfg->stack_offset;
- cfg->stack_offset += 8 * SIZEOF_REGISTER;
-#endif
- }
-
/*
* Currently, fp points to the bottom of the frame on MIPS, unlike other platforms.
* This means that we have to adjust the offsets inside instructions which reference
}
}
- /* Do instrumentation before assigning regvars to registers. Because they may be assigned
- * to the t* registers, which would be clobbered by the instrumentation calls.
- */
- if (tracing) {
- code = mono_arch_instrument_prolog (cfg, mono_trace_enter_method, code, TRUE);
- }
+ /* store runtime generic context */
+ if (cfg->rgctx_var) {
+ MonoInst *ins = cfg->rgctx_var;
+ g_assert (ins->opcode == OP_REGOFFSET);
+
+ g_assert (mips_is_imm16 (ins->inst_offset));
+ mips_sw (code, MONO_ARCH_RGCTX_REG, ins->inst_basereg, ins->inst_offset);
+ }
/* load arguments allocated to register from the stack */
pos = 0;
pos++;
}
- if (method->wrapper_type == MONO_WRAPPER_NATIVE_TO_MANAGED) {
- mips_load_const (code, mips_a0, cfg->domain);
- mips_call (code, mips_t9, (gpointer)mono_jit_thread_attach);
- }
-
if (method->save_lmf) {
mips_load_const (code, mips_at, MIPS_LMF_MAGIC1);
mips_sw (code, mips_at, mips_sp, lmf_offset + G_STRUCT_OFFSET(MonoLMF, magic));
mono_emit_unwind_op_def_cfa_offset (cfg, code, cfa_offset);
}
+ if (tracing) {
+#if _MIPS_SIM == _ABIO32
+ cfg->arch.tracing_offset = cfg->stack_offset;
+#elif _MIPS_SIM == _ABIN32
+ /* no stack slots by default for argument regs, reserve a special block */
+ g_assert_not_reached ();
+#endif
+ code = mono_arch_instrument_prolog (cfg, mono_trace_enter_method, code, TRUE);
+ }
+
cfg->code_len = code - cfg->native_code;
g_assert (cfg->code_len < cfg->code_size);
int save_mode = SAVE_NONE;
int offset;
MonoMethod *method = cfg->method;
- int rtype = mono_type_get_underlying_type (mono_method_signature (method)->ret)->type;
+ int rtype = mini_type_get_underlying_type (cfg->generic_sharing_context, mono_method_signature (method)->ret)->type;
int save_offset = MIPS_STACK_PARAM_OFFSET;
g_assert ((save_offset & (MIPS_STACK_ALIGNMENT-1)) == 0);
}
#endif
}
- if (monodomain_key == -1) {
- ptk = mono_domain_get_tls_key ();
- if (ptk < 1024)
- monodomain_key = ptk;
- }
if (lmf_pthread_key == -1) {
ptk = mono_jit_tls_id;
if (ptk < 1024) {
}
void
-mono_arch_setup_jit_tls_data (MonoJitTlsData *tls)
+mono_arch_finish_init (void)
{
setup_tls_access ();
}
return 0;
}
-MonoInst* mono_arch_get_domain_intrinsic (MonoCompile* cfg)
-{
- MonoInst* ins;
-
- setup_tls_access ();
- if (monodomain_key == -1)
- return NULL;
-
- MONO_INST_NEW (cfg, ins, OP_TLS_GET);
- ins->inst_offset = monodomain_key;
- return ins;
-}
-
mgreg_t
mono_arch_context_get_int_reg (MonoContext *ctx, int reg)
{
MonoVTable*
mono_arch_find_static_call_vtable (mgreg_t *regs, guint8 *code)
{
- NOT_IMPLEMENTED;
return (MonoVTable*) regs [MONO_ARCH_RGCTX_REG];
}
return NULL;
}
+void
+mono_arch_init_lmf_ext (MonoLMFExt *ext, gpointer prev_lmf)
+{
+ ext->lmf.previous_lmf = prev_lmf;
+ /* Mark that this is a MonoLMFExt */
+ ext->lmf.previous_lmf = (gpointer)(((gssize)ext->lmf.previous_lmf) | 2);
+ ext->lmf.iregs [mips_sp] = (gssize)ext;
+}
+
#endif /* MONO_ARCH_SOFT_DEBUG_SUPPORTED */