X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;ds=sidebyside;f=mono%2Fmini%2Finssel-ppc.brg;h=26d63f92f563f02e507c0b031fd4071459ce174e;hb=ef839470ee9e5a5a98980aa80f29ec99428692d9;hp=04d0f4863362a05ad971a9a75c28947d4d02ba68;hpb=ee4ccb6971f7a639440bfdfe784f3f64486c8e33;p=mono.git diff --git a/mono/mini/inssel-ppc.brg b/mono/mini/inssel-ppc.brg index 04d0f486336..26d63f92f56 100644 --- a/mono/mini/inssel-ppc.brg +++ b/mono/mini/inssel-ppc.brg @@ -12,7 +12,47 @@ stmt: OP_START_HANDLER { MonoInst *spvar = mono_find_spvar_for_region (s, s->cbb->region); - MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, spvar->inst_basereg, spvar->inst_offset, ppc_sp); + /*MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, spvar->inst_basereg, spvar->inst_offset, ppc_sp); + */ + tree->inst_left = spvar; + mono_bblock_add_inst (s->cbb, tree); +} + +stmt: CEE_ENDFINALLY { + MonoInst *spvar = mono_find_spvar_for_region (s, s->cbb->region); + tree->inst_left = spvar; + mono_bblock_add_inst (s->cbb, tree); +} + +stmt: OP_ENDFILTER (reg) { + MonoInst *spvar = mono_find_spvar_for_region (s, s->cbb->region); + tree->inst_left = spvar; + tree->sreg1 = state->left->reg1; + mono_bblock_add_inst (s->cbb, tree); +} + +lreg: OP_LADD_OVF (lreg, lreg) "0" { + /* ADC sets the condition code */ + MONO_EMIT_NEW_BIALU (s, OP_ADDCC, state->reg1, state->left->reg1, state->right->reg1); + MONO_EMIT_NEW_BIALU (s, OP_ADD_OVF_CARRY, state->reg2, state->left->reg2, state->right->reg2); +} + +lreg: OP_LADD_OVF_UN (lreg, lreg) "0" { + /* ADC sets the condition code */ + MONO_EMIT_NEW_BIALU (s, OP_ADDCC, state->reg1, state->left->reg1, state->right->reg1); + MONO_EMIT_NEW_BIALU (s, OP_ADD_OVF_UN_CARRY, state->reg2, state->left->reg2, state->right->reg2); +} + +lreg: OP_LSUB_OVF (lreg, lreg) "0" { + /* SBB sets the condition code */ + MONO_EMIT_NEW_BIALU (s, OP_SUBCC, state->reg1, state->left->reg1, state->right->reg1); + MONO_EMIT_NEW_BIALU (s, OP_SUB_OVF_CARRY, state->reg2, state->left->reg2, state->right->reg2); +} + +lreg: OP_LSUB_OVF_UN (lreg, lreg) "0" { + /* SBB sets the condition code */ + MONO_EMIT_NEW_BIALU (s, OP_SUBCC, state->reg1, state->left->reg1, state->right->reg1); + MONO_EMIT_NEW_BIALU (s, OP_SUB_OVF_UN_CARRY, state->reg2, state->left->reg2, state->right->reg2); } stmt: CEE_STIND_I8 (OP_REGVAR, lreg) { @@ -27,25 +67,36 @@ lreg: OP_LNEG (lreg) "2" { } freg: OP_LCONV_TO_R8 (lreg) { + tree->dreg = state->reg1; + tree->sreg1 = state->left->reg1; + tree->sreg2 = state->left->reg2; mono_bblock_add_inst (s->cbb, tree); } freg: OP_LCONV_TO_R4 (lreg) { + tree->dreg = state->reg1; + tree->sreg1 = state->left->reg1; + tree->sreg2 = state->left->reg2; mono_bblock_add_inst (s->cbb, tree); } freg: CEE_CONV_R_UN (reg) { + tree->dreg = state->reg1; + tree->sreg1 = state->left->reg1; mono_bblock_add_inst (s->cbb, tree); } reg: OP_LOCALLOC (OP_ICONST) { /* microcoded in mini-ppc.c */ tree->sreg1 = mono_regstate_next_int (s->rs); + tree->dreg = state->reg1; MONO_EMIT_NEW_ICONST (s, tree->sreg1, state->left->tree->inst_c0); mono_bblock_add_inst (s->cbb, tree); } reg: OP_LOCALLOC (reg) { + tree->dreg = state->reg1; + tree->sreg1 = state->left->reg1; mono_bblock_add_inst (s->cbb, tree); } @@ -57,10 +108,10 @@ stmt: OP_SETRET (reg) { } stmt: OP_SETRET (lreg) { - MONO_EMIT_NEW_UNALU (s, OP_MOVE, ppc_r3, state->left->reg2); - tree->opcode = OP_MOVE; + tree->opcode = OP_SETLRET; tree->sreg1 = state->left->reg1; - tree->dreg = ppc_r4; + tree->sreg2 = state->left->reg2; + tree->dreg = ppc_r3; mono_bblock_add_inst (s->cbb, tree); } @@ -78,68 +129,109 @@ stmt: OP_SETRET (OP_ICONST) { mono_bblock_add_inst (s->cbb, tree); } +stmt: CEE_STIND_I (OP_REGVAR, CEE_SUB (CEE_LDIND_I (OP_REGVAR), OP_ICONST)), +stmt: CEE_STIND_I4 (OP_REGVAR, CEE_SUB (CEE_LDIND_I4 (OP_REGVAR), OP_ICONST)), +stmt: CEE_STIND_I (OP_REGVAR, CEE_ADD (CEE_LDIND_I (OP_REGVAR), OP_ICONST)), +stmt: CEE_STIND_I4 (OP_REGVAR, CEE_ADD (CEE_LDIND_I4 (OP_REGVAR), OP_ICONST)) { + int con = state->right->right->tree->inst_c0; + int dreg = state->left->tree->dreg; + int sreg = state->right->left->left->tree->dreg; + + if (state->right->op == CEE_ADD) + tree->opcode = OP_ADD_IMM; + else if (state->right->op == CEE_SUB) + tree->opcode = OP_SUB_IMM; + else + g_assert_not_reached (); + tree->inst_imm = con; + tree->sreg1 = sreg; + tree->dreg = dreg; + mono_bblock_add_inst (s->cbb, tree); +} + +stmt: OP_OUTARG_MEMBASE (reg) { + MonoPPCArgInfo *ai = tree->backend.data; + MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, ppc_r1, ai->offset, state->left->reg1); +} + +stmt: OP_OUTARG_MEMBASE (OP_REGVAR) { + MonoPPCArgInfo *ai = tree->backend.data; + MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, ppc_r1, ai->offset, state->left->tree->dreg); +} + +stmt: OP_OUTARG_MEMBASE (lreg) { + MonoPPCArgInfo *ai = tree->backend.data; + MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, ppc_r1, ai->offset, state->left->reg2); + MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, ppc_r1, ai->offset + 4, state->left->reg1); +} + +stmt: OP_OUTARG_MEMBASE (OP_ICONST) { + MonoPPCArgInfo *ai = tree->backend.data; + MONO_EMIT_NEW_STORE_MEMBASE_IMM (s, OP_STORE_MEMBASE_IMM, ppc_r1, ai->offset, state->left->tree->inst_c0); +} + +stmt: OP_OUTARG_MEMBASE (CEE_LDIND_REF (OP_REGVAR)) { + MonoPPCArgInfo *ai = tree->backend.data; + MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, ppc_r1, ai->offset, state->left->left->tree->dreg); +} + +stmt: OP_OUTARG_MEMBASE (freg) { + MonoPPCArgInfo *ai = tree->backend.data; + int opcode = ai->size == 4? OP_STORER4_MEMBASE_REG: OP_STORER8_MEMBASE_REG; + MONO_EMIT_NEW_STORE_MEMBASE (s, opcode, ppc_r1, ai->offset, state->left->reg1); +} + stmt: OP_OUTARG (reg) { + MonoCallInst *call = tree->inst_call; + tree->opcode = OP_SETREG; - tree->dreg = tree->unused; + tree->dreg = mono_regstate_next_int (s->rs); tree->sreg1 = state->left->reg1; mono_bblock_add_inst (s->cbb, tree); + mono_call_inst_add_outarg_reg (s, call, tree->dreg, tree->backend.reg3, FALSE); } stmt: OP_OUTARG (OP_REGVAR) { + MonoCallInst *call = tree->inst_call; + tree->opcode = OP_SETREG; - tree->dreg = tree->unused; + tree->dreg = mono_regstate_next_int (s->rs); tree->sreg1 = state->left->tree->dreg; mono_bblock_add_inst (s->cbb, tree); + mono_call_inst_add_outarg_reg (s, call, tree->dreg, tree->backend.reg3, FALSE); } stmt: OP_OUTARG (lreg) { - MONO_EMIT_NEW_UNALU (s, OP_SETREG, tree->unused, state->left->reg2); + MonoCallInst *call = tree->inst_call; + int tdreg = mono_regstate_next_int (s->rs); + + MONO_EMIT_NEW_UNALU (s, OP_SETREG, tdreg, state->left->reg2); + mono_call_inst_add_outarg_reg (s, call, tdreg, tree->backend.reg3, FALSE); tree->opcode = OP_SETREG; - tree->dreg = tree->unused + 1; + tree->dreg = mono_regstate_next_int (s->rs); tree->sreg1 = state->left->reg1; mono_bblock_add_inst (s->cbb, tree); + mono_call_inst_add_outarg_reg (s, call, tree->dreg, tree->backend.reg3 + 1, FALSE); } stmt: OP_OUTARG (OP_ICONST) { + MonoCallInst *call = tree->inst_call; + tree->opcode = OP_SETREGIMM; - tree->dreg = tree->unused; + tree->dreg = mono_regstate_next_int (s->rs); tree->inst_c0 = state->left->tree->inst_c0; mono_bblock_add_inst (s->cbb, tree); + mono_call_inst_add_outarg_reg (s, call, tree->dreg, tree->backend.reg3, FALSE); } -#stmt: OP_OUTARG (CEE_LDIND_I4 (base)) { -# tree->opcode = OP_X86_PUSH_MEMBASE; -# tree->inst_basereg = state->left->left->tree->inst_basereg; -# tree->inst_offset = state->left->left->tree->inst_offset; -# mono_bblock_add_inst (s->cbb, tree); -#} - -#stmt: OP_OUTARG (CEE_LDIND_U4 (base)) { -# tree->opcode = OP_X86_PUSH_MEMBASE; -# tree->inst_basereg = state->left->left->tree->inst_basereg; -# tree->inst_offset = state->left->left->tree->inst_offset; -# mono_bblock_add_inst (s->cbb, tree); -#} - -#stmt: OP_OUTARG (CEE_LDIND_I (base)) { -# tree->opcode = OP_X86_PUSH_MEMBASE; -# tree->inst_basereg = state->left->left->tree->inst_basereg; -# tree->inst_offset = state->left->left->tree->inst_offset; -# mono_bblock_add_inst (s->cbb, tree); -#} - -#stmt: OP_OUTARG (CEE_LDIND_REF (base)) { -# tree->opcode = OP_X86_PUSH_MEMBASE; -# tree->inst_basereg = state->left->left->tree->inst_basereg; -# tree->inst_offset = state->left->left->tree->inst_offset; -# mono_bblock_add_inst (s->cbb, tree); -#} - stmt: OP_OUTARG (CEE_LDIND_REF (OP_REGVAR)) { + MonoCallInst *call = tree->inst_call; + tree->opcode = OP_SETREG; + tree->dreg = mono_regstate_next_int (s->rs); tree->sreg1 = state->left->left->tree->dreg; - tree->dreg = tree->unused; mono_bblock_add_inst (s->cbb, tree); + mono_call_inst_add_outarg_reg (s, call, tree->dreg, tree->backend.reg3, FALSE); } #stmt: OP_OUTARG (CEE_LDOBJ (reg)) { @@ -148,48 +240,102 @@ stmt: OP_OUTARG (CEE_LDIND_REF (OP_REGVAR)) { # mono_bblock_add_inst (s->cbb, tree); #} +stmt: OP_OUTARG_R8 (freg), stmt: OP_OUTARG (freg) { - tree->opcode = OP_SETFREG; - tree->sreg1 = state->left->reg1; - tree->dreg = tree->unused; - mono_bblock_add_inst (s->cbb, tree); -} + MonoCallInst *call = tree->inst_call; -stmt: OP_OUTARG_R4 (freg) { tree->opcode = OP_SETFREG; + tree->dreg = mono_regstate_next_float (s->rs); tree->sreg1 = state->left->reg1; - tree->dreg = tree->unused; mono_bblock_add_inst (s->cbb, tree); + mono_call_inst_add_outarg_reg (s, call, tree->dreg, tree->backend.reg3, TRUE); } -stmt: OP_OUTARG_R8 (freg) { - tree->opcode = OP_SETFREG; - tree->sreg1 = state->left->reg1; - tree->dreg = tree->unused; - mono_bblock_add_inst (s->cbb, tree); +stmt: OP_OUTARG_R8 (CEE_LDOBJ (base)) { + /* small struct with fp value goes in a fp register */ + MonoInst *vt = state->left->left->tree; + int tmpr, soffset, dreg; + MonoCallInst *call = tree->inst_call; + + soffset = vt->inst_offset; + tmpr = mono_regstate_next_float (s->rs); + MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_LOADR4_MEMBASE, tmpr, vt->inst_basereg, soffset); + dreg = mono_regstate_next_float (s->rs); + MONO_EMIT_NEW_UNALU (s, OP_SETFREG, dreg, tmpr); + mono_call_inst_add_outarg_reg (s, call, dreg, tree->backend.reg3, TRUE); } stmt: OP_OUTARG_VT (CEE_LDOBJ (base)) { + MonoCallInst *call = tree->inst_call; + MonoPPCArgInfo *ai = tree->backend.data; MonoInst *vt = state->left->left->tree; - //g_print ("vt size: %d at R%d + %d\n", tree->inst_imm, vt->inst_basereg, vt->inst_offset); - if (tree->inst_imm <= 4) { - tree->opcode = OP_X86_PUSH_MEMBASE; - tree->inst_basereg = vt->inst_basereg; - tree->inst_offset = vt->inst_offset; + int start_reg = ai->reg; + int nregs = ai->size; + int ovf_size = ai->vtsize; + int i, tmpr, soffset, dreg; + int size = 0; + soffset = vt->inst_offset; +/* + Darwin needs some special handling for 1 and 2 byte arguments +*/ +#ifdef __APPLE__ + if (vt->inst_vtype && MONO_TYPE_ISSTRUCT (vt->inst_vtype) && vt->inst_vtype->type != MONO_TYPE_TYPEDBYREF) + size = mono_class_native_size (mono_class_from_mono_type (vt->inst_vtype), NULL); + if (size == 2 || size == 1) { + tmpr = mono_regstate_next_int (s->rs); + if (size == 1) + MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_LOADI1_MEMBASE, tmpr, vt->inst_basereg, soffset); + else + MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_LOADI2_MEMBASE, tmpr, vt->inst_basereg, soffset); + dreg = mono_regstate_next_int (s->rs); + MONO_EMIT_NEW_UNALU (s, OP_SETREG, dreg, tmpr); + mono_call_inst_add_outarg_reg (s, call, dreg, start_reg, FALSE); + } else +#endif + for (i = 0; i < nregs; ++i) { + tmpr = mono_regstate_next_int (s->rs); + MONO_EMIT_NEW_LOAD_MEMBASE (s, tmpr, vt->inst_basereg, soffset); + dreg = mono_regstate_next_int (s->rs); + MONO_EMIT_NEW_UNALU (s, OP_SETREG, dreg, tmpr); + mono_call_inst_add_outarg_reg (s, call, dreg, start_reg + i, FALSE); + soffset += sizeof (gpointer); + } + //g_print ("vt size: %d at R%d + %d\n", ai->offset, vt->inst_basereg, vt->inst_offset); + if (ovf_size != 0) { + mini_emit_memcpy (s, ppc_r1, ai->offset + (soffset - vt->inst_offset), vt->inst_basereg, soffset, ovf_size * sizeof (gpointer), 0); + } +} + +stmt: OP_OUTARG_VT (OP_ICONST) { + MonoCallInst *call = tree->inst_call; + MonoPPCArgInfo *ai = tree->backend.data; + int start_reg = ai->reg; + int nregs = ai->size; + if (nregs) { + tree->opcode = OP_SETREGIMM; + tree->dreg = mono_regstate_next_int (s->rs); + tree->inst_c0 = state->left->tree->inst_c0; mono_bblock_add_inst (s->cbb, tree); + mono_call_inst_add_outarg_reg (s, call, tree->dreg, start_reg, FALSE); } else { - tree->opcode = OP_X86_PUSH_OBJ; - tree->inst_basereg = vt->inst_basereg; - tree->inst_offset = vt->inst_offset; - mono_bblock_add_inst (s->cbb, tree); + g_assert_not_reached (); } } -stmt: OP_OUTARG_VT (OP_ICONST) { - tree->opcode = OP_SETREGIMM; - tree->dreg = tree->unused; - tree->inst_imm = state->left->tree->inst_c0; - mono_bblock_add_inst (s->cbb, tree); +stmt: OP_OUTARG_VT (reg) { + MonoCallInst *call = tree->inst_call; + MonoPPCArgInfo *ai = tree->backend.data; + int start_reg = ai->reg; + int nregs = ai->size; + if (nregs) { + tree->opcode = OP_SETREG; + tree->dreg = mono_regstate_next_int (s->rs); + tree->sreg1 = state->left->reg1; + mono_bblock_add_inst (s->cbb, tree); + mono_call_inst_add_outarg_reg (s, call, tree->dreg, start_reg, FALSE); + } else { + g_assert_not_reached (); + } } stmt: CEE_STIND_R8 (OP_REGVAR, freg) { @@ -254,6 +400,10 @@ freg: OP_LCONV_TO_R8 (lreg) { /* nothing to do - emulated */ } +freg: OP_LCONV_TO_R4 (lreg) { + /* nothing to do - emulated */ +} + freg: OP_LCONV_TO_R_UN (lreg) { /* nothing to do - emulated */ } @@ -287,4 +437,19 @@ reg: OP_CGT_UN (OP_COMPARE (freg, freg)) { state->left->right->reg1); } +reg: CEE_ADD_OVF (reg, reg) "0" { + MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1, state->right->reg1); +} + +reg: CEE_ADD_OVF_UN (reg, reg) "0" { + MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1, state->right->reg1); +} + +reg: CEE_SUB_OVF (reg, reg) "0" { + MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1, state->right->reg1); +} + +reg: CEE_SUB_OVF_UN (reg, reg) "0" { + MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1, state->right->reg1); +} %%