-/*
- * mini-arm.c: ARM backend for the Mono code generator
+/**
+ * \file
+ * ARM backend for the Mono code generator
*
* Authors:
* Paolo Molaro (lupus@ximian.com)
static int i8_align;
static gpointer single_step_tramp, breakpoint_tramp;
-static gpointer get_tls_tramp;
/*
* The code generated for sequence points reads from this location, which is
return code;
}
+static guint8*
+emit_ldr_imm (guint8 *code, int dreg, int sreg, int imm)
+{
+ if (!arm_is_imm12 (imm)) {
+ g_assert (dreg != sreg);
+ code = emit_big_add (code, dreg, sreg, imm);
+ ARM_LDR_IMM (code, dreg, dreg, 0);
+ } else {
+ ARM_LDR_IMM (code, dreg, sreg, imm);
+ }
+ return code;
+}
+
/* If dreg == sreg, this clobbers IP */
static guint8*
emit_sub_imm (guint8 *code, int dreg, int sreg, int imm)
return code;
}
-#if defined(__ARM_EABI__) && defined(__linux__) && !defined(PLATFORM_ANDROID) && !defined(__native_client__)
+#if defined(__ARM_EABI__) && defined(__linux__) && !defined(PLATFORM_ANDROID) && !defined(MONO_CROSS_COMPILE)
#define HAVE_AEABI_READ_TP 1
#endif
#ifdef HAVE_AEABI_READ_TP
static gboolean have_fast_tls = FALSE;
static gboolean inited = FALSE;
- gpointer tp1, tp2;
if (mini_get_debug_options ()->use_fallback_tls)
return FALSE;
if (inited)
return have_fast_tls;
- tp1 = __aeabi_read_tp ();
- asm volatile("mrc p15, 0, %0, c13, c0, 3" : "=r" (tp2));
+ if (v7_supported) {
+ gpointer tp1, tp2;
- have_fast_tls = tp1 && tp1 == tp2;
+ tp1 = __aeabi_read_tp ();
+ asm volatile("mrc p15, 0, %0, c13, c0, 3" : "=r" (tp2));
+
+ have_fast_tls = tp1 && tp1 == tp2;
+ }
inited = TRUE;
return have_fast_tls;
#else
static guint8*
emit_tls_get (guint8 *code, int dreg, int tls_offset)
{
+ g_assert (v7_supported);
ARM_MRC (code, 15, 0, dreg, 13, 0, 3);
ARM_LDR_IMM (code, dreg, dreg, tls_offset);
return code;
emit_tls_set (guint8 *code, int sreg, int tls_offset)
{
int tp_reg = (sreg != ARMREG_R0) ? ARMREG_R0 : ARMREG_R1;
+ g_assert (v7_supported);
ARM_MRC (code, 15, 0, tp_reg, 13, 0, 3);
ARM_STR_IMM (code, sreg, tp_reg, tls_offset);
return code;
void
mono_arch_init (void)
{
- const char *cpu_arch;
+ char *cpu_arch;
#ifdef TARGET_WATCHOS
mini_get_debug_options ()->soft_breakpoints = TRUE;
mono_aot_register_jit_icall ("mono_arm_start_gsharedvt_call", mono_arm_start_gsharedvt_call);
#endif
mono_aot_register_jit_icall ("mono_arm_unaligned_stack", mono_arm_unaligned_stack);
-
+ mono_aot_register_jit_icall ("mono_arm_handler_block_trampoline_helper", mono_arm_handler_block_trampoline_helper);
#if defined(__ARM_EABI__)
eabi_supported = TRUE;
#endif
* works. Most ARM devices have VFP units these days, so
* normally soft float code would not be exercised much.
*/
- const char *soft = g_getenv ("MONO_ARM_FORCE_SOFT_FLOAT");
+ char *soft = g_getenv ("MONO_ARM_FORCE_SOFT_FLOAT");
if (soft && !strncmp (soft, "1", 1))
arm_fpu = MONO_ARM_FPU_NONE;
+ g_free (soft);
#endif
#endif
thumb_supported = strstr (cpu_arch, "thumb") != NULL;
thumb2_supported = strstr (cpu_arch, "thumb2") != NULL;
+ g_free (cpu_arch);
}
}
case MONO_TYPE_FNPTR:
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))
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.storage = RegTypeGeneral;
cinfo->ret.reg = ARMREG_R0;
break;
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_general (&gr, &stack_size, ainfo, TRUE);
break;
/**
* 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;
for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
ArgInfo *ainfo = &cinfo->args [i];
lainfo->nslots = ainfo->struct_size / sizeof (gpointer);
lainfo->esize = 4;
}
-
- printf ("D: %d\n", ainfo->align);
break;
case RegTypeStructByAddr:
case RegTypeStructByAddrOnStack:
}
switch (t->type) {
- case MONO_TYPE_STRING:
- case MONO_TYPE_CLASS:
- case MONO_TYPE_ARRAY:
- case MONO_TYPE_SZARRAY:
case MONO_TYPE_OBJECT:
case MONO_TYPE_PTR:
case MONO_TYPE_I:
case MONO_TYPE_VOID:
*(gpointer*)ret = NULL;
break;
- case MONO_TYPE_STRING:
- case MONO_TYPE_CLASS:
- case MONO_TYPE_ARRAY:
- case MONO_TYPE_SZARRAY:
case MONO_TYPE_OBJECT:
case MONO_TYPE_I:
case MONO_TYPE_U:
return thumb_supported;
}
+gboolean
+mono_arm_eabi_supported (void)
+{
+ return eabi_supported;
+}
+
+int
+mono_arm_i8_align (void)
+{
+ return i8_align;
+}
+
#ifndef DISABLE_JIT
static guint8*
if (cfg->compile_aot) {
g_assert (info_var);
g_assert (info_var->opcode == OP_REGOFFSET);
- g_assert (arm_is_imm12 (info_var->inst_offset));
}
if (!cfg->soft_breakpoints && !cfg->compile_aot) {
var = ss_method_var;
g_assert (var);
g_assert (var->opcode == OP_REGOFFSET);
- g_assert (arm_is_imm12 (var->inst_offset));
- ARM_LDR_IMM (code, dreg, var->inst_basereg, var->inst_offset);
-
+ code = emit_ldr_imm (code, dreg, var->inst_basereg, var->inst_offset);
/* Read the value and check whether it is non-zero. */
ARM_LDR_IMM (code, dreg, dreg, 0);
ARM_CMP_REG_IMM (code, dreg, 0, 0);
var = ss_trigger_page_var;
g_assert (var);
g_assert (var->opcode == OP_REGOFFSET);
- g_assert (arm_is_imm12 (var->inst_offset));
- ARM_LDR_IMM (code, dreg, var->inst_basereg, var->inst_offset);
+ code = emit_ldr_imm (code, dreg, var->inst_basereg, var->inst_offset);
} else {
ARM_LDR_IMM (code, dreg, ARMREG_PC, 0);
ARM_B (code, 0);
guint32 offset = code - cfg->native_code;
guint32 val;
- ARM_LDR_IMM (code, dreg, info_var->inst_basereg, info_var->inst_offset);
+ var = info_var;
+ code = emit_ldr_imm (code, dreg, var->inst_basereg, var->inst_offset);
/* Add the offset */
val = ((offset / 4) * sizeof (guint8*)) + MONO_STRUCT_OFFSET (SeqPointInfo, bp_addrs);
/* Load the info->bp_addrs [offset], which is either 0 or the address of a trigger page */
if (info_var) {
g_assert (info_var->opcode == OP_REGOFFSET);
- g_assert (arm_is_imm12 (info_var->inst_offset));
- ARM_LDR_IMM (code, dreg, info_var->inst_basereg, info_var->inst_offset);
+ code = emit_ldr_imm (code, dreg, info_var->inst_basereg, info_var->inst_offset);
/* Load the trigger page addr */
ARM_LDR_IMM (code, dreg, dreg, MONO_STRUCT_OFFSET (SeqPointInfo, ss_trigger_page));
ARM_STR_IMM (code, dreg, ss_trigger_page_var->inst_basereg, ss_trigger_page_var->inst_offset);
if (mono_jit_trace_calls != NULL)
max_epilog_size += 50;
- if (cfg->prof_options & MONO_PROFILE_ENTER_LEAVE)
- max_epilog_size += 50;
-
while (cfg->code_len + max_epilog_size > (cfg->code_size - 16)) {
cfg->code_size *= 2;
cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
ARM_LDR_REG_REG (code, dreg, ARMREG_PC, dreg);
return code;
}
+
+guint8*
+mono_arm_emit_aotconst (gpointer ji_list, guint8 *code, guint8 *buf, int dreg, int patch_type, gconstpointer data)
+{
+ MonoJumpInfo **ji = (MonoJumpInfo**)ji_list;
+
+ *ji = mono_patch_info_list_prepend (*ji, code - buf, patch_type, data);
+ ARM_LDR_IMM (code, dreg, ARMREG_PC, 0);
+ ARM_B (code, 0);
+ *(gpointer*)code = NULL;
+ code += 4;
+ ARM_LDR_REG_REG (code, dreg, ARMREG_PC, dreg);
+ return code;
+}