2005-12-11 Zoltan Varga <vargaz@gmail.com>
[mono.git] / mono / mini / inssel-x86.brg
index 8e402e170de166e8a5c1c1938a0758c21740c45d..44939553877b4b37c507382fd3c088faac11face 100644 (file)
@@ -37,6 +37,7 @@
                } \
        } while (0)
 
+int call_reg_to_call_membase (int opcode);
 
 %%
 
@@ -127,6 +128,17 @@ cflags: OP_COMPARE (CEE_LDIND_U4 (base), reg) {
        mono_bblock_add_inst (s->cbb, tree);
 }
 
+cflags: OP_COMPARE (CEE_LDIND_REF (base), CEE_LDIND_REF (OP_REGVAR)),
+cflags: OP_COMPARE (CEE_LDIND_I (base), CEE_LDIND_REF (OP_REGVAR)),
+cflags: OP_COMPARE (CEE_LDIND_I4 (base), CEE_LDIND_REF (OP_REGVAR)),
+cflags: OP_COMPARE (CEE_LDIND_U4 (base), CEE_LDIND_REF (OP_REGVAR)) {
+       tree->opcode = OP_X86_COMPARE_MEMBASE_REG;
+       tree->inst_basereg = state->left->left->tree->inst_basereg;
+       tree->inst_offset = state->left->left->tree->inst_offset;
+       tree->sreg2 = state->right->left->tree->dreg;
+       mono_bblock_add_inst (s->cbb, tree);
+}
+
 cflags: OP_COMPARE (CEE_LDIND_REF (base), OP_ICONST),
 cflags: OP_COMPARE (CEE_LDIND_I (base), OP_ICONST),
 cflags: OP_COMPARE (CEE_LDIND_I4 (base), OP_ICONST),
@@ -138,6 +150,17 @@ cflags: OP_COMPARE (CEE_LDIND_U4 (base), OP_ICONST) {
        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)),
@@ -149,6 +172,17 @@ cflags: OP_COMPARE (reg, CEE_LDIND_U4 (base)) {
        mono_bblock_add_inst (s->cbb, tree);
 }
 
+cflags: OP_COMPARE (CEE_LDIND_REF (OP_REGVAR), CEE_LDIND_REF (base)),
+cflags: OP_COMPARE (CEE_LDIND_I (OP_REGVAR), CEE_LDIND_I (base)),
+cflags: OP_COMPARE (CEE_LDIND_I4 (OP_REGVAR), CEE_LDIND_I4 (base)),
+cflags: OP_COMPARE (CEE_LDIND_U4 (OP_REGVAR), CEE_LDIND_U4 (base)) {
+       tree->opcode = OP_X86_COMPARE_REG_MEMBASE;
+       tree->sreg2 = state->right->left->tree->inst_basereg;
+       tree->inst_offset = state->right->left->tree->inst_offset;
+       tree->sreg1 = state->left->left->tree->dreg;
+       mono_bblock_add_inst (s->cbb, tree);
+}
+
 cflags : OP_CEQ (OP_COMPARE (OP_CEQ (cflags), OP_ICONST)) {
        tree->opcode = OP_CNE;
        tree->dreg = state->reg1;
@@ -183,39 +217,33 @@ reg: OP_LOCALLOC (OP_ICONST) {
                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);
        }
 }
 
 reg: OP_LOCALLOC (reg) {
        tree->sreg1 = state->left->tree->dreg;
+       tree->dreg = state->reg1;
        mono_bblock_add_inst (s->cbb, tree);
 }
 
 stmt: OP_SETRET (reg) {
-       tree->opcode = OP_MOVE;
-       tree->sreg1 = state->left->reg1;
-       tree->dreg = X86_EAX;
-       mono_bblock_add_inst (s->cbb, tree);
+       MONO_EMIT_UNALU (s, tree, OP_MOVE, X86_EAX, state->left->reg1);
 }
 
 stmt: OP_SETRET (lreg) {
        MONO_EMIT_NEW_UNALU (s, OP_MOVE, X86_EDX, state->left->reg2);
-       tree->opcode = OP_MOVE;
-       tree->sreg1 = state->left->reg1;
-       tree->dreg = X86_EAX;
-       mono_bblock_add_inst (s->cbb, tree);
+       MONO_EMIT_UNALU (s, tree, OP_MOVE, X86_EAX, state->left->reg1);
 }
 
 stmt: OP_SETRET (CEE_LDIND_REF (OP_REGVAR)),
 stmt: OP_SETRET (CEE_LDIND_I (OP_REGVAR)),
 stmt: OP_SETRET (CEE_LDIND_I4 (OP_REGVAR)),
 stmt: OP_SETRET (CEE_LDIND_U4 (OP_REGVAR)) {
-       tree->opcode = OP_MOVE;
-       tree->sreg1 = state->left->left->tree->dreg;
-       tree->dreg = X86_EAX;
-       mono_bblock_add_inst (s->cbb, tree);
+       MONO_EMIT_UNALU (s, tree, OP_MOVE, X86_EAX, state->left->left->tree->dreg);
 }
 
 stmt: OP_SETRET (freg) {
@@ -229,35 +257,33 @@ stmt: OP_SETRET (OP_ICONST) {
        mono_bblock_add_inst (s->cbb, tree);
 }
 
-stmt: OP_OUTARG (reg) {
-       tree->opcode = OP_X86_PUSH;
-       tree->sreg1 = state->left->reg1;
-       mono_bblock_add_inst (s->cbb, tree);
+stmt: OP_SETRET (i8con) {
+       MONO_EMIT_NEW_ICONST (s, X86_EAX, state->left->tree->inst_ls_word);
+       MONO_EMIT_NEW_ICONST (s, X86_EDX, state->left->tree->inst_ms_word);
 }
 
-# we need to reduce this code duplication with some burg syntax extension
-stmt: OP_OUTARG (CEE_LDIND_REF (OP_REGVAR)) {
-       tree->opcode = OP_X86_PUSH;
-       tree->sreg1 = state->left->left->tree->dreg;
-       mono_bblock_add_inst (s->cbb, tree);
-}
-
-stmt: OP_OUTARG (CEE_LDIND_I4 (OP_REGVAR)) {
+stmt: OP_OUTARG (reg) {
        tree->opcode = OP_X86_PUSH;
-       tree->sreg1 = state->left->left->tree->dreg;
+       tree->sreg1 = state->left->reg1;
        mono_bblock_add_inst (s->cbb, tree);
 }
 
-stmt: OP_OUTARG (CEE_LDIND_U4 (OP_REGVAR)) {
+stmt: OP_OUTARG (CEE_LDIND_REF (OP_REGVAR)),
+stmt: OP_OUTARG (CEE_LDIND_I4 (OP_REGVAR)),
+stmt: OP_OUTARG (CEE_LDIND_U4 (OP_REGVAR)),
+stmt: OP_OUTARG (CEE_LDIND_I (OP_REGVAR)) {
        tree->opcode = OP_X86_PUSH;
        tree->sreg1 = state->left->left->tree->dreg;
        mono_bblock_add_inst (s->cbb, tree);
 }
 
-stmt: OP_OUTARG (CEE_LDIND_I (OP_REGVAR)) {
-       tree->opcode = OP_X86_PUSH;
-       tree->sreg1 = state->left->left->tree->dreg;
-       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) {
@@ -287,27 +313,21 @@ stmt: OP_OUTARG (OP_ICONST) {
        mono_bblock_add_inst (s->cbb, tree);
 }
 
-stmt: OP_OUTARG (CEE_LDIND_I4 (base)) {
-       tree->opcode = OP_X86_PUSH_MEMBASE;
-       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);
-}
-
-stmt: OP_OUTARG (CEE_LDIND_U4 (base)) {
-       tree->opcode = OP_X86_PUSH_MEMBASE;
-       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);
-}
+stmt: OP_OUTARG (i8con) {
+       MonoInst *ins;
+       ins = mono_mempool_alloc0 (s->mempool, sizeof (MonoInst));
+       ins->opcode = OP_X86_PUSH_IMM;
+       ins->inst_imm = state->left->tree->inst_ms_word;
+       mono_bblock_add_inst (s->cbb, ins);
 
-stmt: OP_OUTARG (CEE_LDIND_I (base)) {
-       tree->opcode = OP_X86_PUSH_MEMBASE;
-       tree->inst_basereg = state->left->left->tree->inst_basereg;
-       tree->inst_offset = state->left->left->tree->inst_offset;
+       tree->opcode = OP_X86_PUSH_IMM;
+       tree->inst_imm = state->left->tree->inst_ls_word;
        mono_bblock_add_inst (s->cbb, tree);
 }
 
+stmt: OP_OUTARG (CEE_LDIND_I4 (base)),
+stmt: OP_OUTARG (CEE_LDIND_U4 (base)),
+stmt: OP_OUTARG (CEE_LDIND_I (base)),
 stmt: OP_OUTARG (CEE_LDIND_REF (base)) {
        tree->opcode = OP_X86_PUSH_MEMBASE;
        tree->inst_basereg = state->left->left->tree->inst_basereg;
@@ -315,12 +335,6 @@ stmt: OP_OUTARG (CEE_LDIND_REF (base)) {
        mono_bblock_add_inst (s->cbb, tree);
 }
 
-stmt: OP_OUTARG (CEE_LDIND_REF (OP_REGVAR)) {
-       tree->opcode = OP_X86_PUSH;
-       tree->sreg1 = state->left->left->tree->dreg;
-       mono_bblock_add_inst (s->cbb, tree);
-}
-
 stmt: OP_OUTARG (CEE_LDOBJ (reg)) {
        tree->opcode = OP_X86_PUSH;
        tree->sreg1 = state->left->reg1;
@@ -388,35 +402,20 @@ stmt: OP_OUTARG_VT (OP_ICONST) {
 
 stmt: OP_OUTARG_VT (reg) {
        tree->opcode = OP_X86_PUSH;
-       tree->sreg1 = state->left->tree->dreg;
-       mono_bblock_add_inst (s->cbb, tree);
-}
-
-reg: OP_LDADDR (OP_REGOFFSET) "1" {
-       if (state->left->tree->inst_offset) {
-               tree->opcode = OP_X86_LEA_MEMBASE;
-               tree->sreg1 = state->left->tree->inst_basereg;
-               tree->inst_imm = state->left->tree->inst_offset;
-               tree->dreg = state->reg1;
-       } else {
-               tree->opcode = OP_MOVE;
-               tree->sreg1 = state->left->tree->inst_basereg;
-               tree->dreg = state->reg1;
-       }
+       tree->sreg1 = state->left->reg1;
        mono_bblock_add_inst (s->cbb, tree);
 }
 
-reg: CEE_LDOBJ (OP_REGOFFSET) "1" {
+reg: OP_LDADDR (OP_REGOFFSET),
+reg: CEE_LDOBJ (OP_REGOFFSET) {
        if (state->left->tree->inst_offset) {
                tree->opcode = OP_X86_LEA_MEMBASE;
-               tree->sreg1 = state->left->tree->inst_basereg;
                tree->inst_imm = state->left->tree->inst_offset;
-               tree->dreg = state->reg1;
-       } else {
+       } else
                tree->opcode = OP_MOVE;
-               tree->sreg1 = state->left->tree->inst_basereg;
-               tree->dreg = state->reg1;
-       }
+       
+       tree->sreg1 = state->left->tree->inst_basereg;
+       tree->dreg = state->reg1;
        mono_bblock_add_inst (s->cbb, tree);
 }
 
@@ -724,8 +723,92 @@ lreg: OP_LSHR_UN (lreg, OP_ICONST) "0" {
        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 {
+reg: OP_ATOMIC_ADD_NEW_I4 (base, reg),
+reg: OP_ATOMIC_ADD_I4 (base, reg) {
+       tree->opcode = tree->opcode;
+       tree->inst_basereg = state->left->tree->inst_basereg; 
+       tree->inst_offset = state->left->tree->inst_offset; 
+       tree->dreg = state->reg1;
+       tree->sreg2 = state->right->reg1;
+    
+       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; 
+    
        mono_bblock_add_inst (s->cbb, tree);
 }
 
+# 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);
+}
+
+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;
+       mono_bblock_add_inst (s->cbb, tree);
+}
+
+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);
+}
+
+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;
+}