+int size_to_ia64_load_u_membase_inc (int size);
+int size_to_ia64_store_membase_inc_reg (int size);
+
%%
#
# (C) 2002 Ximian, Inc.
#
+reg: CEE_LDIND_I8 (OP_REGVAR) {
+ state->reg1 = state->left->tree->dreg;
+}
+
+stmt: CEE_STIND_I8 (OP_REGVAR, reg) {
+ MONO_EMIT_NEW_UNALU (s, OP_MOVE, state->left->tree->dreg, state->right->reg1);
+}
+
+reg: CEE_LDIND_I1 (OP_REGVAR) {
+ MONO_EMIT_UNALU (s, tree, OP_SEXT_I1, state->reg1, state->left->tree->dreg);}
+
+reg: CEE_LDIND_I2 (OP_REGVAR) {
+ MONO_EMIT_UNALU (s, tree, OP_SEXT_I2, state->reg1, state->left->tree->dreg);}
+
+stmt: CEE_BEQ (fpcflags) {
+ tree->opcode = OP_FBEQ;
+ mono_bblock_add_inst (s->cbb, tree);
+}
+
+stmt: CEE_BNE_UN (fpcflags) {
+ tree->opcode = OP_FBNE_UN;
+ 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);
+}
+
+fpcflags: OP_COMPARE (freg, freg) {
+ tree->opcode = OP_FCOMPARE;
+ mono_bblock_add_inst (s->cbb, tree);
+}
+
+reg: OP_CEQ (fpcflags) {
+ tree->dreg = state->reg1;
+ tree->opcode = OP_FCEQ;
+ mono_bblock_add_inst (s->cbb, tree);
+}
+
+reg: OP_CLT (fpcflags) {
+ tree->dreg = state->reg1;
+ tree->opcode = OP_FCLT;
+ mono_bblock_add_inst (s->cbb, tree);
+}
+
+reg: OP_CLT_UN (fpcflags) {
+ tree->dreg = state->reg1;
+ tree->opcode = OP_FCLT_UN;
+ mono_bblock_add_inst (s->cbb, tree);
+}
+
+reg: OP_CGT (fpcflags) {
+ tree->dreg = state->reg1;
+ tree->opcode = OP_FCGT;
+ mono_bblock_add_inst (s->cbb, tree);
+}
+
+reg: OP_CGT_UN (fpcflags) {
+ tree->dreg = state->reg1;
+ tree->opcode = OP_FCGT_UN;
+ mono_bblock_add_inst (s->cbb, tree);
+}
+
+freg: OP_LCONV_TO_R8 (reg) {
+ /* FIXME: Move this inssel-long.brg */
+ tree->sreg1 = state->left->reg1;
+ tree->dreg = state->reg1;
+ mono_bblock_add_inst (s->cbb, tree);
+}
+
+freg: OP_LCONV_TO_R4 (reg) {
+ /* FIXME: Move this inssel-long.brg */
+ tree->sreg1 = state->left->reg1;
+ tree->dreg = state->reg1;
+ mono_bblock_add_inst (s->cbb, tree);
+}
+
+stmt: OP_OUTARG_REG (reg) {
+ /* FIXME: Move this to inssel.brg */
+ MonoCallInst *call = (MonoCallInst*)tree->inst_right;
+
+ tree->opcode = OP_MOVE;
+ tree->sreg1 = state->left->reg1;
+ tree->dreg = mono_regstate_next_int (s->rs);
+ mono_bblock_add_inst (s->cbb, tree);
+
+ mono_call_inst_add_outarg_reg (call, tree->dreg, tree->unused, FALSE);
+}
+
+stmt: OP_OUTARG_REG (CEE_LDIND_I (base)),
+stmt: OP_OUTARG_REG (CEE_LDIND_REF (base)),
+stmt: OP_OUTARG_REG (CEE_LDIND_I1 (base)),
+stmt: OP_OUTARG_REG (CEE_LDIND_U1 (base)),
+stmt: OP_OUTARG_REG (CEE_LDIND_I2 (base)),
+stmt: OP_OUTARG_REG (CEE_LDIND_U2 (base)),
+stmt: OP_OUTARG_REG (CEE_LDIND_I4 (base)),
+stmt: OP_OUTARG_REG (CEE_LDIND_U4 (base)),
+stmt: OP_OUTARG_REG (CEE_LDIND_I8 (base)) {
+ /* FIXME: Move this to inssel.brg or inssel-long.brg */
+ MonoCallInst *call = (MonoCallInst*)tree->inst_right;
+ guint32 dreg;
+ MonoInst *base = state->left->left->tree;
+
+ dreg = mono_regstate_next_int (s->rs);
+ MONO_EMIT_LOAD_MEMBASE_OP (s, tree, ldind_to_load_membase (state->left->tree->opcode),
+ dreg, base->inst_basereg, base->inst_offset);
+
+ mono_call_inst_add_outarg_reg (call, tree->dreg, tree->unused, FALSE);
+}
+
+stmt: OP_OUTARG_REG (OP_I8CONST),
+stmt: OP_OUTARG_REG (OP_ICONST) {
+ /* FIXME: Move this to inssel.brg or inssel-long.brg */
+ MonoCallInst *call = (MonoCallInst*)tree->inst_right;
+
+ tree->opcode = OP_ICONST;
+ tree->inst_c0 = state->left->tree->inst_c0;
+ tree->dreg = mono_regstate_next_int (s->rs);
+ mono_bblock_add_inst (s->cbb, tree);
+
+ mono_call_inst_add_outarg_reg (call, tree->dreg, tree->unused, FALSE);
+}
+
+stmt: OP_OUTARG_REG (CEE_LDIND_I (OP_REGVAR)),
+stmt: OP_OUTARG_REG (CEE_LDIND_I8 (OP_REGVAR)),
+stmt: OP_OUTARG_REG (CEE_LDIND_I4 (OP_REGVAR)),
+stmt: OP_OUTARG_REG (CEE_LDIND_U4 (OP_REGVAR)),
+stmt: OP_OUTARG_REG (CEE_LDIND_REF (OP_REGVAR)) {
+ MonoCallInst *call = (MonoCallInst*)tree->inst_right;
+
+ tree->opcode = OP_MOVE;
+ 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 (call, tree->dreg, tree->unused, FALSE);
+}
+
+stmt: OP_OUTARG_FREG (freg) {
+ MonoCallInst *call = (MonoCallInst*)tree->inst_right;
+
+ tree->opcode = OP_FMOVE;
+ tree->sreg1 = state->left->reg1;
+ tree->dreg = mono_regstate_next_float (s->rs);
+ mono_bblock_add_inst (s->cbb, tree);
+
+ mono_call_inst_add_outarg_reg (call, tree->dreg, tree->unused, TRUE);
+}
+
+stmt: OP_OUTARG (reg) {
+ MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI8_MEMBASE_REG, IA64_SP, tree->inst_imm, state->left->reg1);
+}
+
+stmt: OP_OUTARG (freg) {
+ MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORER8_MEMBASE_REG, IA64_SP, tree->inst_imm, state->left->reg1);
+}
+
+stmt: OP_OUTARG_R4 (freg) {
+ MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORER4_MEMBASE_REG, IA64_SP, tree->inst_imm, state->left->reg1);
+}
+
+stmt: OP_OUTARG_REG (OP_LDADDR (OP_REGOFFSET)),
+stmt: OP_OUTARG_REG (CEE_LDOBJ (OP_REGOFFSET)) {
+ /* FIXME: Move this to inssel.brg */
+ MonoCallInst *call = (MonoCallInst*)tree->inst_right;
+
+ tree->opcode = OP_ADD_IMM;
+ tree->sreg1 = state->left->left->tree->inst_basereg;
+ tree->inst_imm = state->left->left->tree->inst_offset;
+ tree->dreg = mono_regstate_next_int (s->rs);
+ mono_bblock_add_inst (s->cbb, tree);
+
+ mono_call_inst_add_outarg_reg (call, tree->dreg, tree->unused, FALSE);
+}
+
stmt: OP_SETRET (reg) {
tree->opcode = OP_MOVE;
tree->sreg1 = state->left->reg1;
mono_bblock_add_inst (s->cbb, tree);
}
-reg: CEE_LDIND_I1 (OP_REGVAR) {
- MONO_EMIT_UNALU (s, tree, OP_SEXT_I1, state->reg1, state->left->tree->dreg);}
+stmt: OP_SETRET (freg) {
+ tree->opcode = OP_FMOVE;
+ tree->sreg1 = state->left->reg1;
+ tree->dreg = MONO_ARCH_FRETREG1;
+ mono_bblock_add_inst (s->cbb, tree);
+}
-reg: CEE_LDIND_I2 (OP_REGVAR) {
- MONO_EMIT_UNALU (s, tree, OP_SEXT_I2, state->reg1, state->left->tree->dreg);}
+# Optimized call instructions
+reg: OP_LCALL_REG (OP_ICONST),
+reg: OP_LCALL_REG (OP_I8CONST) {
+ /* FIXME: Move this to inssel-long.brg */
+ tree->opcode = OP_LCALL;
+ ((MonoCallInst*)tree)->fptr = state->left->tree->inst_p0;
+ tree->dreg = state->reg1;
+ mono_bblock_add_inst (s->cbb, tree);
+}
+
+stmt: OP_OUTARG_VT (CEE_LDOBJ (base), base) {
+ MonoInst *vt = state->left->left->tree;
+ MonoInst *stack_addr = state->right->tree;
+ int sz = stack_addr->inst_imm;
+
+ if (!sz)
+ return;
+
+ mini_emit_memcpy (s, stack_addr->inst_basereg, stack_addr->inst_offset, vt->inst_basereg, vt->inst_offset, sz, 0);
+}
+
+# This handles trees like outarg_vt (refanytype)
+stmt: OP_OUTARG_VT (reg, base) {
+ MonoInst *stack_addr = state->right->tree;
+
+ MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI8_MEMBASE_REG, stack_addr->inst_basereg, stack_addr->inst_offset, state->left->reg1);
+}
+
+stmt: OP_START_HANDLER {
+ mono_bblock_add_inst (s->cbb, tree);
+}
+
+stmt: CEE_ENDFINALLY {
+ mono_bblock_add_inst (s->cbb, tree);
+}
+
+stmt: OP_ENDFILTER (reg) {
+ tree->sreg1 = state->left->reg1;
+ mono_bblock_add_inst (s->cbb, tree);
+}
+
+reg: OP_LOCALLOC (reg) {
+ tree->sreg1 = state->left->reg1;
+ tree->dreg = state->reg1;
+ mono_bblock_add_inst (s->cbb, tree);
+}
+
+reg: CEE_LDIND_REF (OP_REGVAR),
+reg: CEE_LDIND_I (OP_REGVAR),
+reg: CEE_LDIND_I8 (OP_REGVAR),
+reg: CEE_LDIND_I4 (OP_REGVAR),
+reg: CEE_LDIND_U4 (OP_REGVAR) "0" {
+ state->reg1 = state->left->tree->dreg;
+ tree->dreg = state->reg1;
+}
+
+reg: OP_ATOMIC_ADD_NEW_I4 (base, OP_ICONST),
+reg: OP_ATOMIC_ADD_NEW_I8 (base, OP_ICONST) {
+ tree->opcode = tree->opcode == OP_ATOMIC_ADD_NEW_I4 ? OP_IA64_FETCHADD4_IMM : OP_IA64_FETCHADD8_IMM;
+ tree->dreg = state->reg1;
+ tree->inst_imm = state->right->tree->inst_imm;
+ tree->inst_basereg = state->left->tree->inst_basereg;
+ tree->inst_offset = state->left->tree->inst_offset;
+
+ mono_bblock_add_inst (s->cbb, tree);
+}
+
+reg: OP_ATOMIC_EXCHANGE_I4 (base, reg),
+reg: OP_ATOMIC_EXCHANGE_I8 (base, reg) {
+ tree->opcode = tree->opcode;
+ tree->dreg = state->reg1;
+ tree->sreg2 = state->right->reg1;
+ tree->inst_basereg = state->left->tree->inst_basereg;
+ tree->inst_offset = state->left->tree->inst_offset;
+
+ mono_bblock_add_inst (s->cbb, tree);
+}
+
+# Optimized memset implementation
+stmt: OP_MEMSET (base) "0" {
+ int dest_reg, dest_reg2, val_reg, unit, align;
+ int size = tree->unused;
+
+ dest_reg = mono_regstate_next_int (s->rs);
+
+ if (state->left->tree->inst_basereg == s->frame_reg)
+ /* Aligned by mono_allocate_stack_slots */
+ align = 8;
+ else
+ align = 4;
+
+ if (tree->inst_imm == 0)
+ val_reg = IA64_R0;
+ else {
+ val_reg = mono_regstate_next_int (s->rs);
+
+ MONO_EMIT_NEW_ICONST (s, val_reg, tree->inst_imm);
+ }
+
+ MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, dest_reg, state->left->tree->inst_basereg, state->left->tree->inst_offset);
+
+ /* FIXME: Alignment */
+ for (unit = align; unit >= 1; unit = unit >> 1) {
+ dest_reg2 = mono_regstate_next_int (s->rs);
+
+ /* Use two destination regs to increase paralellism */
+ if (size >= 2 * unit) {
+ MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, dest_reg2, state->left->tree->inst_basereg, state->left->tree->inst_offset + unit);
+
+ while (size >= (2 * unit)) {
+ MONO_EMIT_NEW_STORE_MEMBASE (s, size_to_ia64_store_membase_inc_reg (unit), dest_reg, 0, val_reg);
+ MONO_EMIT_NEW_STORE_MEMBASE (s, size_to_ia64_store_membase_inc_reg (unit), dest_reg2, 0, val_reg);
+ size -= 2 * unit;
+ }
+ }
+
+ while (size >= unit) {
+ MONO_EMIT_NEW_STORE_MEMBASE (s, size_to_ia64_store_membase_inc_reg (unit), dest_reg, 0, val_reg);
+ size -= unit;
+ }
+ }
+
+}
+
+# Optimized memcpy implementation
+stmt: OP_MEMCPY (base, base) "0" {
+ int cur_reg, src_reg, dest_reg, unit;
+ int size = tree->unused;
+ int align;
+
+ src_reg = mono_regstate_next_int (s->rs);
+ dest_reg = mono_regstate_next_int (s->rs);
+
+ if ((state->left->tree->inst_basereg == s->frame_reg) &&
+ (state->right->tree->inst_basereg == s->frame_reg))
+ /* Aligned by mono_allocate_stack_slots */
+ align = 8;
+ else
+ align = 4;
+
+ MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, dest_reg, state->left->tree->inst_basereg, state->left->tree->inst_offset);
+ MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, src_reg, state->right->tree->inst_basereg, state->right->tree->inst_offset);
+
+ /* FIXME: Alignment */
+ for (unit = align; unit >= 1; unit = unit >> 1) {
+
+ while (size >= unit) {
+ cur_reg = mono_regstate_next_int (s->rs);
+ MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, size_to_ia64_load_u_membase_inc (unit), cur_reg, src_reg, 0);
+ MONO_EMIT_NEW_STORE_MEMBASE (s, size_to_ia64_store_membase_inc_reg (unit), dest_reg, 0, cur_reg);
+ size -= unit;
+ }
+ }
+}
%%
+
+int
+size_to_ia64_load_u_membase_inc (int size)
+{
+ switch (size) {
+ case 1:
+ return OP_IA64_LOADU1_MEMBASE_INC;
+ case 2:
+ return OP_IA64_LOADU2_MEMBASE_INC;
+ case 4:
+ return OP_IA64_LOADU4_MEMBASE_INC;
+ case 8:
+ return OP_IA64_LOADI8_MEMBASE_INC;
+ default:
+ g_assert_not_reached ();
+ return -1;
+ }
+}
+
+int
+size_to_ia64_store_membase_inc_reg (int size)
+{
+ switch (size) {
+ case 1:
+ return OP_IA64_STOREI1_MEMBASE_INC_REG;
+ case 2:
+ return OP_IA64_STOREI2_MEMBASE_INC_REG;
+ case 4:
+ return OP_IA64_STOREI4_MEMBASE_INC_REG;
+ case 8:
+ return OP_IA64_STOREI8_MEMBASE_INC_REG;
+ default:
+ g_assert_not_reached ();
+ return -1;
+ }
+}