+#if defined(__ARM_EABI__) && defined(__linux__) && !defined(HOST_ANDROID) && !defined(MONO_CROSS_COMPILE)
+#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;
+
+ if (mini_get_debug_options ()->use_fallback_tls)
+ return FALSE;
+
+ if (inited)
+ return have_fast_tls;
+
+ if (v7_supported) {
+ gpointer 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
+ return FALSE;
+#endif
+}
+
+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;
+}
+
+static guint8*
+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;
+}
+