X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmini%2Fmini-ppc.c;h=4ba20cc2257e31ff9ad4e154ca7267b2b939d124;hb=HEAD;hp=656ba1ed916e58c7eec2c00d683cea8fb106d1e6;hpb=fcca9846c82626dd094b2ca0c5f35991f8afc3a5;p=mono.git diff --git a/mono/mini/mini-ppc.c b/mono/mini/mini-ppc.c index 656ba1ed916..4ba20cc2257 100644 --- a/mono/mini/mini-ppc.c +++ b/mono/mini/mini-ppc.c @@ -1,5 +1,6 @@ -/* - * mini-ppc.c: PowerPC backend for the Mono code generator +/** + * \file + * PowerPC backend for the Mono code generator * * Authors: * Paolo Molaro (lupus@ximian.com) @@ -18,6 +19,7 @@ #include #include #include +#include #include "mini-ppc.h" #ifdef TARGET_POWERPC64 @@ -67,8 +69,6 @@ enum { static mono_mutex_t mini_arch_mutex; int mono_exc_esp_offset = 0; -static int tls_mode = TLS_MODE_DETECT; -static int lmf_pthread_key = -1; /* * The code generated for sequence points reads from this location, which is @@ -79,66 +79,6 @@ static gpointer ss_trigger_page; /* Enabled breakpoints read from this trigger page */ static gpointer bp_trigger_page; -static int -offsets_from_pthread_key (guint32 key, int *offset2) -{ - int idx1 = key / 32; - int idx2 = key % 32; - *offset2 = idx2 * sizeof (gpointer); - return 284 + idx1 * sizeof (gpointer); -} - -#define emit_linuxthreads_tls(code,dreg,key) do {\ - int off1, off2; \ - off1 = offsets_from_pthread_key ((key), &off2); \ - ppc_ldptr ((code), (dreg), off1, ppc_r2); \ - ppc_ldptr ((code), (dreg), off2, (dreg)); \ - } while (0); - -#define emit_darwing5_tls(code,dreg,key) do {\ - int off1 = 0x48 + key * sizeof (gpointer); \ - ppc_mfspr ((code), (dreg), 104); \ - ppc_ldptr ((code), (dreg), off1, (dreg)); \ - } while (0); - -/* FIXME: ensure the sc call preserves all but r3 */ -#define emit_darwing4_tls(code,dreg,key) do {\ - int off1 = 0x48 + key * sizeof (gpointer); \ - if ((dreg) != ppc_r3) ppc_mr ((code), ppc_r12, ppc_r3); \ - ppc_li ((code), ppc_r0, 0x7FF2); \ - ppc_sc ((code)); \ - ppc_lwz ((code), (dreg), off1, ppc_r3); \ - if ((dreg) != ppc_r3) ppc_mr ((code), ppc_r3, ppc_r12); \ - } 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_ldptr ((code), (dreg), off1, PPC_THREAD_PTR_REG); \ - } else { \ - int off3 = (off2 + 1) > 1; \ - ppc_addis ((code), ppc_r12, PPC_THREAD_PTR_REG, off3); \ - ppc_ldptr ((code), (dreg), off1, ppc_r12); \ - } \ - } 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 (); \ - } \ - } while (0) - #define MONO_EMIT_NEW_LOAD_R8(cfg,dr,addr) do { \ MonoInst *inst; \ MONO_INST_NEW ((cfg), (inst), OP_R8CONST); \ @@ -646,6 +586,12 @@ mono_arch_cleanup (void) mono_os_mutex_destroy (&mini_arch_mutex); } +gboolean +mono_arch_have_fast_tls (void) +{ + return FALSE; +} + /* * This function returns the optimizations supported on this cpu. */ @@ -1059,8 +1005,7 @@ get_call_info (MonoMethodSignature *sig) fr = PPC_FIRST_FPARG_REG; gr = PPC_FIRST_ARG_REG; - /* FIXME: handle returning a struct */ - if (MONO_TYPE_ISSTRUCT (sig->ret)) { + if (mini_type_is_vtype (sig->ret)) { cinfo->vtype_retaddr = TRUE; } @@ -1850,7 +1795,7 @@ mono_arch_emit_outarg_vt (MonoCompile *cfg, MonoInst *ins, MonoInst *src) soffset += sizeof (gpointer); } if (ovf_size != 0) - mini_emit_memcpy (cfg, ppc_r1, doffset + soffset, src->dreg, soffset, ovf_size * sizeof (gpointer), 0); + mini_emit_memcpy (cfg, ppc_r1, doffset + soffset, src->dreg, soffset, ovf_size * sizeof (gpointer), SIZEOF_VOID_P); } else if (ainfo->regtype == RegTypeFPStructByVal) { soffset = 0; for (i = 0; i < ainfo->vtregs; ++i) { @@ -1865,7 +1810,7 @@ mono_arch_emit_outarg_vt (MonoCompile *cfg, MonoInst *ins, MonoInst *src) soffset += ainfo->size; } if (ovf_size != 0) - mini_emit_memcpy (cfg, ppc_r1, doffset + soffset, src->dreg, soffset, ovf_size * sizeof (gpointer), 0); + mini_emit_memcpy (cfg, ppc_r1, doffset + soffset, src->dreg, soffset, ovf_size * sizeof (gpointer), SIZEOF_VOID_P); } else if (ainfo->regtype == RegTypeFP) { int tmpr = mono_alloc_freg (cfg); if (ainfo->size == 4) @@ -1891,7 +1836,7 @@ mono_arch_emit_outarg_vt (MonoCompile *cfg, MonoInst *ins, MonoInst *src) g_assert (ovf_size > 0); EMIT_NEW_VARLOADA (cfg, load, vtcopy, vtcopy->inst_vtype); - mini_emit_memcpy (cfg, load->dreg, 0, src->dreg, 0, size, 0); + mini_emit_memcpy (cfg, load->dreg, 0, src->dreg, 0, size, SIZEOF_VOID_P); if (ainfo->offset) MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, ppc_r1, ainfo->offset, load->dreg); @@ -3238,17 +3183,6 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) cpos = bb->max_offset; - if (cfg->prof_options & MONO_PROFILE_COVERAGE) { - //MonoCoverageInfo *cov = mono_get_coverage_info (cfg->method); - //g_assert (!mono_compile_aot); - //cpos += 6; - //if (bb->cil_code) - // cov->data [bb->dfn].iloffset = bb->cil_code - cfg->cil_code; - /* this is not thread save, but good enough */ - /* fixme: howto handle overflows? */ - //x86_inc_mem (code, &cov->data [bb->dfn].count); - } - MONO_BB_FOR_EACH_INS (bb, ins) { offset = code - cfg->native_code; @@ -3301,9 +3235,6 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) ppc_nop (code); break; } - case OP_TLS_GET: - emit_tls_access (code, ins->dreg, ins->inst_offset); - break; case OP_BIGMUL: ppc_mullw (code, ppc_r0, ins->sreg1, ins->sreg2); ppc_mulhw (code, ppc_r3, ins->sreg1, ins->sreg2); @@ -4194,6 +4125,11 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) ppc_mtctr (code, ins->sreg1); ppc_bcctr (code, PPC_BR_ALWAYS, 0); break; + case OP_ICNEQ: + ppc_li (code, ins->dreg, 0); + ppc_bc (code, PPC_BR_TRUE, PPC_BR_EQ, 2); + ppc_li (code, ins->dreg, 1); + break; case OP_CEQ: case OP_ICEQ: CASE_PPC64 (OP_LCEQ) @@ -4211,6 +4147,12 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) ppc_bc (code, PPC_BR_TRUE, PPC_BR_LT, 2); ppc_li (code, ins->dreg, 0); break; + case OP_ICGE: + case OP_ICGE_UN: + ppc_li (code, ins->dreg, 1); + ppc_bc (code, PPC_BR_FALSE, PPC_BR_LT, 2); + ppc_li (code, ins->dreg, 0); + break; case OP_CGT: case OP_CGT_UN: case OP_ICGT: @@ -4221,6 +4163,12 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) ppc_bc (code, PPC_BR_TRUE, PPC_BR_GT, 2); ppc_li (code, ins->dreg, 0); break; + case OP_ICLE: + case OP_ICLE_UN: + ppc_li (code, ins->dreg, 1); + ppc_bc (code, PPC_BR_FALSE, PPC_BR_GT, 2); + ppc_li (code, ins->dreg, 0); + break; case OP_COND_EXC_EQ: case OP_COND_EXC_NE_UN: case OP_COND_EXC_LT: @@ -4423,15 +4371,17 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) ppc_fcmpu (code, 0, ins->sreg1, ins->sreg2); break; case OP_FCEQ: + case OP_FCNEQ: ppc_fcmpo (code, 0, ins->sreg1, ins->sreg2); - ppc_li (code, ins->dreg, 0); - ppc_bc (code, PPC_BR_FALSE, PPC_BR_EQ, 2); ppc_li (code, ins->dreg, 1); + ppc_bc (code, ins->opcode == OP_FCEQ ? PPC_BR_TRUE : PPC_BR_FALSE, PPC_BR_EQ, 2); + ppc_li (code, ins->dreg, 0); break; case OP_FCLT: + case OP_FCGE: ppc_fcmpo (code, 0, ins->sreg1, ins->sreg2); ppc_li (code, ins->dreg, 1); - ppc_bc (code, PPC_BR_TRUE, PPC_BR_LT, 2); + ppc_bc (code, ins->opcode == OP_FCLT ? PPC_BR_TRUE : PPC_BR_FALSE, PPC_BR_LT, 2); ppc_li (code, ins->dreg, 0); break; case OP_FCLT_UN: @@ -4442,9 +4392,10 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) ppc_li (code, ins->dreg, 0); break; case OP_FCGT: + case OP_FCLE: ppc_fcmpo (code, 0, ins->sreg1, ins->sreg2); ppc_li (code, ins->dreg, 1); - ppc_bc (code, PPC_BR_TRUE, PPC_BR_GT, 2); + ppc_bc (code, ins->opcode == OP_FCGT ? PPC_BR_TRUE : PPC_BR_FALSE, PPC_BR_GT, 2); ppc_li (code, ins->dreg, 0); break; case OP_FCGT_UN: @@ -4748,7 +4699,7 @@ mono_arch_patch_code (MonoCompile *cfg, MonoMethod *method, MonoDomain *domain, MonoJumpInfo *patch_info; gboolean compile_aot = !run_cctors; - mono_error_init (error); + error_init (error); for (patch_info = ji; patch_info; patch_info = patch_info->next) { unsigned char *ip = patch_info->ip.i + code; @@ -4976,9 +4927,6 @@ mono_arch_emit_prolog (MonoCompile *cfg) MonoInst *ins; bb->max_offset = max_offset; - if (cfg->prof_options & MONO_PROFILE_COVERAGE) - max_offset += 6; - MONO_BB_FOR_EACH_INS (bb, ins) max_offset += ins_native_length (cfg, ins); } @@ -5312,24 +5260,18 @@ 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 (tls_mode != TLS_MODE_NPTL && G_STRUCT_OFFSET (MonoJitTlsData, lmf)) - ppc_addi (code, ppc_r3, ppc_r3, G_STRUCT_OFFSET (MonoJitTlsData, lmf)); + if (cfg->compile_aot) { + /* Compute the got address which is needed by the PLT entry */ + code = mono_arch_emit_load_got_addr (cfg->native_code, code, cfg, NULL); + } + mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD, + (gpointer)"mono_tls_get_lmf_addr"); + if ((FORCE_INDIR_CALL || cfg->method->dynamic) && !cfg->compile_aot) { + ppc_load_func (code, PPC_CALL_REG, 0); + ppc_mtlr (code, PPC_CALL_REG); + ppc_blrl (code); } else { - if (cfg->compile_aot) { - /* Compute the got address which is needed by the PLT entry */ - code = mono_arch_emit_load_got_addr (cfg->native_code, code, cfg, NULL); - } - mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD, - (gpointer)"mono_get_lmf_addr"); - if ((FORCE_INDIR_CALL || cfg->method->dynamic) && !cfg->compile_aot) { - ppc_load_func (code, PPC_CALL_REG, 0); - ppc_mtlr (code, PPC_CALL_REG); - ppc_blrl (code); - } else { - ppc_bl (code, 0); - } + ppc_bl (code, 0); } /* we build the MonoLMF structure on the stack - see mini-ppc.h */ /* lmf_offset is the offset from the previous stack pointer, @@ -5393,9 +5335,6 @@ mono_arch_emit_epilog (MonoCompile *cfg) if (mono_jit_trace_calls != NULL) max_epilog_size += 50; - if (cfg->prof_options & MONO_PROFILE_ENTER_LEAVE) - max_epilog_size += 50; - while (cfg->code_len + max_epilog_size > (cfg->code_size - 16)) { cfg->code_size *= 2; cfg->native_code = g_realloc (cfg->native_code, cfg->code_size); @@ -5669,143 +5608,9 @@ try_offset_access (void *value, guint32 idx) } #endif -static void -setup_tls_access (void) -{ -#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 - -#ifdef TARGET_PS3 - tls_mode = TLS_MODE_FAILED; -#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 defined(__APPLE__) && defined(__mono_ppc__) && !defined(__mono_ppc64__) - tls_mode = TLS_MODE_DARWIN_G4; -#elif 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; -#elif !defined(TARGET_PS3) - ins = (guint32*)pthread_getspecific; - /* uncond branch to the real method */ - if ((*ins >> 26) == 18) { - gint32 val; - val = (*ins & ~3) << 6; - val >>= 6; - if (*ins & 2) { - /* absolute */ - ins = (guint32*)(long)val; - } else { - ins = (guint32*) ((char*)ins + val); - } - } - code = &cmplwi_1023; - ppc_cmpli (code, 0, 0, ppc_r3, 1023); - code = &li_0x48; - ppc_li (code, ppc_r4, 0x48); - code = &blr_ins; - ppc_blr (code); - if (*ins == cmplwi_1023) { - int found_lwz_284 = 0; - guint32 ptk; - for (ptk = 0; ptk < 20; ++ptk) { - ++ins; - if (!*ins || *ins == blr_ins) - break; - if ((guint16)*ins == 284 && (*ins >> 26) == 32) { - found_lwz_284 = 1; - break; - } - } - if (!found_lwz_284) { - tls_mode = TLS_MODE_FAILED; - return; - } - tls_mode = TLS_MODE_LTHREADS; - } else if (*ins == li_0x48) { - ++ins; - /* uncond branch to the real method */ - if ((*ins >> 26) == 18) { - gint32 val; - val = (*ins & ~3) << 6; - val >>= 6; - if (*ins & 2) { - /* absolute */ - ins = (guint32*)(long)val; - } else { - ins = (guint32*) ((char*)ins + val); - } - code = (guint32*)&val; - ppc_li (code, ppc_r0, 0x7FF2); - if (ins [1] == val) { - /* Darwin on G4, implement */ - tls_mode = TLS_MODE_FAILED; - return; - } else { - code = (guint32*)&val; - ppc_mfspr (code, ppc_r3, 104); - if (ins [1] != val) { - tls_mode = TLS_MODE_FAILED; - return; - } - tls_mode = TLS_MODE_DARWIN_G5; - } - } else { - tls_mode = TLS_MODE_FAILED; - return; - } - } else { - tls_mode = TLS_MODE_FAILED; - return; - } -#endif - } -#ifndef TARGET_PS3 - if (tls_mode == TLS_MODE_DETECT) - tls_mode = TLS_MODE_FAILED; - if (tls_mode == TLS_MODE_FAILED) - return; - if ((lmf_pthread_key == -1) && (tls_mode == TLS_MODE_NPTL)) { - lmf_pthread_key = mono_get_lmf_addr_tls_offset(); - } - -#if 0 - /* 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) { - guint32 ptk = mono_jit_tls_id; - if (ptk < 1024) { - /*g_print ("MonoLMF at: %d\n", ptk);*/ - /*if (!try_offset_access (mono_get_lmf_addr (), ptk)) { - init_tls_failed = 1; - return; - }*/ - lmf_pthread_key = ptk; - } - } -#endif - -#endif -} - void mono_arch_finish_init (void) { - setup_tls_access (); } void @@ -5955,7 +5760,7 @@ mono_arch_build_imt_trampoline (MonoVTable *vtable, MonoDomain *domain, MonoIMTC } if (!fail_tramp) - mono_stats.imt_trampolines_size += code - start; + UnlockedAdd (&mono_stats.imt_trampolines_size, code - start); g_assert (code - start <= size); mono_arch_flush_icache (start, size); @@ -5997,21 +5802,13 @@ mono_arch_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMetho return NULL; } -gboolean -mono_arch_print_tree (MonoInst *tree, int arity) -{ - return 0; -} - mgreg_t mono_arch_context_get_int_reg (MonoContext *ctx, int reg) { if (reg == ppc_r1) return (mgreg_t)MONO_CONTEXT_GET_SP (ctx); - g_assert (reg >= ppc_r13); - - return ctx->regs [reg - ppc_r13]; + return ctx->regs [reg]; } guint32 @@ -6234,15 +6031,3 @@ mono_arch_opcode_supported (int opcode) } } - -#if 0 -// FIXME: To get the test case finally_block_ending_in_dead_bb to work properly we need to define the following -// (in mini-ppc.h) and then implement the fuction mono_arch_create_handler_block_trampoline. -// #define MONO_ARCH_HAVE_HANDLER_BLOCK_GUARD 1 - -gpointer -mono_arch_create_handler_block_trampoline (void) -{ - . . . -} -#endif