%% # # inssel-sparc.brg: burg file for special sparc instructions # # Author: # Dietmar Maurer (dietmar@ximian.com) # Paolo Molaro (lupus@ximian.com) # # (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); MONO_EMIT_NEW_UNALU (s, OP_MOVE, state->left->tree->dreg + 1, state->right->reg1); } lreg: CEE_LDIND_I8 (OP_REGVAR) { /* reg2 contains the most significant word */ MONO_EMIT_NEW_UNALU (s, OP_MOVE, state->reg2, state->left->tree->dreg); tree->opcode = OP_SETREG; tree->dreg = state->reg1; tree->sreg1 = state->left->tree->dreg + 1; mono_bblock_add_inst (s->cbb, tree); } freg: OP_LCONV_TO_R8 (lreg) { tree->sreg1 = state->left->reg1; tree->dreg = state->reg1; 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; mono_bblock_add_inst (s->cbb, tree); } freg: CEE_CONV_R_UN (reg) { tree->sreg1 = state->left->reg1; tree->dreg = state->reg1; 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) { tree->sreg1 = state->left->reg1; tree->dreg = state->reg1; mono_bblock_add_inst (s->cbb, tree); } base: OP_SPARC_INARG_VT (base) { MONO_EMIT_NEW_LOAD_MEMBASE (s, state->reg1, state->left->tree->inst_basereg, state->left->tree->inst_offset); } reg: OP_LDADDR (OP_SPARC_INARG_VT (base)) { MONO_EMIT_NEW_LOAD_MEMBASE (s, state->reg1, state->left->left->tree->inst_basereg, state->left->left->tree->inst_offset); } reg: CEE_LDOBJ (OP_SPARC_INARG_VT (base)) { MONO_EMIT_NEW_LOAD_MEMBASE (s, state->reg1, state->left->left->tree->inst_basereg, state->left->left->tree->inst_offset); } base: OP_LDADDR (reg) { /* tree->inst_basereg = mono_regstate_next_int (s->rs); tree->inst_offset = 0; MONO_EMIT_NEW_LOAD_MEMBASE (s, tree->inst_basereg, state->left->tree->dreg, 0); */ tree->inst_basereg = state->left->tree->dreg; tree->inst_offset = 0; } stmt: OP_OUTARG (OP_LDADDR (reg)) { MonoCallInst *call = (MonoCallInst*)tree->inst_right->inst_left; tree->opcode = OP_SETREG; 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) { tree->opcode = OP_MOVE; tree->sreg1 = state->left->reg1; tree->dreg = sparc_i0; mono_bblock_add_inst (s->cbb, tree); } stmt: OP_SETRET (lreg) { MONO_EMIT_NEW_UNALU (s, OP_MOVE, sparc_i0, state->left->reg2); tree->opcode = OP_MOVE; tree->sreg1 = state->left->reg1; tree->dreg = sparc_i1; mono_bblock_add_inst (s->cbb, tree); } stmt: OP_SETRET (freg) { tree->opcode = OP_SETFRET; tree->sreg1 = state->left->reg1; tree->dreg = sparc_f0; mono_bblock_add_inst (s->cbb, tree); } stmt: OP_SETRET (OP_ICONST) { tree->opcode = OP_ICONST; tree->inst_c0 = state->left->tree->inst_c0; tree->dreg = sparc_i0; mono_bblock_add_inst (s->cbb, tree); } stmt: OP_OUTARG (reg) { MonoCallInst *call = (MonoCallInst*)tree->inst_right->inst_left; 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, tree->unused, FALSE); } stmt: OP_OUTARG (OP_REGVAR) { MonoCallInst *call = (MonoCallInst*)tree->inst_right->inst_left; tree->opcode = OP_SETREG; 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->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 = 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 = 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) { 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 = 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_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, 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) { 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_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_right->inst_basereg, tree->inst_right->inst_imm, state->left->reg2); tree->opcode = OP_STOREI4_MEMBASE_REG; 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_right->inst_basereg, tree->inst_right->inst_imm, state->left->reg1); } stmt: OP_SPARC_OUTARG_SPLIT_REG_STACK (lreg) { 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_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) { 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, 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); 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); MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, state->reg1, sparc_sp, tree->inst_c1); } 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 = 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)) { 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 = 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) { /* nothing to do: the value is already on the FP stack */ } reg: CEE_LDIND_I1 (OP_REGVAR) { MONO_EMIT_UNALU (s, tree, CEE_CONV_I1, state->reg1, state->left->tree->dreg); } reg: CEE_LDIND_I2 (OP_REGVAR) { MONO_EMIT_UNALU (s, tree, CEE_CONV_I2, state->reg1, state->left->tree->dreg); } stmt: CEE_BNE_UN (fpcflags) { tree->opcode = OP_FBNE_UN; mono_bblock_add_inst (s->cbb, tree); } stmt: CEE_BEQ (fpcflags) { tree->opcode = OP_FBEQ; mono_bblock_add_inst (s->cbb, tree); } stmt: CEE_BLT (fpcflags) { tree->opcode = OP_FBLT; mono_bblock_add_inst (s->cbb, tree); } stmt: CEE_BLT_UN (fpcflags) { tree->opcode = OP_FBLT_UN; mono_bblock_add_inst (s->cbb, tree); } stmt: CEE_BGT (fpcflags) { tree->opcode = OP_FBGT; mono_bblock_add_inst (s->cbb, tree); } stmt: CEE_BGT_UN (fpcflags) { tree->opcode = OP_FBGT_UN; mono_bblock_add_inst (s->cbb, tree); } stmt: CEE_BGE (fpcflags) { tree->opcode = OP_FBGE; mono_bblock_add_inst (s->cbb, tree); } stmt: CEE_BGE_UN (fpcflags) { tree->opcode = OP_FBGE_UN; mono_bblock_add_inst (s->cbb, tree); } stmt: CEE_BLE (fpcflags) { tree->opcode = OP_FBLE; mono_bblock_add_inst (s->cbb, tree); } stmt: CEE_BLE_UN (fpcflags) { tree->opcode = OP_FBLE_UN; mono_bblock_add_inst (s->cbb, tree); } 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)) { MONO_EMIT_BIALU (s, tree, OP_FCEQ, state->reg1, state->left->left->reg1, state->left->right->reg1); } reg: OP_CLT (OP_COMPARE (freg, freg)) { MONO_EMIT_BIALU (s, tree, OP_FCLT, state->reg1, state->left->left->reg1, state->left->right->reg1); } reg: OP_CLT_UN (OP_COMPARE (freg, freg)) { MONO_EMIT_BIALU (s, tree, OP_FCLT_UN, state->reg1, state->left->left->reg1, state->left->right->reg1); } reg: OP_CGT (OP_COMPARE (freg, freg)) { MONO_EMIT_BIALU (s, tree, OP_FCGT, state->reg1, state->left->left->reg1, state->left->right->reg1); } reg: OP_CGT_UN (OP_COMPARE (freg, freg)) { MONO_EMIT_BIALU (s, tree, OP_FCGT_UN, state->reg1, state->left->left->reg1, state->left->right->reg1); } reg: OP_LOCALLOC (reg) { tree->sreg1 = state->left->tree->dreg; mono_bblock_add_inst (s->cbb, tree); } # # 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; tree->inst_c0 = state->right->tree->inst_c0; mono_bblock_add_inst (s->cbb, tree); } 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: 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_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 = 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 = 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" { if (state->left->tree->inst_offset) { MONO_EMIT_BIALU_IMM (s, tree, OP_ADD_IMM, state->reg1, state->left->tree->inst_basereg, state->left->tree->inst_offset); } else { tree->opcode = OP_MOVE; tree->sreg1 = state->left->tree->inst_basereg; tree->dreg = state->reg1; } 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; int destreg = state->left->reg1; 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; /* FIXME: This assumes the destination is dword aligned */ /* if ((tree->inst_imm == 0) && (size >= 8)) { while (size >= 8) { MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI8_MEMBASE_IMM, destreg, offset, sparc_g0); 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: 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); } } %%