mips.c (mips_frame_set): New.
authorRichard Sandiford <rsandifo@redhat.com>
Tue, 18 Sep 2001 16:24:32 +0000 (16:24 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Tue, 18 Sep 2001 16:24:32 +0000 (16:24 +0000)
* config/mips/mips.c (mips_frame_set): New.
(mips_emit_frame_related_store): When storing two 32-bit FPRs, use
a parallel frame-related expression with a set for each register.

From-SVN: r45678

gcc/ChangeLog
gcc/config/mips/mips.c

index 014f18e9320915f6ebffc76117fd2e262837af40..178137419c8aeaf806631bf9395e3630c61221b1 100644 (file)
@@ -1,3 +1,9 @@
+2001-09-18  Richard Sandiford  <rsandifo@redhat.com>
+
+       * config/mips/mips.c (mips_frame_set): New.
+       (mips_emit_frame_related_store): When storing two 32-bit FPRs, use
+       a parallel frame-related expression with a set for each register.
+
 2001-09-18  Philip Blundell  <philb@gnu.org>
 
        * config/arm/lib1funcs.asm (L_dvmd_lnx): Don't rely on kernel
index dee6503ee545398e33bc224780c931bb568a98c2..92d4e84b39c3cdec0c21279f4f58f9072598f02a 100644 (file)
@@ -94,6 +94,8 @@ static void block_move_call                   PARAMS ((rtx, rtx, rtx));
 static rtx mips_add_large_offset_to_sp         PARAMS ((HOST_WIDE_INT,
                                                         FILE *));
 static void mips_annotate_frame_insn           PARAMS ((rtx, rtx));
+static rtx mips_frame_set                      PARAMS ((enum machine_mode,
+                                                        int, int));
 static void mips_emit_frame_related_store      PARAMS ((rtx, rtx,
                                                         HOST_WIDE_INT));
 static void save_restore_insns                 PARAMS ((int, rtx,
@@ -6599,8 +6601,27 @@ mips_annotate_frame_insn (insn, dwarf_pattern)
                                      REG_NOTES (insn));
 }
 
+/* Return a frame-related rtx that stores register REGNO at (SP + OFFSET).
+   The expression should only be used to store single registers.  */
+
+static rtx
+mips_frame_set (mode, regno, offset)
+     enum machine_mode mode;
+     int regno;
+     int offset;
+{
+  rtx address = plus_constant (stack_pointer_rtx, offset);
+  rtx set = gen_rtx_SET (mode,
+                        gen_rtx_MEM (mode, address),
+                        gen_rtx_REG (mode, regno));
+  RTX_FRAME_RELATED_P (set) = 1;
+  return set;
+}
+
+
 /* Emit a move instruction that stores REG in MEM.  Make the instruction
-   frame related and note that it stores REG at (SP + OFFSET).  */
+   frame related and note that it stores REG at (SP + OFFSET).  This
+   function may be asked to store an FPR pair.  */
 
 static void
 mips_emit_frame_related_store (mem, reg, offset)
@@ -6608,11 +6629,24 @@ mips_emit_frame_related_store (mem, reg, offset)
      rtx reg;
      HOST_WIDE_INT offset;
 {
-  rtx dwarf_address = plus_constant (stack_pointer_rtx, offset);
-  rtx dwarf_mem = gen_rtx_MEM (GET_MODE (reg), dwarf_address);
+  rtx dwarf_expr;
 
-  mips_annotate_frame_insn (emit_move_insn (mem, reg),
-                           gen_rtx_SET (GET_MODE (reg), dwarf_mem, reg));
+  if (GET_MODE (reg) == DFmode && ! TARGET_FLOAT64)
+    {
+      /* Two registers are being stored, so the frame-related expression
+        must be a PARALLEL rtx with one SET for each register.  The
+        higher numbered register is stored in the lower address on
+        big-endian targets.  */
+      int regno1 = TARGET_BIG_ENDIAN ? REGNO (reg) + 1 : REGNO (reg);
+      int regno2 = TARGET_BIG_ENDIAN ? REGNO (reg) : REGNO (reg) + 1;
+      rtx set1 = mips_frame_set (SFmode, regno1, offset);
+      rtx set2 = mips_frame_set (SFmode, regno2, offset + UNITS_PER_FPREG);
+      dwarf_expr = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, set1, set2));
+    }
+  else
+    dwarf_expr = mips_frame_set (GET_MODE (reg), REGNO (reg), offset);
+      
+  mips_annotate_frame_insn (emit_move_insn (mem, reg), dwarf_expr);
 }
 
 static void