2006-07-02 Zoltan Varga <vargaz@gmail.com>
[mono.git] / mono / mini / inssel-sparc.brg
index db6c7a6a1814a719b05d7ae3f2054cc94020e982..c5368f37e89a7b4477d01e1a6660fdb8c802cc28 100644 (file)
 # (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);
@@ -31,6 +39,10 @@ freg: OP_LCONV_TO_R8 (lreg) {
        mono_bblock_add_inst (s->cbb, tree);
 }
 
+freg: OP_LCONV_TO_R8 (lreg) {
+       /* Dummy rule */
+}
+
 freg: OP_LCONV_TO_R4 (lreg) {
        tree->sreg1 = state->left->reg1;
        tree->dreg = state->reg1;
@@ -43,11 +55,17 @@ freg: CEE_CONV_R_UN (reg) {
        mono_bblock_add_inst (s->cbb, tree);
 }
 
-reg: OP_LOCALLOC (OP_ICONST) {
-       /* microcoded in mini-sparc.c */
-       tree->sreg1 = mono_regstate_next_int (s->rs);
-       MONO_EMIT_NEW_ICONST (s, tree->sreg1, state->left->tree->inst_c0);
-       mono_bblock_add_inst (s->cbb, tree);
+freg: OP_FCONV_TO_R4 (freg) "0" {
+       /* The conversion is done elsewhere */
+       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) {
@@ -83,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) {
@@ -105,7 +127,9 @@ stmt: OP_SETRET (lreg) {
 }
 
 stmt: OP_SETRET (freg) {
-       MONO_EMIT_UNALU (s, tree, OP_FMOVE, sparc_f0, state->left->reg1);
+       tree->opcode = OP_SETFRET;
+       tree->sreg1 = state->left->reg1;
+       tree->dreg = sparc_f0;
        mono_bblock_add_inst (s->cbb, tree);
 }
 
@@ -117,115 +141,217 @@ 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 = 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);
+}
+
+stmt: OP_OUTARG (OP_I8CONST) {
+       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);
+} 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) {
-       int size = tree->unused;
        MONO_EMIT_NEW_STORE_MEMBASE_IMM (s, OP_STOREI4_MEMBASE_IMM, sparc_sp, tree->inst_c1, state->left->tree->inst_c0);
        MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, state->reg1, sparc_sp, tree->inst_c1);
 }
 
+reg: OP_OUTARG_VT (OP_AOTCONST) {
+       MONO_EMIT_NEW_AOTCONST (s, state->reg1, state->left->tree->inst_p0, state->left->tree->inst_c1);
+       MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI4_MEMBASE_REG, sparc_sp, tree->inst_c1, state->reg1);
+       MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, state->reg1, sparc_sp, tree->inst_c1);
+}
+
+# FIXME: Unify this with the previous rule
+reg: OP_OUTARG_VT (OP_REFANYTYPE (reg)) {
+       MONO_EMIT_NEW_LOAD_MEMBASE (s, state->reg1, state->left->left->reg1, G_STRUCT_OFFSET (MonoTypedRef, type));
+       MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI4_MEMBASE_REG, sparc_sp, tree->inst_c1, state->reg1);
+       MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, state->reg1, sparc_sp, tree->inst_c1);
+}      
+
 reg: OP_OUTARG_VT (base) {
        int size = tree->unused;
        mini_emit_memcpy (s, sparc_sp, tree->inst_c1, state->left->tree->inst_basereg, state->left->tree->inst_offset, size, 0);
@@ -233,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) {
@@ -256,19 +395,11 @@ stmt: CEE_STIND_R8 (OP_REGVAR, freg) {
 }
 
 reg: CEE_LDIND_I1 (OP_REGVAR) {
-       /* All regs are 32 bit */
-       tree->opcode = OP_MOVE;
-       tree->sreg1 = state->left->tree->dreg;
-       tree->dreg = state->reg1;
-       mono_bblock_add_inst (s->cbb, tree);
+       MONO_EMIT_UNALU (s, tree, CEE_CONV_I1, state->reg1, state->left->tree->dreg);
 }
 
 reg: CEE_LDIND_I2 (OP_REGVAR) {
-       /* All regs are 32 bit */
-       tree->opcode = OP_MOVE;
-       tree->sreg1 = state->left->tree->dreg;
-       tree->dreg = state->reg1;
-       mono_bblock_add_inst (s->cbb, tree);
+       MONO_EMIT_UNALU (s, tree, CEE_CONV_I2, state->reg1, state->left->tree->dreg);
 }
 
 stmt: CEE_BNE_UN (fpcflags) {
@@ -325,13 +456,34 @@ stmt: CEE_POP (freg) "0" {
        /* nothing to do */
 }     
 
+stmt: OP_START_HANDLER {
+     mono_bblock_add_inst (s->cbb, tree);
+}
+
+stmt: CEE_ENDFINALLY {
+       //MonoInst *spvar = mono_find_spvar_for_region (s, s->cbb->region);
+       //MONO_EMIT_NEW_LOAD_MEMBASE (s, sparc_o7, spvar->inst_basereg, spvar->inst_offset); 
+       mono_bblock_add_inst (s->cbb, tree);
+}
+
+stmt: OP_ENDFILTER (reg) {
+       //MonoInst *spvar = mono_find_spvar_for_region (s, s->cbb->region);
+       //MONO_EMIT_NEW_LOAD_MEMBASE (s, sparc_o7, spvar->inst_basereg, spvar->inst_offset); 
+       tree->sreg1 = state->left->reg1;
+       mono_bblock_add_inst (s->cbb, tree);
+}
+
 stmt: OP_START_HANDLER {
 }
 
 stmt: CEE_ENDFINALLY {
+       mono_bblock_add_inst (s->cbb, tree);
 }
 
 stmt: OP_ENDFILTER (reg) {
+       tree->sreg1 = state->left->reg1;
+       tree->dreg = state->reg1;
+       mono_bblock_add_inst (s->cbb, tree);
 }
 
 reg: OP_CEQ (OP_COMPARE (freg, freg)) {        
@@ -359,40 +511,133 @@ reg: OP_CGT_UN (OP_COMPARE (freg, freg)) {
                         state->left->right->reg1);
 }
 
+reg: OP_LOCALLOC (reg) {
+       tree->sreg1 = state->left->tree->dreg;
+       mono_bblock_add_inst (s->cbb, tree);
+}
+
 #
 # Optimizations
 #
 
-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);  
+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;
+       tree->inst_c0 = state->right->tree->inst_c0;
        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);  
+stmt: CEE_STIND_I2 (OP_REGVAR, OP_ICONST) {
+       tree->opcode = OP_ICONST;
+       tree->dreg = state->left->tree->dreg;
+       tree->inst_c0 = state->right->tree->inst_c0;
        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: CEE_STIND_I4 (OP_REGVAR, CEE_ADD (reg, OP_ICONST)) {
+       MONO_EMIT_BIALU_IMM (s, tree, OP_ADD_IMM, state->left->tree->dreg, state->right->left->reg1, state->right->right->tree->inst_c0);
+}
+
+stmt: CEE_STIND_REF (OP_REGVAR, CEE_ADD (reg, OP_ICONST)) {
+       MONO_EMIT_BIALU_IMM (s, tree, OP_ADD_IMM, state->left->tree->dreg, state->right->left->reg1, state->right->right->tree->inst_c0);
+}
+
+stmt: CEE_STIND_I4 (OP_REGVAR, CEE_SUB (reg, OP_ICONST)) {
+       MONO_EMIT_BIALU_IMM (s, tree, OP_SUB_IMM, state->left->tree->dreg, state->right->left->reg1, state->right->right->tree->inst_c0);
+}
+
+stmt: CEE_STIND_REF (OP_REGVAR, CEE_SUB (reg, OP_ICONST)) {
+       MONO_EMIT_BIALU_IMM (s, tree, OP_SUB_IMM, state->left->tree->dreg, state->right->left->reg1, state->right->right->tree->inst_c0);
+}
+
+stmt: CEE_STIND_I4 (OP_REGVAR, CEE_ADD (reg, reg)) {
+       MONO_EMIT_BIALU (s, tree, CEE_ADD, state->left->tree->dreg, state->right->left->reg1, state->right->right->reg1);
+}
+
+stmt: CEE_STIND_REF (OP_REGVAR, CEE_ADD (reg, reg)) {
+       MONO_EMIT_BIALU (s, tree, CEE_ADD, state->left->tree->dreg, state->right->left->reg1, state->right->right->reg1);
+}
+
+stmt: CEE_STIND_I4 (OP_REGVAR, CEE_LDIND_I4(base)) {
+       MONO_EMIT_LOAD_MEMBASE (s, tree, state->left->tree->dreg, state->right->left->tree->inst_basereg, 
+                               state->right->left->tree->inst_offset); 
+       mono_bblock_add_inst (s->cbb, tree);
+}
+
+stmt: CEE_STIND_REF (OP_REGVAR, CEE_LDIND_REF(base)) {
+       MONO_EMIT_LOAD_MEMBASE (s, tree, state->left->tree->dreg, state->right->left->tree->inst_basereg, 
+                               state->right->left->tree->inst_offset); 
        mono_bblock_add_inst (s->cbb, tree);
 }
 
-stmt: OP_OUTARG (CEE_LDIND_I (OP_REGVAR)) {
+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);
+}
+
+stmt: OP_SETRET (CEE_LDIND_I4(OP_REGVAR)) {
+       tree->opcode = OP_SETREG;
+       tree->dreg = sparc_i0;
+       tree->sreg1 = state->left->left->tree->dreg;
+       mono_bblock_add_inst (s->cbb, tree);
+}
+
+stmt: OP_SETRET (CEE_LDIND_I(OP_REGVAR)) {
        tree->opcode = OP_SETREG;
-       tree->dreg = tree->unused;
+       tree->dreg = sparc_i0;
        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)) {
+       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)) {
+       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" {
@@ -406,11 +651,85 @@ 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);
 }
 
+# This one too
+reg: CEE_DIV (reg, OP_ICONST) {
+       MONO_EMIT_BIALU_IMM (s, tree, OP_DIV_IMM, state->reg1, state->left->reg1, state->right->tree->inst_c0);
+}
+
+reg: OP_LOCALLOC (OP_ICONST) {
+       tree->opcode = OP_SPARC_LOCALLOC_IMM;
+       tree->inst_c0 = state->left->tree->inst_c0;
+       tree->dreg = state->reg1;
+       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;
+       int offset = state->left->left->tree->inst_offset;
+       int destreg = state->left->left->tree->inst_basereg;
+       int val_reg;
+
+       if (tree->inst_imm) {
+               val_reg = mono_regstate_next_int (s->rs);
+               MONO_EMIT_NEW_ICONST (s, val_reg, tree->inst_imm);
+       }
+       else
+               val_reg = sparc_g0;
+
+       /* Target address must be dword aligned */
+       if ((tree->inst_imm == 0) && (size >= 8) && 
+               (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);
+
+                       while (size >= 8) {
+                               MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI8_MEMBASE_REG, destreg, offset, val_reg);
+                               offset += 8;
+                               size -= 8;
+                       }
+               }
+               else {
+                       /* Use STX imm */
+                       while (size >= 8) {
+                               MONO_EMIT_NEW_STORE_MEMBASE_IMM (s, OP_STOREI8_MEMBASE_IMM, destreg, offset, 0);
+                               offset += 8;
+                               size -= 8;
+                       }
+               }
+       }
+               
+       while (size >= 4) {
+               MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI4_MEMBASE_REG, destreg, offset, val_reg);
+               offset += 4;
+               size -= 4;
+       }
+       while (size >= 2) {
+               MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI2_MEMBASE_REG, destreg, offset, val_reg);
+               offset += 2;
+               size -= 2;
+       }
+       while (size >= 1) {
+               MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI1_MEMBASE_REG, destreg, offset, val_reg);
+               offset += 1;
+               size -= 1;
+       }
+}              
+
 stmt: OP_MEMSET (reg) "0" {
        int size = tree->unused;
        int offset = 0;
@@ -427,10 +746,8 @@ stmt: OP_MEMSET (reg) "0" {
        /* FIXME: This assumes the destination is dword aligned */
        /*
        if ((tree->inst_imm == 0) && (size >= 8)) {
-               MONO_EMIT_NEW_ICONST (s, sparc_g1, 0);
-
                while (size >= 8) {
-                       MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI8_MEMBASE_REG, destreg, offset, val_reg);
+                       MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI8_MEMBASE_IMM, destreg, offset, sparc_g0);
                        offset += 8;
                        size -= 8;
                }
@@ -454,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);
+       }
+}
+
 %%