arm.c (add_constant): New parameter address_only, change caller.
authorRichard Earnshaw <rearnsha@arm.com>
Sat, 19 Sep 1998 07:46:45 +0000 (07:46 +0000)
committerRichard Earnshaw <rearnsha@gcc.gnu.org>
Sat, 19 Sep 1998 07:46:45 +0000 (07:46 +0000)
* arm.c (add_constant): New parameter address_only, change caller.
Set it non-zero if taking the address of an item in the pool.
(arm_reorg): Handle cases where we need the address of an item in
the pool.

From-SVN: r22477

gcc/ChangeLog
gcc/config/arm/arm.c

index 6caede77f236d2e74219d38a53980036a3355f9e..9c1bc65323590aeb1442f665e8993f577ed2012c 100644 (file)
@@ -1,3 +1,10 @@
+Sat Sep 19 07:33:36 1998  Richard Earnshaw (rearnsha@arm.com)
+
+       * arm.c (add_constant): New parameter address_only, change caller.
+       Set it non-zero if taking the address of an item in the pool.
+       (arm_reorg): Handle cases where we need the address of an item in
+       the pool.
+
 Sat Sep 19 01:00:32 1998  Michael Hayes  (mph@elec.canterbury.ac.nz)
 
        * README.C4X: New file with information about the c4x ports.
index 8c8e4286912be680396540007886483ffd130c7e..7c2f9b1936d982aa89ecfe00f3d05b40be2af1e6 100644 (file)
@@ -55,7 +55,7 @@ static int arm_naked_function_p PROTO ((tree));
 static void init_fpa_table PROTO ((void));
 static enum machine_mode select_dominance_cc_mode PROTO ((enum rtx_code, rtx,
                                                          rtx, HOST_WIDE_INT));
-static HOST_WIDE_INT add_constant PROTO ((rtx, enum machine_mode));
+static HOST_WIDE_INT add_constant PROTO ((rtx, enum machine_mode, int *));
 static void dump_table PROTO ((rtx));
 static int fixit PROTO ((rtx, enum machine_mode, int));
 static rtx find_barrier PROTO ((rtx, int));
@@ -3446,18 +3446,30 @@ static pool_node pool_vector[MAX_POOL_SIZE];
 static int pool_size;
 static rtx pool_vector_label;
 
-/* Add a constant to the pool and return its label.  */
+/* Add a constant to the pool and return its offset within the current
+   pool.
+
+   X is the rtx we want to replace. MODE is its mode.  On return,
+   ADDRESS_ONLY will be non-zero if we really want the address of such
+   a constant, not the constant itself.  */
 static HOST_WIDE_INT
-add_constant (x, mode)
+add_constant (x, mode, address_only)
      rtx x;
      enum machine_mode mode;
+     int *address_only;
 {
   int i;
   HOST_WIDE_INT offset;
 
+  *address_only = 0;
   if (mode == SImode && GET_CODE (x) == MEM && CONSTANT_P (XEXP (x, 0))
       && CONSTANT_POOL_ADDRESS_P (XEXP (x, 0)))
     x = get_pool_constant (XEXP (x, 0));
+  else if (GET_CODE (x) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P(x))
+    {
+      *address_only = 1;
+      x = get_pool_constant (x);
+    }
 #ifndef AOF_ASSEMBLER
   else if (GET_CODE (x) == UNSPEC && XINT (x, 1) == 3)
     x = XVECEXP (x, 0, 0);
@@ -3709,6 +3721,7 @@ arm_reorg (first)
                  rtx newsrc;
                  rtx addr;
                  int scratch;
+                 int address_only;
 
                  /* If this is an HImode constant load, convert it into
                     an SImode constant load.  Since the register is always
@@ -3722,39 +3735,50 @@ arm_reorg (first)
                      PUT_MODE (dst, SImode);
                    }
 
-                 offset = add_constant (src, mode);
+                 offset = add_constant (src, mode, &address_only);
                  addr = plus_constant (gen_rtx (LABEL_REF, VOIDmode,
                                                 pool_vector_label),
                                        offset);
 
-                 /* For wide moves to integer regs we need to split the
-                    address calculation off into a separate insn, so that
-                    the load can then be done with a load-multiple.  This is
-                    safe, since we have already noted the length of such
-                    insns to be 8, and we are immediately over-writing the
-                    scratch we have grabbed with the final result.  */
-                 if (GET_MODE_SIZE (mode) > 4
+                 /* If we only want the address of the pool entry, or
+                    for wide moves to integer regs we need to split
+                    the address calculation off into a separate insn.
+                    If necessary, the load can then be done with a
+                    load-multiple.  This is safe, since we have
+                    already noted the length of such insns to be 8,
+                    and we are immediately over-writing the scratch
+                    we have grabbed with the final result.  */
+                 if ((address_only || GET_MODE_SIZE (mode) > 4)
                      && (scratch = REGNO (dst)) < 16)
                    {
-                     rtx reg = gen_rtx (REG, SImode, scratch);
+                     rtx reg;
+
+                     if (mode == SImode)
+                       reg = dst;
+                     else 
+                       reg = gen_rtx (REG, SImode, scratch);
+
                      newinsn = emit_insn_after (gen_movaddr (reg, addr),
                                                 newinsn);
                      addr = reg;
                    }
 
-                 newsrc = gen_rtx (MEM, mode, addr);
-
-                 /* Build a jump insn wrapper around the move instead
-                    of an ordinary insn, because we want to have room for
-                    the target label rtx in fld[7], which an ordinary
-                    insn doesn't have. */
-                 newinsn = emit_jump_insn_after (gen_rtx (SET, VOIDmode,
-                                                          dst, newsrc),
-                                                 newinsn);
-                 JUMP_LABEL (newinsn) = pool_vector_label;
-
-                 /* But it's still an ordinary insn */
-                 PUT_CODE (newinsn, INSN);
+                 if (! address_only)
+                   {
+                     newsrc = gen_rtx (MEM, mode, addr);
+
+                     /* XXX Fixme -- I think the following is bogus.  */
+                     /* Build a jump insn wrapper around the move instead
+                        of an ordinary insn, because we want to have room for
+                        the target label rtx in fld[7], which an ordinary
+                        insn doesn't have. */
+                     newinsn = emit_jump_insn_after
+                       (gen_rtx (SET, VOIDmode, dst, newsrc), newinsn);
+                     JUMP_LABEL (newinsn) = pool_vector_label;
+
+                     /* But it's still an ordinary insn */
+                     PUT_CODE (newinsn, INSN);
+                   }
 
                  /* Kill old insn */
                  delete_insn (scan);