X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmini%2Finssel-sparc.brg;h=c5368f37e89a7b4477d01e1a6660fdb8c802cc28;hb=c4901fe17ff0f38aa4ab19678336a8ac15a6ae3f;hp=f5b1d363833821527a4e72e810eb97b1c5b63675;hpb=84b709f11124509f2268722945b803ee7e631d93;p=mono.git diff --git a/mono/mini/inssel-sparc.brg b/mono/mini/inssel-sparc.brg index f5b1d363833..c5368f37e89 100644 --- a/mono/mini/inssel-sparc.brg +++ b/mono/mini/inssel-sparc.brg @@ -10,6 +10,14 @@ # (C) 2002 Ximian, Inc. # +stmt: CEE_STIND_I8 (OP_REGVAR, reg) { + MONO_EMIT_NEW_UNALU (s, OP_MOVE, state->left->tree->dreg, state->right->reg1); +} + +reg: CEE_LDIND_I8 (OP_REGVAR) { + MONO_EMIT_NEW_UNALU (s, OP_MOVE, state->reg1, state->left->tree->dreg); +} + stmt: CEE_STIND_I8 (OP_REGVAR, lreg) { /* this should only happen for methods returning a long */ MONO_EMIT_NEW_UNALU (s, OP_MOVE, state->left->tree->dreg, state->right->reg2); @@ -52,6 +60,14 @@ freg: OP_FCONV_TO_R4 (freg) "0" { MONO_EMIT_UNALU (s, tree, OP_FMOVE, state->reg1, state->left->reg1); } +freg: CEE_LDIND_R8 (OP_REGVAR) { + MONO_EMIT_UNALU (s, tree, OP_FMOVE, state->reg1, state->left->tree->dreg); +} + +freg: CEE_LDIND_R4 (OP_REGVAR) { + MONO_EMIT_UNALU (s, tree, OP_FMOVE, state->reg1, state->left->tree->dreg); +} + reg: OP_LOCALLOC (reg) { tree->sreg1 = state->left->reg1; tree->dreg = state->reg1; @@ -85,10 +101,14 @@ base: OP_LDADDR (reg) { } stmt: OP_OUTARG (OP_LDADDR (reg)) { + MonoCallInst *call = (MonoCallInst*)tree->inst_right->inst_left; + tree->opcode = OP_SETREG; - tree->dreg = tree->unused; + tree->dreg = mono_regstate_next_int (s->rs); tree->sreg1 = state->left->left->tree->dreg; mono_bblock_add_inst (s->cbb, tree); + + mono_call_inst_add_outarg_reg (s, call, tree->dreg, tree->unused, FALSE); } stmt: OP_SETRET (reg) { @@ -121,108 +141,198 @@ stmt: OP_SETRET (OP_ICONST) { } stmt: OP_OUTARG (reg) { + MonoCallInst *call = (MonoCallInst*)tree->inst_right->inst_left; + 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->unused, FALSE); } stmt: OP_OUTARG (OP_REGVAR) { + MonoCallInst *call = (MonoCallInst*)tree->inst_right->inst_left; + 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); -} -stmt: OP_OUTARG (freg) { - /* floating-point <-> integer transfer must go through memory */ - MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORER4_MEMBASE_REG, tree->inst_basereg, - tree->inst_imm, state->left->reg1); - MONO_EMIT_NEW_LOAD_MEMBASE (s, tree->unused, tree->inst_basereg, tree->inst_imm); + mono_call_inst_add_outarg_reg (s, call, tree->dreg, tree->unused, FALSE); } stmt: OP_OUTARG (OP_ICONST) { + MonoCallInst *call = (MonoCallInst*)tree->inst_right->inst_left; + + 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, tree->unused, FALSE); +} + +stmt: OP_OUTARG (OP_I8CONST) { + MonoCallInst *call = (MonoCallInst*)tree->inst_right->inst_left; + 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->unused, FALSE); +} cost { + MBCOND (sizeof (gpointer) == 8); + + return 0; } stmt: OP_OUTARG (CEE_LDIND_R4 (base)) { + MonoCallInst *call = (MonoCallInst*)tree->inst_right->inst_left; + tree->opcode = OP_LOADI4_MEMBASE; - tree->dreg = tree->unused; + tree->dreg = mono_regstate_next_int (s->rs); 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); + + mono_call_inst_add_outarg_reg (s, call, tree->dreg, tree->unused, FALSE); +} + +stmt: OP_SPARC_OUTARG_FLOAT (freg) { + MonoCallInst *call = (MonoCallInst*)tree->inst_right->inst_left; + int dreg = mono_regstate_next_int (s->rs); + /* floating-point <-> integer transfer must go through memory */ + MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORER4_MEMBASE_REG, tree->inst_right->inst_basereg, + tree->inst_right->inst_imm, state->left->reg1); + MONO_EMIT_NEW_LOAD_MEMBASE (s, dreg, tree->inst_right->inst_basereg, tree->inst_right->inst_imm); + + mono_call_inst_add_outarg_reg (s, call, dreg, tree->unused, FALSE); } stmt: OP_SPARC_OUTARG_REGPAIR (lreg) { - MONO_EMIT_NEW_UNALU (s, OP_SETREG, tree->unused, state->left->reg2); + MonoCallInst *call = (MonoCallInst*)tree->inst_right->inst_left; + int dreg = mono_regstate_next_int (s->rs); + int dreg2 = mono_regstate_next_int (s->rs); + + MONO_EMIT_NEW_UNALU (s, OP_SETREG, dreg, state->left->reg2); tree->opcode = OP_SETREG; - tree->dreg = tree->unused + 1; + tree->dreg = dreg2; tree->sreg1 = state->left->reg1; mono_bblock_add_inst (s->cbb, tree); + + mono_call_inst_add_outarg_reg (s, call, dreg, tree->unused, FALSE); + mono_call_inst_add_outarg_reg (s, call, dreg2, tree->unused + 1, FALSE); } -stmt: OP_SPARC_OUTARG_REGPAIR (freg) { - MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORER8_MEMBASE_REG, tree->inst_basereg, - tree->inst_imm, state->left->reg1); +stmt: OP_SPARC_OUTARG_REGPAIR_FLOAT (freg) { + MonoCallInst *call = (MonoCallInst*)tree->inst_right->inst_left; + int dreg = mono_regstate_next_int (s->rs); + int dreg2 = mono_regstate_next_int (s->rs); + + MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORER8_MEMBASE_REG, tree->inst_right->inst_basereg, + tree->inst_right->inst_imm, state->left->reg1); /* floating-point <-> integer transfer must go through memory */ /* Load into a register pair */ - MONO_EMIT_NEW_LOAD_MEMBASE (s, tree->unused, tree->inst_basereg, tree->inst_imm); - MONO_EMIT_NEW_LOAD_MEMBASE (s, tree->unused + 1, tree->inst_basereg, tree->inst_imm + 4); + MONO_EMIT_NEW_LOAD_MEMBASE (s, dreg, tree->inst_right->inst_basereg, tree->inst_right->inst_imm); + MONO_EMIT_NEW_LOAD_MEMBASE (s, dreg2, tree->inst_right->inst_basereg, tree->inst_right->inst_imm + 4); + + mono_call_inst_add_outarg_reg (s, call, dreg, tree->unused, FALSE); + mono_call_inst_add_outarg_reg (s, call, dreg2, tree->unused + 1, FALSE); } stmt: OP_SPARC_OUTARG_MEM (reg) { - if (tree->inst_imm & 0x1) - tree->opcode = OP_STOREI1_MEMBASE_REG; - else if (tree->inst_imm & 0x2) - tree->opcode = OP_STOREI2_MEMBASE_REG; - else - tree->opcode = OP_STOREI4_MEMBASE_REG; - tree->inst_destbasereg = tree->inst_basereg; - tree->inst_offset = tree->inst_imm; + guint32 offset = tree->inst_right->inst_imm; + if (mono_sparc_is_sparc64 ()) { + guint32 real_offset = tree->inst_right->inst_imm - MONO_SPARC_STACK_BIAS; + /* Correct for the additions in get_call_info () */ + offset = MONO_SPARC_STACK_BIAS + (real_offset & ~(7)); + tree->opcode = OP_STOREI8_MEMBASE_REG; + } + else { + if (offset & 0x1) + tree->opcode = OP_STOREI1_MEMBASE_REG; + else if (offset & 0x2) + tree->opcode = OP_STOREI2_MEMBASE_REG; + else + tree->opcode = OP_STOREI4_MEMBASE_REG; + } + tree->inst_destbasereg = tree->inst_right->inst_basereg; + tree->inst_offset = offset; tree->sreg1 = state->left->reg1; mono_bblock_add_inst (s->cbb, tree); } stmt: OP_SPARC_OUTARG_MEM (freg) { - MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORER4_MEMBASE_REG, tree->inst_basereg, - tree->inst_imm, state->left->reg1); + MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORER4_MEMBASE_REG, tree->inst_right->inst_basereg, + tree->inst_right->inst_imm, state->left->reg1); } stmt: OP_SPARC_OUTARG_MEMPAIR (lreg) { - MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI4_MEMBASE_REG, tree->inst_basereg, - tree->inst_imm, state->left->reg2); + MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI4_MEMBASE_REG, tree->inst_right->inst_basereg, + tree->inst_right->inst_imm, state->left->reg2); tree->opcode = OP_STOREI4_MEMBASE_REG; - tree->inst_destbasereg = tree->inst_basereg; - tree->inst_offset = tree->inst_imm + 4; + tree->inst_destbasereg = tree->inst_right->inst_basereg; + tree->inst_offset = tree->inst_right->inst_imm + 4; tree->sreg1 = state->left->reg1; mono_bblock_add_inst (s->cbb, tree); } stmt: OP_SPARC_OUTARG_MEMPAIR (freg) { - MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORER8_MEMBASE_REG, tree->inst_basereg, - tree->inst_imm, state->left->reg1); + MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORER8_MEMBASE_REG, tree->inst_right->inst_basereg, + tree->inst_right->inst_imm, state->left->reg1); } stmt: OP_SPARC_OUTARG_SPLIT_REG_STACK (lreg) { - MONO_EMIT_NEW_UNALU (s, OP_SETREG, tree->unused, state->left->reg2); + MonoCallInst *call = (MonoCallInst*)tree->inst_right->inst_left; + + int dreg = mono_regstate_next_int (s->rs); + MONO_EMIT_NEW_UNALU (s, OP_SETREG, dreg, state->left->reg2); tree->opcode = OP_STOREI4_MEMBASE_REG; - tree->inst_destbasereg = tree->inst_basereg; - tree->inst_offset = tree->inst_imm + 4; + tree->inst_destbasereg = tree->inst_right->inst_basereg; + tree->inst_offset = tree->inst_right->inst_imm + 4; tree->sreg1 = state->left->reg1; mono_bblock_add_inst (s->cbb, tree); + + mono_call_inst_add_outarg_reg (s, call, dreg, tree->unused, FALSE); } stmt: OP_SPARC_OUTARG_SPLIT_REG_STACK (freg) { - MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORER8_MEMBASE_REG, tree->inst_basereg, - tree->inst_imm, state->left->reg1); + MonoCallInst *call = (MonoCallInst*)tree->inst_right->inst_left; + + int dreg = mono_regstate_next_int (s->rs); + MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORER8_MEMBASE_REG, tree->inst_right->inst_basereg, + tree->inst_right->inst_imm, state->left->reg1); /* floating-point <-> integer transfer must go through memory */ /* Load most significant word into register */ - MONO_EMIT_NEW_LOAD_MEMBASE (s, tree->unused, tree->inst_basereg, tree->inst_imm); + MONO_EMIT_NEW_LOAD_MEMBASE (s, dreg, tree->inst_right->inst_basereg, tree->inst_right->inst_imm); + + mono_call_inst_add_outarg_reg (s, call, dreg, tree->unused, FALSE); } +stmt: OP_SPARC_OUTARG_FLOAT_REG (freg) { + MonoCallInst *call = (MonoCallInst*)tree->inst_right->inst_left; + + tree->opcode = OP_SPARC_SETFREG_FLOAT; + 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->unused, TRUE); +} + +stmt: OP_SPARC_OUTARG_DOUBLE_REG (freg) { + MonoCallInst *call = (MonoCallInst*)tree->inst_right->inst_left; + + tree->opcode = OP_SETFREG; + 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->unused, TRUE); +} + # Handles scalar valuetypes like RuntimeTypeHandle reg: OP_OUTARG_VT (OP_ICONST) { MONO_EMIT_NEW_STORE_MEMBASE_IMM (s, OP_STOREI4_MEMBASE_IMM, sparc_sp, tree->inst_c1, state->left->tree->inst_c0); @@ -249,22 +359,35 @@ reg: OP_OUTARG_VT (base) { } stmt: OP_OUTARG (CEE_LDIND_REF (OP_REGVAR)) { + MonoCallInst *call = (MonoCallInst*)tree->inst_right->inst_left; + tree->opcode = OP_SETREG; tree->sreg1 = state->left->left->tree->dreg; - tree->dreg = tree->unused; + tree->dreg = mono_regstate_next_int (s->rs); mono_bblock_add_inst (s->cbb, tree); + + mono_call_inst_add_outarg_reg (s, call, tree->dreg, tree->unused, FALSE); } stmt: OP_OUTARG (CEE_LDIND_REF (OP_REGOFFSET)) { - MONO_EMIT_NEW_LOAD_MEMBASE (s, tree->unused, state->left->left->tree->inst_basereg, + MonoCallInst *call = (MonoCallInst*)tree->inst_right->inst_left; + + int dreg = mono_regstate_next_int (s->rs); + MONO_EMIT_NEW_LOAD_MEMBASE (s, dreg, state->left->left->tree->inst_basereg, state->left->left->tree->inst_offset); + + mono_call_inst_add_outarg_reg (s, call, dreg, tree->unused, FALSE); } stmt: OP_OUTARG_VT (OP_ICONST) { + MonoCallInst *call = (MonoCallInst*)tree->inst_right->inst_left; + tree->opcode = OP_SETREGIMM; - tree->dreg = tree->unused; + tree->dreg = mono_regstate_next_int (s->rs); tree->inst_imm = state->left->tree->inst_c0; mono_bblock_add_inst (s->cbb, tree); + + mono_call_inst_add_outarg_reg (s, call, tree->dreg, tree->unused, FALSE); } stmt: CEE_STIND_R8 (OP_REGVAR, freg) { @@ -397,6 +520,15 @@ reg: OP_LOCALLOC (reg) { # Optimizations # +reg: CEE_LDIND_REF (OP_REGVAR), +reg: CEE_LDIND_I (OP_REGVAR), +reg: CEE_LDIND_I4 (OP_REGVAR), +reg: CEE_LDIND_U4 (OP_REGVAR) "0" { + /* This rule might not work on all archs, hence it is sparc only */ + state->reg1 = state->left->tree->dreg; + tree->dreg = state->reg1; +} + stmt: CEE_STIND_I1 (OP_REGVAR, OP_ICONST) { tree->opcode = OP_ICONST; tree->dreg = state->left->tree->dreg; @@ -447,21 +579,16 @@ stmt: CEE_STIND_REF (OP_REGVAR, CEE_LDIND_REF(base)) { mono_bblock_add_inst (s->cbb, tree); } -stmt: OP_SETRET (CEE_LDIND_REF(base)) { - MONO_EMIT_LOAD_MEMBASE (s, tree, sparc_i0, state->left->left->tree->inst_basereg, - state->left->left->tree->inst_offset); - mono_bblock_add_inst (s->cbb, tree); -} - -stmt: OP_SETRET (CEE_LDIND_I4(base)) { - MONO_EMIT_LOAD_MEMBASE (s, tree, sparc_i0, state->left->left->tree->inst_basereg, - state->left->left->tree->inst_offset); - mono_bblock_add_inst (s->cbb, tree); -} - -stmt: OP_SETRET (CEE_LDIND_I(base)) { - MONO_EMIT_LOAD_MEMBASE (s, tree, sparc_i0, state->left->left->tree->inst_basereg, - state->left->left->tree->inst_offset); +stmt: OP_SETRET (CEE_LDIND_I1(base)), +stmt: OP_SETRET (CEE_LDIND_U1(base)), +stmt: OP_SETRET (CEE_LDIND_I2(base)), +stmt: OP_SETRET (CEE_LDIND_U2(base)), +stmt: OP_SETRET (CEE_LDIND_I(base)), +stmt: OP_SETRET (CEE_LDIND_REF(base)), +stmt: OP_SETRET (CEE_LDIND_I4(base)), +stmt: OP_SETRET (CEE_LDIND_U4(base)) { + MONO_EMIT_LOAD_MEMBASE_OP (s, tree, ldind_to_load_membase (state->left->tree->opcode), + sparc_i0, state->left->left->tree->inst_basereg, state->left->left->tree->inst_offset); mono_bblock_add_inst (s->cbb, tree); } @@ -479,30 +606,38 @@ stmt: OP_SETRET (CEE_LDIND_I(OP_REGVAR)) { mono_bblock_add_inst (s->cbb, tree); } -stmt: OP_OUTARG (CEE_LDIND_I (OP_REGVAR)) { - tree->opcode = OP_SETREG; - tree->dreg = tree->unused; - tree->sreg1 = state->left->left->tree->dreg; - mono_bblock_add_inst (s->cbb, tree); -} - +stmt: OP_OUTARG (CEE_LDIND_I (OP_REGVAR)), stmt: OP_OUTARG (CEE_LDIND_I4 (OP_REGVAR)) { + MonoCallInst *call = (MonoCallInst*)tree->inst_right->inst_left; + tree->opcode = OP_SETREG; - tree->dreg = tree->unused; + tree->dreg = mono_regstate_next_int (s->rs); tree->sreg1 = state->left->left->tree->dreg; mono_bblock_add_inst (s->cbb, tree); + + mono_call_inst_add_outarg_reg (s, call, tree->dreg, tree->unused, FALSE); } stmt: OP_OUTARG (CEE_LDIND_REF(base)) { - MONO_EMIT_LOAD_MEMBASE (s, tree, tree->unused, state->left->left->tree->inst_basereg, + MonoCallInst *call = (MonoCallInst*)tree->inst_right->inst_left; + + int dreg = mono_regstate_next_int (s->rs); + MONO_EMIT_LOAD_MEMBASE (s, tree, dreg, state->left->left->tree->inst_basereg, state->left->left->tree->inst_offset); mono_bblock_add_inst (s->cbb, tree); + + mono_call_inst_add_outarg_reg (s, call, dreg, tree->unused, FALSE); } stmt: OP_OUTARG (CEE_LDIND_I4(base)) { - MONO_EMIT_LOAD_MEMBASE (s, tree, tree->unused, state->left->left->tree->inst_basereg, + MonoCallInst *call = (MonoCallInst*)tree->inst_right->inst_left; + + int dreg = mono_regstate_next_int (s->rs); + MONO_EMIT_LOAD_MEMBASE_OP (s, tree, OP_LOADI4_MEMBASE, dreg, state->left->left->tree->inst_basereg, state->left->left->tree->inst_offset); mono_bblock_add_inst (s->cbb, tree); + + mono_call_inst_add_outarg_reg (s, call, dreg, tree->unused, FALSE); } reg: OP_LDADDR (OP_REGOFFSET) "1" { @@ -516,6 +651,12 @@ reg: OP_LDADDR (OP_REGOFFSET) "1" { mono_bblock_add_inst (s->cbb, tree); } +lreg: OP_LNEG (lreg) "3" { + /* The one in inssel.brg doesn't work, this one is based on gcc code */ + MONO_EMIT_NEW_BIALU (s, OP_SUBCC, state->reg1, 0, state->left->reg1); + MONO_EMIT_NEW_BIALU (s, OP_SBB, state->reg2, 0, state->left->reg2); +} + # FIXME: This rule was commented out in inssel.brg, why ? reg: CEE_REM (reg, OP_ICONST) { MONO_EMIT_BIALU_IMM (s, tree, OP_REM_IMM, state->reg1, state->left->reg1, state->right->tree->inst_c0); @@ -533,6 +674,8 @@ reg: OP_LOCALLOC (OP_ICONST) { mono_bblock_add_inst (s->cbb, tree); } +# FIXME: Optimized MEMCPY for copying valuetypes + # Optimized version for initializing valuetypes on the stack stmt: OP_MEMSET (OP_LDADDR(OP_REGOFFSET)) "0" { int size = tree->unused; @@ -549,7 +692,7 @@ stmt: OP_MEMSET (OP_LDADDR(OP_REGOFFSET)) "0" { /* Target address must be dword aligned */ if ((tree->inst_imm == 0) && (size >= 8) && - (destreg == sparc_fp) && ((offset % 8) == 0)) { + (destreg == sparc_fp) && (((offset - MONO_SPARC_STACK_BIAS) % 8) == 0)) { if (!mono_sparc_is_v9 ()) { /* Use STD */ MONO_EMIT_NEW_ICONST (s, sparc_g1, 0); @@ -628,4 +771,27 @@ stmt: OP_MEMSET (reg) "0" { } } + +stmt: CEE_STIND_R8 (base, OP_R8CONST) { + /* fp constants are pricy on SPARC */ + guint64 d = *(guint64*)state->right->tree->inst_p0; + + if (d == 0) { + if (sizeof (gpointer) == 8) { + MONO_EMIT_STORE_MEMBASE (s, tree, OP_STOREI8_MEMBASE_REG, state->left->tree->inst_basereg, state->left->tree->inst_offset, sparc_g0); + } + else { + /* STOREI8 would write %g1 as well */ + MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI4_MEMBASE_REG, state->left->tree->inst_basereg, state->left->tree->inst_offset, sparc_g0); + MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI4_MEMBASE_REG, state->left->tree->inst_basereg, state->left->tree->inst_offset + 4, sparc_g0); + } + } + else { + state->right->tree->dreg = state->reg1; + mono_bblock_add_inst (s->cbb, state->right->tree); + MONO_EMIT_STORE_MEMBASE (s, tree, OP_STORER8_MEMBASE_REG, state->left->tree->inst_basereg, + state->left->tree->inst_offset, state->reg1); + } +} + %%