]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
* i386.c (ix86_emit_restore_regs_using_mov): Deal with large offsets.
authorJan Hubicka <jh@suse.cz>
Fri, 23 Jan 2004 13:24:58 +0000 (14:24 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Fri, 23 Jan 2004 13:24:58 +0000 (14:24 +0100)
From-SVN: r76416

gcc/ChangeLog
gcc/config/i386/i386.c

index 99f3135a6df222d4f36b4201cad37cceaa9187f7..e1c07a06cd964816de0ceee04779bb4ee443281d 100644 (file)
@@ -1,3 +1,7 @@
+2003-11-30  Jan Hubicka  <jh@suse.cz>
+
+       * i386.c (ix86_emit_restore_regs_using_mov):  Deal with large offsets.
+
 2004-01-23  J"orn Rennecke <joern.rennecke@superh.com>
 
        * doc/tm.texi: Insert some weasel words when LOAD_EXTEND_OP
index b7c7008e6836f38e51b26e4502a0c1b5d507e29b..0cad3f1571d4a54060b306814347f369b9b817f5 100644 (file)
@@ -808,7 +808,7 @@ static int ix86_split_to_parts (rtx, rtx *, enum machine_mode);
 static int ix86_nsaved_regs (void);
 static void ix86_emit_save_regs (void);
 static void ix86_emit_save_regs_using_mov (rtx, HOST_WIDE_INT);
-static void ix86_emit_restore_regs_using_mov (rtx, int, int);
+static void ix86_emit_restore_regs_using_mov (rtx, HOST_WIDE_INT, int);
 static void ix86_output_function_epilogue (FILE *, HOST_WIDE_INT);
 static void ix86_set_move_mem_attrs_1 (rtx, rtx, rtx, rtx, rtx);
 static void ix86_sched_reorder_ppro (rtx *, rtx *);
@@ -5278,16 +5278,29 @@ ix86_expand_prologue (void)
 /* Emit code to restore saved registers using MOV insns.  First register
    is restored from POINTER + OFFSET.  */
 static void
-ix86_emit_restore_regs_using_mov (rtx pointer, int offset, int maybe_eh_return)
+ix86_emit_restore_regs_using_mov (rtx pointer, HOST_WIDE_INT offset,
+                                 int maybe_eh_return)
 {
   int regno;
+  rtx base_address = gen_rtx_MEM (Pmode, pointer);
 
   for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
     if (ix86_save_reg (regno, maybe_eh_return))
       {
+       /* Ensure that adjust_address won't be forced to produce pointer
+          out of range allowed by x86-64 instruction set.  */
+       if (TARGET_64BIT && offset != trunc_int_for_mode (offset, SImode))
+         {
+           rtx r11;
+
+           r11 = gen_rtx_REG (DImode, FIRST_REX_INT_REG + 3 /* R11 */);
+           emit_move_insn (r11, GEN_INT (offset));
+           emit_insn (gen_adddi3 (r11, r11, pointer));
+           base_address = gen_rtx_MEM (Pmode, r11);
+           offset = 0;
+         }
        emit_move_insn (gen_rtx_REG (Pmode, regno),
-                       adjust_address (gen_rtx_MEM (Pmode, pointer),
-                                       Pmode, offset));
+                       adjust_address (base_address, Pmode, offset));
        offset += UNITS_PER_WORD;
       }
 }