X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmini%2Fmini-ppc.c;h=159b77bbc663ac1a9fe0c41ef2bc8c7d418e399e;hb=31d03d041acc13818cdd392bc99890d1c524be34;hp=c5d4f92f46f468de0bd672d1fbb8eb455b2e0819;hpb=dbf19eb41dbd299c4c33d4de35ffe3cf6c669832;p=mono.git diff --git a/mono/mini/mini-ppc.c b/mono/mini/mini-ppc.c index c5d4f92f46f..159b77bbc66 100644 --- a/mono/mini/mini-ppc.c +++ b/mono/mini/mini-ppc.c @@ -21,6 +21,8 @@ #include #endif +#define FORCE_INDIR_CALL 1 + enum { TLS_MODE_DETECT, TLS_MODE_FAILED, @@ -410,7 +412,7 @@ enum { typedef struct { gint32 offset; - guint16 vtsize; /* in param area */ + guint32 vtsize; /* in param area */ guint8 reg; guint8 regtype : 4; /* 0 general, 1 basereg, 2 floating point register, see RegType* */ guint8 size : 4; /* 1, 2, 4, 8, or regs used by RegTypeStructByVal */ @@ -620,6 +622,7 @@ calculate_sizes (MonoMethodSignature *sig, gboolean is_pinvoke) #else add_general (&gr, &stack_size, cinfo->args + n, TRUE); cinfo->args [n].regtype = RegTypeStructByAddr; + cinfo->args [n].vtsize = size; #endif n++; break; @@ -649,6 +652,7 @@ calculate_sizes (MonoMethodSignature *sig, gboolean is_pinvoke) #else add_general (&gr, &stack_size, cinfo->args + n, TRUE); cinfo->args [n].regtype = RegTypeStructByAddr; + cinfo->args [n].vtsize = size; #endif n++; break; @@ -996,9 +1000,17 @@ mono_arch_call_opcode (MonoCompile *cfg, MonoBasicBlock* bb, MonoCallInst *call, if (arg->type == STACK_I8) call->used_iregs |= 1 << (ainfo->reg + 1); } else if (ainfo->regtype == RegTypeStructByAddr) { - /* FIXME: where si the data allocated? */ - arg->backend.reg3 = ainfo->reg; - call->used_iregs |= 1 << ainfo->reg; + if (ainfo->offset) { + MonoPPCArgInfo *ai = mono_mempool_alloc0 (cfg->mempool, sizeof (MonoPPCArgInfo)); + arg->opcode = OP_OUTARG_MEMBASE; + ai->reg = ainfo->reg; + ai->size = sizeof (gpointer); + ai->offset = ainfo->offset; + arg->backend.data = ai; + } else { + arg->backend.reg3 = ainfo->reg; + call->used_iregs |= 1 << ainfo->reg; + } } else if (ainfo->regtype == RegTypeStructByVal) { int cur_reg; MonoPPCArgInfo *ai = mono_mempool_alloc0 (cfg->mempool, sizeof (MonoPPCArgInfo)); @@ -1358,15 +1370,8 @@ peephole_pass (MonoCompile *cfg, MonoBasicBlock *bb) if (last_ins && (last_ins->opcode == OP_STOREI1_MEMBASE_REG) && ins->inst_basereg == last_ins->inst_destbasereg && ins->inst_offset == last_ins->inst_offset) { - if (ins->dreg == last_ins->sreg1) { - last_ins->next = ins->next; - ins = ins->next; - continue; - } else { - //static int c = 0; printf ("MATCHX %s %d\n", cfg->method->name,c++); - ins->opcode = OP_MOVE; - ins->sreg1 = last_ins->sreg1; - } + ins->opcode = (ins->opcode == OP_LOADI1_MEMBASE) ? CEE_CONV_I1 : CEE_CONV_U1; + ins->sreg1 = last_ins->sreg1; } break; case OP_LOADU2_MEMBASE: @@ -1374,15 +1379,8 @@ peephole_pass (MonoCompile *cfg, MonoBasicBlock *bb) if (last_ins && (last_ins->opcode == OP_STOREI2_MEMBASE_REG) && ins->inst_basereg == last_ins->inst_destbasereg && ins->inst_offset == last_ins->inst_offset) { - if (ins->dreg == last_ins->sreg1) { - last_ins->next = ins->next; - ins = ins->next; - continue; - } else { - //static int c = 0; printf ("MATCHX %s %d\n", cfg->method->name,c++); - ins->opcode = OP_MOVE; - ins->sreg1 = last_ins->sreg1; - } + ins->opcode = (ins->opcode == OP_LOADI2_MEMBASE) ? CEE_CONV_I2 : CEE_CONV_U2; + ins->sreg1 = last_ins->sreg1; } break; case CEE_CONV_I4: @@ -1462,8 +1460,6 @@ branch_b1_table [] = { PPC_BR_LT }; -static const char*const * ins_spec = ppcg4; - static void insert_after_ins (MonoBasicBlock *bb, MonoInst *ins, MonoInst *to_insert) { @@ -1567,8 +1563,8 @@ mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb) int imm; /* setup the virtual reg allocator */ - if (bb->max_ireg > cfg->rs->next_vireg) - cfg->rs->next_vireg = bb->max_ireg; + if (bb->max_vreg > cfg->rs->next_vreg) + cfg->rs->next_vreg = bb->max_vreg; ins = bb->code; while (ins) { @@ -1700,7 +1696,7 @@ loop_start: ins = ins->next; } bb->last_ins = last_ins; - bb->max_ireg = cfg->rs->next_vireg; + bb->max_vreg = cfg->rs->next_vreg; } @@ -1946,10 +1942,10 @@ ppc_patch (guchar *code, guchar *target) return; } - if (prim == 15 || ins == 0x4e800021) { + if (prim == 15 || ins == 0x4e800021 || ins == 0x4e800020 || ins == 0x4e800420) { guint32 *seq; - /* the trampoline code will try to patch the blrl */ - if (ins == 0x4e800021) { + /* the trampoline code will try to patch the blrl, blr, bcctr */ + if (ins == 0x4e800021 || ins == 0x4e800020 || ins == 0x4e800420) { code -= 12; } /* this is the lis/ori/mtlr/blrl sequence */ @@ -1957,7 +1953,7 @@ ppc_patch (guchar *code, guchar *target) g_assert ((seq [0] >> 26) == 15); g_assert ((seq [1] >> 26) == 24); g_assert ((seq [2] >> 26) == 31); - g_assert (seq [3] == 0x4e800021); + g_assert (seq [3] == 0x4e800021 || seq [3] == 0x4e800020 || seq [3] == 0x4e800420); /* FIXME: make this thread safe */ ppc_lis (code, ppc_r0, (guint32)(target) >> 16); ppc_ori (code, ppc_r0, ppc_r0, (guint32)(target) & 0xffff); @@ -2004,7 +2000,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) while (ins) { offset = code - cfg->native_code; - max_len = ((guint8 *)ins_spec [ins->opcode])[MONO_INST_LEN]; + max_len = ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN]; if (offset > (cfg->code_size - max_len - 16)) { cfg->code_size *= 2; @@ -2355,7 +2351,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) if (!(ins->inst_imm & 0xffff0000)) { ppc_ori (code, ins->sreg1, ins->dreg, ins->inst_imm); } else if (!(ins->inst_imm & 0xffff)) { - ppc_oris (code, ins->sreg1, ins->dreg, ((guint32)(ins->inst_imm) >> 16)); + ppc_oris (code, ins->dreg, ins->sreg1, ((guint32)(ins->inst_imm) >> 16)); } else { g_assert_not_reached (); } @@ -2525,7 +2521,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) mono_add_patch_info (cfg, offset, MONO_PATCH_INFO_METHOD, call->method); else mono_add_patch_info (cfg, offset, MONO_PATCH_INFO_ABS, call->fptr); - if (cfg->method->dynamic) { + if (FORCE_INDIR_CALL || cfg->method->dynamic) { ppc_lis (code, ppc_r0, 0); ppc_ori (code, ppc_r0, ppc_r0, 0); ppc_mtlr (code, ppc_r0); @@ -2594,7 +2590,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) ppc_mr (code, ppc_r3, ins->sreg1); mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD, (gpointer)"mono_arch_throw_exception"); - if (cfg->method->dynamic) { + if (FORCE_INDIR_CALL || cfg->method->dynamic) { ppc_lis (code, ppc_r0, 0); ppc_ori (code, ppc_r0, ppc_r0, 0); ppc_mtlr (code, ppc_r0); @@ -2609,7 +2605,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) ppc_mr (code, ppc_r3, ins->sreg1); mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD, (gpointer)"mono_arch_rethrow_exception"); - if (cfg->method->dynamic) { + if (FORCE_INDIR_CALL || cfg->method->dynamic) { ppc_lis (code, ppc_r0, 0); ppc_ori (code, ppc_r0, ppc_r0, 0); ppc_mtlr (code, ppc_r0); @@ -2888,7 +2884,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) g_assert_not_reached (); break; case OP_FCOMPARE: - ppc_fcmpo (code, 0, ins->sreg1, ins->sreg2); + ppc_fcmpu (code, 0, ins->sreg1, ins->sreg2); break; case OP_FCEQ: ppc_fcmpo (code, 0, ins->sreg1, ins->sreg2); @@ -2929,6 +2925,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) EMIT_COND_BRANCH (ins, CEE_BNE_UN - CEE_BEQ); break; case OP_FBLT: + ppc_bc (code, PPC_BR_TRUE, PPC_BR_SO, 2); EMIT_COND_BRANCH (ins, CEE_BLT - CEE_BEQ); break; case OP_FBLT_UN: @@ -2936,6 +2933,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) EMIT_COND_BRANCH (ins, CEE_BLT_UN - CEE_BEQ); break; case OP_FBGT: + ppc_bc (code, PPC_BR_TRUE, PPC_BR_SO, 2); EMIT_COND_BRANCH (ins, CEE_BGT - CEE_BEQ); break; case OP_FBGT_UN: @@ -2943,12 +2941,14 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) EMIT_COND_BRANCH (ins, CEE_BGT_UN - CEE_BEQ); break; case OP_FBGE: + ppc_bc (code, PPC_BR_TRUE, PPC_BR_SO, 2); EMIT_COND_BRANCH (ins, CEE_BGE - CEE_BEQ); break; case OP_FBGE_UN: EMIT_COND_BRANCH (ins, CEE_BGE_UN - CEE_BEQ); break; case OP_FBLE: + ppc_bc (code, PPC_BR_TRUE, PPC_BR_SO, 2); EMIT_COND_BRANCH (ins, CEE_BLE - CEE_BEQ); break; case OP_FBLE_UN: @@ -3163,7 +3163,7 @@ mono_arch_emit_prolog (MonoCompile *cfg) max_offset += 6; while (ins) { - max_offset += ((guint8 *)ins_spec [ins->opcode])[MONO_INST_LEN]; + max_offset += ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN]; ins = ins->next; } } @@ -3322,9 +3322,17 @@ register. Should this case include linux/ppc? code = emit_memcpy (code, ainfo->vtsize * sizeof (gpointer), inst->inst_basereg, doffset, ppc_r11, ainfo->offset + soffset); } } else if (ainfo->regtype == RegTypeStructByAddr) { + /* if it was originally a RegTypeBase */ + if (ainfo->offset) { + /* load the previous stack pointer in r11 */ + ppc_lwz (code, ppc_r11, 0, ppc_sp); + ppc_lwz (code, ppc_r11, ainfo->offset, ppc_r11); + } else { + ppc_mr (code, ppc_r11, ainfo->reg); + } g_assert (ppc_is_imm16 (inst->inst_offset)); - /* FIXME: handle overrun! with struct sizes not multiple of 4 */ - code = emit_memcpy (code, ainfo->vtsize * sizeof (gpointer), inst->inst_basereg, inst->inst_offset, ainfo->reg, 0); + code = emit_memcpy (code, ainfo->vtsize, inst->inst_basereg, inst->inst_offset, ppc_r11, 0); + /*g_print ("copy in %s: %d bytes from %d to offset: %d\n", method->name, ainfo->vtsize, ainfo->reg, inst->inst_offset);*/ } else g_assert_not_reached (); } @@ -3334,7 +3342,14 @@ register. Should this case include linux/ppc? if (method->wrapper_type == MONO_WRAPPER_NATIVE_TO_MANAGED) { ppc_load (code, ppc_r3, cfg->domain); mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD, (gpointer)"mono_jit_thread_attach"); - ppc_bl (code, 0); + if (FORCE_INDIR_CALL || cfg->method->dynamic) { + ppc_lis (code, ppc_r0, 0); + ppc_ori (code, ppc_r0, ppc_r0, 0); + ppc_mtlr (code, ppc_r0); + ppc_blrl (code); + } else { + ppc_bl (code, 0); + } } if (method->save_lmf) { @@ -3345,7 +3360,7 @@ register. Should this case include linux/ppc? } else { mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD, (gpointer)"mono_get_lmf_addr"); - if (cfg->method->dynamic) { + if (FORCE_INDIR_CALL || cfg->method->dynamic) { ppc_lis (code, ppc_r0, 0); ppc_ori (code, ppc_r0, ppc_r0, 0); ppc_mtlr (code, ppc_r0); @@ -3534,7 +3549,7 @@ mono_arch_emit_exceptions (MonoCompile *cfg) if (patch_info->type == MONO_PATCH_INFO_EXC) { i = exception_id_by_name (patch_info->data.target); if (!exc_throw_found [i]) { - max_epilog_size += 12; + max_epilog_size += 24; exc_throw_found [i] = TRUE; } } else if (patch_info->type == MONO_PATCH_INFO_BB_OVF) @@ -3543,7 +3558,7 @@ mono_arch_emit_exceptions (MonoCompile *cfg) MonoOvfJump *ovfj = patch_info->data.target; i = exception_id_by_name (ovfj->data.exception); if (!exc_throw_found [i]) { - max_epilog_size += 12; + max_epilog_size += 24; exc_throw_found [i] = TRUE; } max_epilog_size += 8; @@ -3612,7 +3627,14 @@ mono_arch_emit_exceptions (MonoCompile *cfg) patch_info->type = MONO_PATCH_INFO_INTERNAL_METHOD; patch_info->data.name = "mono_arch_throw_exception_by_name"; patch_info->ip.i = code - cfg->native_code; - ppc_b (code, 0); + if (FORCE_INDIR_CALL || cfg->method->dynamic) { + ppc_lis (code, ppc_r0, 0); + ppc_ori (code, ppc_r0, ppc_r0, 0); + ppc_mtctr (code, ppc_r0); + ppc_bcctr (code, PPC_BR_ALWAYS, 0); + } else { + ppc_b (code, 0); + } break; } default: