[arm] Resurrect inlined fast tls
authorVlad Brezae <brezaevlad@gmail.com>
Wed, 23 Nov 2016 01:48:48 +0000 (01:48 +0000)
committerVlad Brezae <brezaevlad@gmail.com>
Wed, 14 Dec 2016 15:52:51 +0000 (17:52 +0200)
Only on desktop linux, where we now inline aeabi_read_tp.

mono/arch/arm/arm-codegen.h
mono/mini/cpu-arm.md
mono/mini/mini-arm.c
mono/mini/mini-arm.h
mono/utils/mono-tls.c

index 4cde34937b72a59e5f28737c7f45a41d40fb294f..9b2141521c70191fc5d127ef355c66d220fb9bbf 100644 (file)
@@ -1090,6 +1090,16 @@ typedef union {
 #define ARM_MCR(p, coproc, opc1, rt, crn, crm, opc2) \
        ARM_MCR_COND ((p), (coproc), (opc1), (rt), (crn), (crm), (opc2), ARMCOND_AL)
 
+/* MRC */
+#define ARM_DEF_MRC_COND(coproc, opc1, rt, crn, crm, opc2, cond)       \
+       ARM_DEF_COND ((cond)) | ((0xe << 24) | (((opc1) & 0x7) << 21) | (1 << 20) | (((crn) & 0xf) << 16) | (((rt) & 0xf) << 12) | (((coproc) & 0xf) << 8) | (((opc2) & 0x7) << 5) | (1 << 4) | (((crm) & 0xf) << 0))
+
+#define ARM_MRC_COND(p, coproc, opc1, rt, crn, crm, opc2, cond)        \
+       ARM_EMIT(p, ARM_DEF_MRC_COND ((coproc), (opc1), (rt), (crn), (crm), (opc2), (cond)))
+
+#define ARM_MRC(p, coproc, opc1, rt, crn, crm, opc2) \
+       ARM_MRC_COND ((p), (coproc), (opc1), (rt), (crn), (crm), (opc2), ARMCOND_AL)
+
 /* ARMv7VE */
 #define ARM_SDIV_COND(p, rd, rn, rm, cond) ARM_EMIT (p, (((cond) << 28) | (0xe << 23) | (0x1 << 20) | ((rd) << 16) | (0xf << 12) | ((rm) << 8) | (0x0 << 5) | (0x1 << 4) | ((rn) << 0)))
 #define ARM_SDIV(p, rd, rn, rm) ARM_SDIV_COND ((p), (rd), (rn), (rm), ARMCOND_AL)
index 201644bc5da09fcef2dff7450bd5da37606f5a81..25e5f931118c65462120eb35e4050e4535ad5f88 100644 (file)
@@ -244,6 +244,8 @@ sbb_imm: dest:i src1:i len:12
 br_reg: src1:i len:8
 bigmul: len:8 dest:l src1:i src2:i
 bigmul_un: len:8 dest:l src1:i src2:i
+tls_get: len:16 dest:i
+tls_set: len:16 src1:i clob:c
 
 # 32 bit opcodes
 int_add: dest:i src1:i src2:i len:4
index 70113d9fde71a2816dff322d195a4a549ced0b75..cfbbd02cec19520d411d9e7a7a31face0b72f112 100644 (file)
@@ -322,10 +322,54 @@ mono_arm_patchable_bl (guint8 *code, int cond)
        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;
 }
 
 /*
@@ -339,9 +383,13 @@ emit_save_lmf (MonoCompile *cfg, guint8 *code, gint32 lmf_offset)
 {
        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
@@ -4149,6 +4197,12 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                                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: {
index bf0c611ab1279c69f90a8310efdf1a1bd767f9f6..9a09ce51ff0077c27c140a3f63ef00c87894ff4b 100644 (file)
@@ -401,7 +401,7 @@ gboolean
 mono_arm_is_hard_float (void);
 
 gboolean
-mono_arm_have_tls_get (void);
+mono_arm_have_fast_tls (void);
 
 void
 mono_arm_unaligned_stack (MonoMethod *method);
index ea2a34e43ccea4eab38afb4189bb0b8820543978..765011dbfe81aa5551e410a2fb01e9065a2be6a0 100644 (file)
        __asm ( "mov %0, #0\n add %0, %0, #:tprel_hi12:" #var "\n add %0, %0, #:tprel_lo12_nc:" #var "\n" \
                : "=r" (offset))
 
+#elif defined(TARGET_ARM) && defined(__ARM_EABI__) && !defined(PIC)
+
+#define MONO_THREAD_VAR_OFFSET(var,offset) __asm ("     ldr     %0, 1f; b 2f; 1: .word " #var "(tpoff); 2:" : "=r" (offset))
+
 #else
 
 #define MONO_THREAD_VAR_OFFSET(var,offset) (offset) = -1