Implement support for OP_LOADR4_MEMBASE/STORER4_MEMBASE with big offsets on ARM....
authorZoltan Varga <vargaz@gmail.com>
Thu, 17 May 2012 22:49:42 +0000 (00:49 +0200)
committerZoltan Varga <vargaz@gmail.com>
Thu, 17 May 2012 22:50:34 +0000 (00:50 +0200)
mono/mini/mini-arm.c

index 9d4fa72af3b01ec1ccdf428e7c522a67534eef4d..79062b31421ba1ac34983fd40c80c714e1a88c8d 100644 (file)
@@ -2680,7 +2680,7 @@ branch_cc_table [] = {
        ARMCOND_LO
 };
 
-#define NEW_INS(cfg,dest,op) do {       \
+#define ADD_NEW_INS(cfg,dest,op) do {       \
                MONO_INST_NEW ((cfg), (dest), (op)); \
         mono_bblock_insert_before_ins (bb, ins, (dest)); \
        } while (0)
@@ -2782,7 +2782,7 @@ loop_start:
                case OP_IOR_IMM:
                case OP_IXOR_IMM:
                        if ((imm8 = mono_arm_is_rotated_imm8 (ins->inst_imm, &rot_amount)) < 0) {
-                               NEW_INS (cfg, temp, OP_ICONST);
+                               ADD_NEW_INS (cfg, temp, OP_ICONST);
                                temp->inst_c0 = ins->inst_imm;
                                temp->dreg = mono_alloc_ireg (cfg);
                                ins->sreg2 = temp->dreg;
@@ -2809,7 +2809,7 @@ loop_start:
                                ins->inst_imm = imm8;
                                break;
                        }
-                       NEW_INS (cfg, temp, OP_ICONST);
+                       ADD_NEW_INS (cfg, temp, OP_ICONST);
                        temp->inst_c0 = ins->inst_imm;
                        temp->dreg = mono_alloc_ireg (cfg);
                        ins->sreg2 = temp->dreg;
@@ -2824,7 +2824,7 @@ loop_start:
                                ins->next->opcode = OP_COND_EXC_NC;
                        break;
                case OP_LOCALLOC_IMM:
-                       NEW_INS (cfg, temp, OP_ICONST);
+                       ADD_NEW_INS (cfg, temp, OP_ICONST);
                        temp->inst_c0 = ins->inst_imm;
                        temp->dreg = mono_alloc_ireg (cfg);
                        ins->sreg1 = temp->dreg;
@@ -2841,7 +2841,7 @@ loop_start:
                         */
                        if (arm_is_imm12 (ins->inst_offset))
                                break;
-                       NEW_INS (cfg, temp, OP_ICONST);
+                       ADD_NEW_INS (cfg, temp, OP_ICONST);
                        temp->inst_c0 = ins->inst_offset;
                        temp->dreg = mono_alloc_ireg (cfg);
                        ins->sreg2 = temp->dreg;
@@ -2852,7 +2852,7 @@ loop_start:
                case OP_LOADI1_MEMBASE:
                        if (arm_is_imm8 (ins->inst_offset))
                                break;
-                       NEW_INS (cfg, temp, OP_ICONST);
+                       ADD_NEW_INS (cfg, temp, OP_ICONST);
                        temp->inst_c0 = ins->inst_offset;
                        temp->dreg = mono_alloc_ireg (cfg);
                        ins->sreg2 = temp->dreg;
@@ -2864,23 +2864,34 @@ loop_start:
                                break;
                        low_imm = ins->inst_offset & 0x1ff;
                        if ((imm8 = mono_arm_is_rotated_imm8 (ins->inst_offset & ~0x1ff, &rot_amount)) >= 0) {
-                               NEW_INS (cfg, temp, OP_ADD_IMM);
+                               ADD_NEW_INS (cfg, temp, OP_ADD_IMM);
                                temp->inst_imm = ins->inst_offset & ~0x1ff;
                                temp->sreg1 = ins->inst_basereg;
                                temp->dreg = mono_alloc_ireg (cfg);
                                ins->inst_basereg = temp->dreg;
                                ins->inst_offset = low_imm;
-                               break;
+                       } else {
+                               MonoInst *add_ins;
+
+                               ADD_NEW_INS (cfg, temp, OP_ICONST);
+                               temp->inst_c0 = ins->inst_offset;
+                               temp->dreg = mono_alloc_ireg (cfg);
+
+                               ADD_NEW_INS (cfg, add_ins, OP_IADD);
+                               add_ins->sreg1 = ins->inst_basereg;
+                               add_ins->sreg2 = temp->dreg;
+                               add_ins->dreg = mono_alloc_ireg (cfg);
+
+                               ins->inst_basereg = add_ins->dreg;
+                               ins->inst_offset = 0;
                        }
-                       /* VFP/FPA doesn't have indexed load instructions */
-                       g_assert_not_reached ();
                        break;
                case OP_STORE_MEMBASE_REG:
                case OP_STOREI4_MEMBASE_REG:
                case OP_STOREI1_MEMBASE_REG:
                        if (arm_is_imm12 (ins->inst_offset))
                                break;
-                       NEW_INS (cfg, temp, OP_ICONST);
+                       ADD_NEW_INS (cfg, temp, OP_ICONST);
                        temp->inst_c0 = ins->inst_offset;
                        temp->dreg = mono_alloc_ireg (cfg);
                        ins->sreg2 = temp->dreg;
@@ -2889,7 +2900,7 @@ loop_start:
                case OP_STOREI2_MEMBASE_REG:
                        if (arm_is_imm8 (ins->inst_offset))
                                break;
-                       NEW_INS (cfg, temp, OP_ICONST);
+                       ADD_NEW_INS (cfg, temp, OP_ICONST);
                        temp->inst_c0 = ins->inst_offset;
                        temp->dreg = mono_alloc_ireg (cfg);
                        ins->sreg2 = temp->dreg;
@@ -2901,23 +2912,33 @@ loop_start:
                                break;
                        low_imm = ins->inst_offset & 0x1ff;
                        if ((imm8 = mono_arm_is_rotated_imm8 (ins->inst_offset & ~ 0x1ff, &rot_amount)) >= 0 && arm_is_fpimm8 (low_imm)) {
-                               NEW_INS (cfg, temp, OP_ADD_IMM);
+                               ADD_NEW_INS (cfg, temp, OP_ADD_IMM);
                                temp->inst_imm = ins->inst_offset & ~0x1ff;
                                temp->sreg1 = ins->inst_destbasereg;
                                temp->dreg = mono_alloc_ireg (cfg);
                                ins->inst_destbasereg = temp->dreg;
                                ins->inst_offset = low_imm;
-                               break;
+                       } else {
+                               MonoInst *add_ins;
+
+                               ADD_NEW_INS (cfg, temp, OP_ICONST);
+                               temp->inst_c0 = ins->inst_offset;
+                               temp->dreg = mono_alloc_ireg (cfg);
+
+                               ADD_NEW_INS (cfg, add_ins, OP_IADD);
+                               add_ins->sreg1 = ins->inst_destbasereg;
+                               add_ins->sreg2 = temp->dreg;
+                               add_ins->dreg = mono_alloc_ireg (cfg);
+
+                               ins->inst_destbasereg = add_ins->dreg;
+                               ins->inst_offset = 0;
                        }
-                       /*g_print ("fail with: %d (%d, %d)\n", ins->inst_offset, ins->inst_offset & ~0x1ff, low_imm);*/
-                       /* VFP/FPA doesn't have indexed store instructions */
-                       g_assert_not_reached ();
                        break;
                case OP_STORE_MEMBASE_IMM:
                case OP_STOREI1_MEMBASE_IMM:
                case OP_STOREI2_MEMBASE_IMM:
                case OP_STOREI4_MEMBASE_IMM:
-                       NEW_INS (cfg, temp, OP_ICONST);
+                       ADD_NEW_INS (cfg, temp, OP_ICONST);
                        temp->inst_c0 = ins->inst_imm;
                        temp->dreg = mono_alloc_ireg (cfg);
                        ins->sreg1 = temp->dreg;