#ifdef __APPLE__
#include <sys/sysctl.h>
#endif
+#ifdef __linux__
+#include <unistd.h>
+#endif
#define FORCE_INDIR_CALL 1
if ((dreg) != ppc_r3) ppc_mr ((code), ppc_r3, ppc_r11); \
} while (0);
+#ifdef PPC_THREAD_PTR_REG
+#define emit_nptl_tls(code,dreg,key) do { \
+ int off1 = key; \
+ int off2 = key >> 15; \
+ if ((off2 == 0) || (off2 == -1)) { \
+ ppc_load_reg ((code), (dreg), off1, PPC_THREAD_PTR_REG); \
+ } else { \
+ int off3 = (off2 + 1) > 1; \
+ ppc_addis ((code), ppc_r11, PPC_THREAD_PTR_REG, off3); \
+ ppc_load_reg ((code), (dreg), off1, ppc_r11); \
+ } \
+ } while (0);
+#else
+#define emit_nptl_tls(code,dreg,key) do { \
+ g_assert_not_reached (); \
+ } while (0)
+#endif
+
#define emit_tls_access(code,dreg,key) do { \
switch (tls_mode) { \
case TLS_MODE_LTHREADS: emit_linuxthreads_tls(code,dreg,key); break; \
+ case TLS_MODE_NPTL: emit_nptl_tls(code,dreg,key); break; \
case TLS_MODE_DARWIN_G5: emit_darwing5_tls(code,dreg,key); break; \
case TLS_MODE_DARWIN_G4: emit_darwing4_tls(code,dreg,key); break; \
default: g_assert_not_reached (); \
pdata.found = 0;
mono_domain_lock (domain);
- mono_code_manager_foreach (domain->code_mp, search_thunk_slot, &pdata);
+ mono_domain_code_foreach (domain, search_thunk_slot, &pdata);
if (!pdata.found) {
/* this uses the first available slot */
pdata.found = 2;
- mono_code_manager_foreach (domain->code_mp, search_thunk_slot, &pdata);
+ mono_domain_code_foreach (domain, search_thunk_slot, &pdata);
}
mono_domain_unlock (domain);
ppc_load_reg_indexed (code, ins->dreg, ins->sreg2, ins->inst_basereg);
break;
case OP_LOADI4_MEMINDEX:
- case OP_LOADU4_MEMINDEX:
- ppc_lwzx (code, ins->dreg, ins->sreg2, ins->inst_basereg);
#ifdef __mono_ppc64__
- if (ins->opcode == OP_LOADI4_MEMINDEX)
- ppc_extsb (code, ins->dreg, ins->dreg);
+ ppc_lwax (code, ins->dreg, ins->sreg2, ins->inst_basereg);
+ break;
#endif
+ case OP_LOADU4_MEMINDEX:
+ ppc_lwzx (code, ins->dreg, ins->sreg2, ins->inst_basereg);
break;
case OP_LOADU2_MEMINDEX:
ppc_lhzx (code, ins->dreg, ins->sreg2, ins->inst_basereg);
break;
}
#endif
+ case OP_ATOMIC_CAS_I4:
+ CASE_PPC64 (OP_ATOMIC_CAS_I8) {
+ int location = ins->sreg1;
+ int value = ins->sreg2;
+ int comparand = ins->sreg3;
+ guint8 *start, *not_equal, *lost_reservation;
+
+ start = code;
+ if (ins->opcode == OP_ATOMIC_CAS_I4)
+ ppc_lwarx (code, ppc_r0, 0, location);
+#ifdef __mono_ppc64__
+ else
+ ppc_ldarx (code, ppc_r0, 0, location);
+#endif
+ ppc_cmp (code, 0, ins->opcode == OP_ATOMIC_CAS_I4 ? 0 : 1, ppc_r0, comparand);
+
+ not_equal = code;
+ ppc_bc (code, PPC_BR_FALSE, PPC_BR_EQ, 0);
+ if (ins->opcode == OP_ATOMIC_CAS_I4)
+ ppc_stwcxd (code, value, 0, location);
+#ifdef __mono_ppc64__
+ else
+ ppc_stdcxd (code, value, 0, location);
+#endif
+
+ lost_reservation = code;
+ ppc_bc (code, PPC_BR_FALSE, PPC_BR_EQ, 0);
+ ppc_patch (lost_reservation, start);
+
+ ppc_patch (not_equal, code);
+ ppc_mr (code, ins->dreg, ppc_r0);
+ break;
+ }
default:
g_warning ("unknown opcode %s in %s()\n", mono_inst_name (ins->opcode), __FUNCTION__);
if (method->save_lmf) {
if (lmf_pthread_key != -1) {
emit_tls_access (code, ppc_r3, lmf_pthread_key);
- if (G_STRUCT_OFFSET (MonoJitTlsData, lmf))
+ if (tls_mode != TLS_MODE_NPTL && G_STRUCT_OFFSET (MonoJitTlsData, lmf))
ppc_addi (code, ppc_r3, ppc_r3, G_STRUCT_OFFSET (MonoJitTlsData, lmf));
} else {
mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
static void
setup_tls_access (void)
{
-#ifdef __mono_ppc64__
- /* FIXME: implement */
- tls_mode = TLS_MODE_FAILED;
- return;
-#else
guint32 ptk;
+
+#if defined(__linux__) && defined(_CS_GNU_LIBPTHREAD_VERSION)
+ size_t conf_size = 0;
+ char confbuf[128];
+#else
+ /* FIXME for darwin */
guint32 *ins, *code;
guint32 cmplwi_1023, li_0x48, blr_ins;
+#endif
+
if (tls_mode == TLS_MODE_FAILED)
return;
-
if (g_getenv ("MONO_NO_TLS")) {
tls_mode = TLS_MODE_FAILED;
return;
}
- if (tls_mode == TLS_MODE_DETECT) {
+ if (tls_mode == TLS_MODE_DETECT) {
+#if defined(__linux__) && defined(_CS_GNU_LIBPTHREAD_VERSION)
+ conf_size = confstr ( _CS_GNU_LIBPTHREAD_VERSION, confbuf, sizeof(confbuf));
+ if ((conf_size > 4) && (strncmp (confbuf, "NPTL", 4) == 0))
+ tls_mode = TLS_MODE_NPTL;
+ else
+ tls_mode = TLS_MODE_LTHREADS;
+#else
ins = (guint32*)pthread_getspecific;
/* uncond branch to the real method */
if ((*ins >> 26) == 18) {
val >>= 6;
if (*ins & 2) {
/* absolute */
- ins = (guint32*)val;
+ ins = (guint32*)(long)val;
} else {
ins = (guint32*) ((char*)ins + val);
}
val >>= 6;
if (*ins & 2) {
/* absolute */
- ins = (guint32*)val;
+ ins = (guint32*)(long)val;
} else {
ins = (guint32*) ((char*)ins + val);
}
tls_mode = TLS_MODE_FAILED;
return;
}
+#endif
}
+ if ((monodomain_key == -1) && (tls_mode == TLS_MODE_NPTL)) {
+ monodomain_key = mono_domain_get_tls_offset();
+ }
+ /* if not TLS_MODE_NPTL or local dynamic (as indicated by
+ mono_domain_get_tls_offset returning -1) then use keyed access. */
if (monodomain_key == -1) {
ptk = mono_domain_get_tls_key ();
if (ptk < 1024) {
}
}
}
+
+ if ((lmf_pthread_key == -1) && (tls_mode == TLS_MODE_NPTL)) {
+ lmf_pthread_key = mono_get_lmf_addr_tls_offset();
+ }
+ /* if not TLS_MODE_NPTL or local dynamic (as indicated by
+ mono_get_lmf_addr_tls_offset returning -1) then use keyed access. */
if (lmf_pthread_key == -1) {
ptk = mono_pthread_key_for_tls (mono_jit_tls_id);
if (ptk < 1024) {
lmf_pthread_key = ptk;
}
}
+
+ if ((monothread_key == -1) && (tls_mode == TLS_MODE_NPTL)) {
+ monothread_key = mono_thread_get_tls_offset();
+ }
+ /* if not TLS_MODE_NPTL or local dynamic (as indicated by
+ mono_get_lmf_addr_tls_offset returning -1) then use keyed access. */
if (monothread_key == -1) {
ptk = mono_thread_get_tls_key ();
if (ptk < 1024) {
/*g_print ("thread not inited yet %d\n", ptk);*/
}
}
-#endif
}
void
if (item->check_target_idx) {
if (!item->compare_done)
item->chunk_size += CMP_SIZE;
- if (fail_tramp)
+ if (item->has_target_code)
item->chunk_size += BR_SIZE + JUMP_IMM32_SIZE;
else
item->chunk_size += LOADSTORE_SIZE + BR_SIZE + JUMP_IMM_SIZE;
} else {
if (fail_tramp) {
item->chunk_size += CMP_SIZE + BR_SIZE + JUMP_IMM32_SIZE * 2;
+ if (!item->has_target_code)
+ item->chunk_size += LOADSTORE_SIZE;
} else {
item->chunk_size += LOADSTORE_SIZE + JUMP_IMM_SIZE;
#if ENABLE_WRONG_METHOD_CHECK
} else {
/* the initial load of the vtable address */
size += PPC_LOAD_SEQUENCE_LENGTH + LOADSTORE_SIZE;
- code = mono_code_manager_reserve (domain->code_mp, size);
+ code = mono_domain_code_reserve (domain, size);
}
start = code;
if (!fail_tramp) {
}
item->jmp_code = code;
ppc_bc (code, PPC_BR_FALSE, PPC_BR_EQ, 0);
- if (fail_tramp) {
+ if (item->has_target_code) {
ppc_load (code, ppc_r0, item->value.target_code);
} else {
ppc_load_reg (code, ppc_r0, (sizeof (gpointer) * item->value.vtable_slot), ppc_r11);
ppc_compare_log (code, 0, MONO_ARCH_IMT_REG, ppc_r0);
item->jmp_code = code;
ppc_bc (code, PPC_BR_FALSE, PPC_BR_EQ, 0);
- ppc_load (code, ppc_r0, item->value.target_code);
+ if (item->has_target_code) {
+ ppc_load (code, ppc_r0, item->value.target_code);
+ } else {
+ g_assert (vtable);
+ ppc_load (code, ppc_r0, & (vtable->vtable [item->value.vtable_slot]));
+ ppc_load_reg_indexed (code, ppc_r0, 0, ppc_r0);
+ }
ppc_mtctr (code, ppc_r0);
ppc_bcctr (code, PPC_BR_ALWAYS, 0);
ppc_patch (item->jmp_code, code);