-/*
- * mini-arm.c: ARM backend for the Mono code generator
+/**
+ * \file
+ * ARM backend for the Mono code generator
*
* Authors:
* Paolo Molaro (lupus@ximian.com)
return code;
}
+#if defined(__ARM_EABI__) && defined(__linux__) && !defined(PLATFORM_ANDROID) && !defined(__native_client__)
+#define HAVE_AEABI_READ_TP 1
+#endif
+
+#ifdef HAVE_AEABI_READ_TP
+gpointer __aeabi_read_tp (void);
+#endif
+
gboolean
mono_arch_have_fast_tls (void)
{
+#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));
+
+ have_fast_tls = tp1 && tp1 == tp2;
+ inited = TRUE;
+ return have_fast_tls;
+#else
return FALSE;
+#endif
+}
+
+static guint8*
+emit_tls_get (guint8 *code, int dreg, int tls_offset)
+{
+ ARM_MRC (code, 15, 0, dreg, 13, 0, 3);
+ ARM_LDR_IMM (code, dreg, dreg, tls_offset);
+ return code;
+}
+
+static guint8*
+emit_tls_set (guint8 *code, int sreg, int tls_offset)
+{
+ int tp_reg = (sreg != ARMREG_R0) ? ARMREG_R0 : ARMREG_R1;
+ ARM_MRC (code, 15, 0, tp_reg, 13, 0, 3);
+ ARM_STR_IMM (code, sreg, tp_reg, tls_offset);
+ return code;
}
/*
{
int i;
- mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
- (gpointer)"mono_get_lmf_addr");
- code = emit_call_seq (cfg, code);
+ if (mono_arch_have_fast_tls () && mono_tls_get_tls_offset (TLS_KEY_LMF_ADDR) != -1) {
+ code = emit_tls_get (code, ARMREG_R0, mono_tls_get_tls_offset (TLS_KEY_LMF_ADDR));
+ } else {
+ mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
+ (gpointer)"mono_tls_get_lmf_addr");
+ code = emit_call_seq (cfg, code);
+ }
/* we build the MonoLMF structure on the stack - see mini-arm.h */
/* lmf_offset is the offset from the previous stack pointer,
* alloc_size is the total stack space allocated, so the offset
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
#else
arm_fpu = MONO_ARM_FPU_VFP;
-#if defined(ARM_FPU_NONE) && !defined(__APPLE__)
+#if defined(ARM_FPU_NONE) && !defined(TARGET_IOS)
/*
* If we're compiling with a soft float fallback and it
* turns out that no VFP unit is available, we need to
v7_supported = TRUE;
#endif
-#if defined(__APPLE__)
+#if defined(TARGET_IOS)
/* iOS is special-cased here because we don't yet
have a way to properly detect CPU features on it. */
thumb_supported = TRUE;
nwords = (align_size + sizeof (gpointer) -1 ) / sizeof (gpointer);
ainfo->storage = RegTypeStructByVal;
ainfo->struct_size = size;
+ ainfo->align = align;
/* FIXME: align stack_size if needed */
if (eabi_supported) {
if (align >= 8 && (gr & 1))
/**
* 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)
linfo->ret.nslots = cinfo->ret.nregs;
break;
#endif
+ case RegTypeHFA:
+ linfo->ret.storage = LLVMArgFpStruct;
+ linfo->ret.nslots = cinfo->ret.nregs;
+ linfo->ret.esize = cinfo->ret.esize;
+ break;
default:
cfg->exception_message = g_strdup_printf ("unknown ret conv (%d)", cinfo->ret.storage);
cfg->disable_llvm = TRUE;
break;
case RegTypeStructByVal:
lainfo->storage = LLVMArgAsIArgs;
- lainfo->nslots = ainfo->struct_size / sizeof (gpointer);
+ if (eabi_supported && ainfo->align == 8) {
+ /* LLVM models this by passing an int64 array */
+ lainfo->nslots = ALIGN_TO (ainfo->struct_size, 8) / 8;
+ lainfo->esize = 8;
+ } else {
+ lainfo->nslots = ainfo->struct_size / sizeof (gpointer);
+ lainfo->esize = 4;
+ }
+
+ printf ("D: %d\n", ainfo->align);
break;
case RegTypeStructByAddr:
case RegTypeStructByAddrOnStack:
lainfo->storage = LLVMArgVtypeByRef;
break;
+ case RegTypeHFA: {
+ int j;
+
+ lainfo->storage = LLVMArgAsFpArgs;
+ lainfo->nslots = ainfo->nregs;
+ lainfo->esize = ainfo->esize;
+ for (j = 0; j < ainfo->nregs; ++j)
+ lainfo->pair_storage [j] = LLVMArgInFPReg;
+ break;
+ }
default:
cfg->exception_message = g_strdup_printf ("ainfo->storage (%d)", ainfo->storage);
cfg->disable_llvm = TRUE;
ARM_MCR (code, 15, 0, ARMREG_R0, 7, 10, 5);
}
break;
+ case OP_TLS_GET:
+ code = emit_tls_get (code, ins->dreg, ins->inst_offset);
+ break;
+ case OP_TLS_SET:
+ code = emit_tls_set (code, ins->sreg1, ins->inst_offset);
+ break;
case OP_ATOMIC_EXCHANGE_I4:
case OP_ATOMIC_CAS_I4:
case OP_ATOMIC_ADD_I4: {
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;
+}