} \
} while (0)
+int call_reg_to_call_membase (int opcode);
%%
mono_bblock_add_inst (s->cbb, tree);
}
+
+cflags: OP_COMPARE (CEE_LDIND_REF (OP_ICONST), OP_ICONST),
+cflags: OP_COMPARE (CEE_LDIND_I (OP_ICONST), OP_ICONST),
+cflags: OP_COMPARE (CEE_LDIND_I4 (OP_ICONST), OP_ICONST),
+cflags: OP_COMPARE (CEE_LDIND_U4 (OP_ICONST), OP_ICONST) {
+ tree->opcode = OP_X86_COMPARE_MEM_IMM;
+ tree->inst_offset = state->left->left->tree->inst_c0;
+ tree->inst_imm = state->right->tree->inst_c0;
+ mono_bblock_add_inst (s->cbb, tree);
+}
+
cflags: OP_COMPARE (reg, CEE_LDIND_REF (base)),
cflags: OP_COMPARE (reg, CEE_LDIND_I (base)),
cflags: OP_COMPARE (reg, CEE_LDIND_I4 (base)),
MONO_EMIT_NEW_ICONST (s, tree->sreg1, state->left->tree->inst_c0);
mono_bblock_add_inst (s->cbb, tree);
} else {
- MONO_EMIT_NEW_BIALU_IMM (s, OP_SUB_IMM, X86_ESP, X86_ESP, state->left->tree->inst_c0);
+ guint32 size = state->left->tree->inst_c0;
+ size = (size + (MONO_ARCH_FRAME_ALIGNMENT - 1)) & ~ (MONO_ARCH_FRAME_ALIGNMENT - 1);
+ MONO_EMIT_NEW_BIALU_IMM (s, OP_SUB_IMM, X86_ESP, X86_ESP, size);
MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, X86_ESP);
}
}
mono_bblock_add_inst (s->cbb, tree);
}
+stmt: OP_OUTARG (OP_GOT_ENTRY (CEE_LDIND_I (OP_REGVAR), OP_PATCH_INFO)) {
+ MonoInst *ins;
+ ins = mono_mempool_alloc0 (s->mempool, sizeof (MonoInst));
+ ins->opcode = OP_X86_PUSH_GOT_ENTRY;
+ ins->inst_right = state->left->right->tree;
+ ins->inst_basereg = state->left->left->left->tree->dreg;
+ mono_bblock_add_inst (s->cbb, ins);
+}
+
stmt: OP_OUTARG (lreg) {
MONO_EMIT_NEW_UNALU (s, OP_X86_PUSH, -1, state->left->reg2);
tree->opcode = OP_X86_PUSH;
MONO_EMIT_BIALU_IMM (s, tree, OP_LSHR_UN_IMM, state->reg1, state->left->reg1, state->right->tree->inst_c0);
}
-reg: OP_X86_TLS_GET {
- tree->dreg = state->reg1;
- mono_bblock_add_inst (s->cbb, tree);
-}
-
+reg: OP_ATOMIC_ADD_NEW_I4 (base, reg),
reg: OP_ATOMIC_ADD_I4 (base, reg) {
- tree->opcode = OP_ATOMIC_ADD_I4;
+ tree->opcode = tree->opcode;
tree->inst_basereg = state->left->tree->inst_basereg;
tree->inst_offset = state->left->tree->inst_offset;
tree->dreg = state->reg1;
mono_bblock_add_inst (s->cbb, tree);
}
-stmt: OP_ATOMIC_ADD_I4 (base, OP_ICONST) {
- tree->opcode = OP_ATOMIC_ADD_IMM_PREV_I4;
- tree->inst_basereg = state->left->tree->inst_basereg;
- tree->inst_offset = state->left->tree->inst_offset;
- tree->dreg = state->reg1;
- tree->inst_imm = state->right->tree->inst_c0;
+reg: OP_ATOMIC_EXCHANGE_I4 (base, reg) {
+ tree->opcode = OP_ATOMIC_EXCHANGE_I4;
+ 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);
}
-stmt: CEE_STIND_I4 (OP_REGVAR, OP_ATOMIC_ADD_I4 (base, OP_ICONST)) {
- tree->opcode = OP_ATOMIC_ADD_IMM_PREV_I4;
- tree->inst_basereg = state->right->left->tree->inst_basereg;
- tree->inst_offset = state->right->left->tree->inst_offset;
- tree->dreg = state->left->tree->dreg;
- tree->inst_imm = state->right->right->tree->inst_c0;
-
+# Optimized call instructions
+# mono_arch_patch_delegate_trampoline depends on these
+reg: OP_CALL_REG (CEE_LDIND_I (base)),
+freg: OP_FCALL_REG (CEE_LDIND_I (base)),
+reg: OP_LCALL_REG (CEE_LDIND_I (base)) {
+ tree->opcode = call_reg_to_call_membase (tree->opcode);
+ tree->inst_basereg = state->left->left->tree->inst_basereg;
+ tree->inst_offset = state->left->left->tree->inst_offset;
+ tree->dreg = state->reg1;
mono_bblock_add_inst (s->cbb, tree);
}
-reg: OP_ATOMIC_ADD_IMM_I4 (base, OP_ICONST) {
- tree->opcode = OP_ATOMIC_ADD_IMM_I4;
- tree->inst_basereg = state->left->tree->inst_basereg;
- tree->inst_offset = state->left->tree->inst_offset;
+lreg: OP_LCALL_REG (CEE_LDIND_I (base)) {
+ tree->opcode = call_reg_to_call_membase (tree->opcode);
+ tree->inst_basereg = state->left->left->tree->inst_basereg;
+ tree->inst_offset = state->left->left->tree->inst_offset;
tree->dreg = state->reg1;
- tree->inst_imm = state->right->tree->inst_c0;
-
mono_bblock_add_inst (s->cbb, tree);
}
-stmt: CEE_STIND_I4 (OP_REGVAR, OP_ATOMIC_ADD_IMM_I4 (base, OP_ICONST)) {
- tree->opcode = OP_ATOMIC_ADD_IMM_I4;
- tree->inst_basereg = state->right->left->tree->inst_basereg;
- tree->inst_offset = state->right->left->tree->inst_offset;
- tree->dreg = state->left->tree->dreg;
- tree->inst_imm = state->right->right->tree->inst_c0;
-
+stmt: OP_VOIDCALL_REG (CEE_LDIND_I (base)) {
+ tree->opcode = call_reg_to_call_membase (tree->opcode);
+ 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);
}
-reg: OP_ATOMIC_EXCHANGE_I4 (base, reg) {
- tree->opcode = OP_ATOMIC_EXCHANGE_I4;
- 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;
-
+stmt: OP_VCALL_REG (CEE_LDIND_I (base), reg) {
+ mono_arch_emit_this_vret_args (s, (MonoCallInst*)tree, -1, -1, state->right->reg1);
+
+ tree->opcode = call_reg_to_call_membase (tree->opcode);
+ tree->inst_basereg = state->left->left->tree->inst_basereg;
+ tree->inst_offset = state->left->left->tree->inst_offset;
+ tree->dreg = state->reg1;
mono_bblock_add_inst (s->cbb, tree);
}
+# Optimized ldind(reg) rules
+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" {
+ state->reg1 = state->left->tree->dreg;
+ tree->dreg = state->reg1;
+}
+
%%
+
+int
+call_reg_to_call_membase (int opcode)
+{
+ switch (opcode) {
+ case OP_CALL_REG:
+ return OP_CALL_MEMBASE;
+ case OP_FCALL_REG:
+ return OP_FCALL_MEMBASE;
+ case OP_VCALL_REG:
+ return OP_VCALL_MEMBASE;
+ case OP_LCALL_REG:
+ return OP_LCALL_MEMBASE;
+ case OP_VOIDCALL_REG:
+ return OP_VOIDCALL_MEMBASE;
+ default:
+ g_assert_not_reached ();
+ }
+
+ return -1;
+}