Implement fast tls for s390x (#4161)
authorNeale Ferguson <neale@sinenomine.net>
Tue, 20 Dec 2016 12:56:21 +0000 (07:56 -0500)
committerVlad Brezae <brezaevlad@gmail.com>
Tue, 20 Dec 2016 12:56:21 +0000 (14:56 +0200)
[s390x] Implement fast tls for s390x

mono/mini/cpu-s390x.md
mono/mini/mini-s390x.c
mono/utils/mono-tls.c

index b7653f85df34f60a4a3918702c0483e12e6c3b01..8dabb43234f80cb4af5a22bdba870fe28aee4831 100644 (file)
@@ -203,6 +203,8 @@ sub_ovf_carry: dest:i src1:1 src2:i len:28
 sub_ovf_un_carry: dest:i src1:1 src2:i len:12
 subcc: dest:i src1:i src2:i len:12
 throw: src1:i len:26
+tls_get: dest:1 len:32
+tls_set: src1:1 len:32
 vcall: len:22 clob:c
 vcall_membase: src1:b len:12 clob:c
 vcall_reg: src1:i len:8 clob:c
index ac0bcaa48fbb64fb822ad286dc9f227b950af0af..8cbcd45acccc51fe35fc339b2353975983fcc3d5 100644 (file)
@@ -1368,7 +1368,7 @@ mono_arch_cleanup (void)
 gboolean
 mono_arch_have_fast_tls (void)
 {
-       return FALSE;
+       return TRUE;
 }
 
 /*========================= End of Function ========================*/
@@ -3918,6 +3918,34 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                case OP_S390_SETF4RET:
                        s390_ledbr (code, ins->dreg, ins->sreg1);
                        break;
+                case OP_TLS_GET: {
+                       if (s390_is_imm16 (ins->inst_offset)) {
+                               s390_lghi (code, s390_r13, ins->inst_offset);
+                       } else if (s390_is_imm32 (ins->inst_offset)) {
+                               s390_lgfi (code, s390_r13, ins->inst_offset);
+                       } else {
+                               S390_SET  (code, s390_r13, ins->inst_offset);
+                       }
+                       s390_ear (code, s390_r1, 0);
+                       s390_sllg(code, s390_r1, s390_r1, 0, 32);
+                       s390_ear (code, s390_r1, 1);
+                       s390_lg  (code, ins->dreg, s390_r13, s390_r1, 0);
+                       }
+                       break;
+                case OP_TLS_SET: {
+                       if (s390_is_imm16 (ins->inst_offset)) {
+                               s390_lghi (code, s390_r13, ins->inst_offset);
+                       } else if (s390_is_imm32 (ins->inst_offset)) {
+                               s390_lgfi (code, s390_r13, ins->inst_offset);
+                       } else {
+                               S390_SET  (code, s390_r13, ins->inst_offset);
+                       }
+                       s390_ear (code, s390_r1, 0);
+                       s390_sllg(code, s390_r1, s390_r1, 0, 32);
+                       s390_ear (code, s390_r1, 1);
+                       s390_stg (code, ins->sreg1, s390_r13, s390_r1, 0);
+                       }
+                       break;
                case OP_JMP: {
                        if (cfg->method->save_lmf)
                                restoreLMF(code, cfg->frame_reg, cfg->stack_usage);
@@ -6268,6 +6296,18 @@ mono_arch_print_tree (MonoInst *tree, int arity)
                                mono_arch_regname (tree->sreg1));
                        done = 1;
                        break;
+               case OP_TLS_GET:
+                       printf ("[0x%lx(0x%lx,%s)]", tree->inst_offset,
+                       tree->inst_imm,
+                       mono_arch_regname (tree->sreg1));
+                       done = 1;
+                       break;
+               case OP_TLS_SET:
+                       printf ("[0x%lx(0x%lx,%s)]", tree->inst_offset,
+                       tree->inst_imm,
+                       mono_arch_regname (tree->sreg1));
+                       done = 1;
+                       break;
                case OP_S390_BKCHAIN:
                        printf ("[previous_frame(%s)]", 
                                mono_arch_regname (tree->sreg1));
index 186e1d5c551b46a67be4772ce7791665faafdb46..da4498936a2160792255e7386d1ebc527c47849d 100644 (file)
 
 #define MONO_THREAD_VAR_OFFSET(var,offset) __asm ("     ldr     %0, 1f; b 2f; 1: .word " #var "(tpoff); 2:" : "=r" (offset))
 
+#elif defined(TARGET_S390X)
+# if defined(__PIC__)
+#  if !defined(__PIE__)
+// This only works if libmono is linked into the application
+#   define MONO_THREAD_VAR_OFFSET(var,offset) do { guint64 foo;                                \
+                                               __asm__ ("basr  %%r1,0\n\t"                     \
+                                                        "j     0f\n\t"                         \
+                                                        ".quad " #var "@TLSGD\n"               \
+                                                        "0:\n\t"                               \
+                                                        "lg    %%r2,4(%%r1)\n\t"               \
+                                                        "brasl %%r14,__tls_get_offset@PLT:tls_gdcall:"#var"\n\t" \
+                                                        "lgr   %0,%%r2\n\t"                    \
+                                                       : "=r" (foo) :                          \
+                                                       : "1", "2", "14", "cc");                \
+                                               offset = foo; } while (0)
+#  elif __PIE__ == 1
+#   define MONO_THREAD_VAR_OFFSET(var,offset) do { guint64 foo;                                        \
+                                               __asm__ ("lg    %0," #var "@GOTNTPOFF(%%r12)\n\t"       \
+                                                        : "=r" (foo));                                 \
+                                               offset = foo; } while (0)
+#  elif __PIE__ == 2
+#   define MONO_THREAD_VAR_OFFSET(var,offset) do { guint64 foo;                                \
+                                               __asm__ ("larl  %%r1," #var "@INDNTPOFF\n\t"    \
+                                                        "lg    %0,0(%%r1)\n\t"                 \
+                                                        : "=r" (foo) :                         \
+                                                        : "1", "cc");                          \
+                                               offset = foo; } while (0)
+#  endif
+# else
+#  define MONO_THREAD_VAR_OFFSET(var,offset) do { guint64 foo;                         \
+                                               __asm__ ("basr  %%r1,0\n\t"             \
+                                                        "j     0f\n\t"                 \
+                                                        ".quad " #var "@NTPOFF\n"      \
+                                                        "0:\n\t"                       \
+                                                        "lg    %0,4(%%r1)\n\t"         \
+                                                       : "=r" (foo) : : "1");          \
+                                               offset = foo; } while (0)
+# endif
 #else
 
 #define MONO_THREAD_VAR_OFFSET(var,offset) (offset) = -1