From 72613dfaa22b438aa161bad3a92e87984148ae0d Mon Sep 17 00:00:00 2001 From: Jan Hubicka Date: Fri, 23 Jan 2004 14:24:58 +0100 Subject: [PATCH] * i386.c (ix86_emit_restore_regs_using_mov): Deal with large offsets. From-SVN: r76416 --- gcc/ChangeLog | 4 ++++ gcc/config/i386/i386.c | 21 +++++++++++++++++---- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 99f3135a6df..e1c07a06cd9 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,7 @@ +2003-11-30 Jan Hubicka + + * i386.c (ix86_emit_restore_regs_using_mov): Deal with large offsets. + 2004-01-23 J"orn Rennecke * doc/tm.texi: Insert some weasel words when LOAD_EXTEND_OP diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index b7c7008e683..0cad3f1571d 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -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; } } -- 2.30.2