X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmini%2Fmini-ppc.c;h=f1149abd8b7e0a2ae1070b27bce3ac1002814f17;hb=409cc50c9c94638819abc1d9a1b921b518313807;hp=e6c7f5b6462f934ea6220d8c1001f669a64a2643;hpb=04aa4b3d4c1f73a989c58f676e0f53c478c54ec4;p=mono.git diff --git a/mono/mini/mini-ppc.c b/mono/mini/mini-ppc.c index e6c7f5b6462..f1149abd8b7 100644 --- a/mono/mini/mini-ppc.c +++ b/mono/mini/mini-ppc.c @@ -26,6 +26,9 @@ #ifdef __APPLE__ #include #endif +#ifdef __linux__ +#include +#endif #define FORCE_INDIR_CALL 1 @@ -81,9 +84,28 @@ offsets_from_pthread_key (guint32 key, int *offset2) 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 (); \ @@ -2581,12 +2603,12 @@ handle_thunk (int absolute, guchar *code, const guchar *target) { 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); @@ -3163,12 +3185,12 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) 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); @@ -4196,6 +4218,39 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) 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__); @@ -4700,7 +4755,7 @@ mono_arch_emit_prolog (MonoCompile *cfg) 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, @@ -5029,23 +5084,32 @@ try_offset_access (void *value, guint32 idx) 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) { @@ -5054,7 +5118,7 @@ setup_tls_access (void) val >>= 6; if (*ins & 2) { /* absolute */ - ins = (guint32*)val; + ins = (guint32*)(long)val; } else { ins = (guint32*) ((char*)ins + val); } @@ -5090,7 +5154,7 @@ setup_tls_access (void) val >>= 6; if (*ins & 2) { /* absolute */ - ins = (guint32*)val; + ins = (guint32*)(long)val; } else { ins = (guint32*) ((char*)ins + val); } @@ -5117,7 +5181,13 @@ setup_tls_access (void) 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) { @@ -5127,6 +5197,12 @@ setup_tls_access (void) } } } + + 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) { @@ -5138,6 +5214,12 @@ setup_tls_access (void) 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) { @@ -5150,7 +5232,6 @@ setup_tls_access (void) /*g_print ("thread not inited yet %d\n", ptk);*/ } } -#endif } void @@ -5190,13 +5271,15 @@ mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckI 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 @@ -5215,7 +5298,7 @@ mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckI } 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) { @@ -5241,7 +5324,7 @@ mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckI } 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); @@ -5255,7 +5338,13 @@ mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckI 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);