gboolean
mono_arch_have_fast_tls (void)
{
- return FALSE;
+ return TRUE;
}
/*========================= End of Function ========================*/
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);
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));
#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