* arm.c (output_move_double): Allocate 3 entries in otherops array.
authorJeffrey A Law <law@cygnus.com>
Mon, 3 Nov 1997 02:26:49 +0000 (02:26 +0000)
committerJeff Law <law@gcc.gnu.org>
Mon, 3 Nov 1997 02:26:49 +0000 (19:26 -0700)
From-SVN: r16281

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

index 265182fb6dd33b151bf26b51f5f6a9283af56987..28bc348c9c20ffbae9e79fc0792f0c83f3d5fd17 100644 (file)
@@ -1,3 +1,7 @@
+Sun Nov  2 19:27:21 1997  Jeffrey A Law  (law@cygnus.com)
+
+       * arm.c (output_move_double): Allocate 3 entries in otherops array.
+
 Sat Nov  1 21:43:00 1997  Mike Stump  (mrs@wrs.com)
 
        * except.c (expand_ex_region_start_for_decl): Emit EH_REGION_BEG
index fe263ba04d3353ce2f49143b3ab8c6275f37f858..ac433374fa411419eba090ec0764d419a4207633 100644 (file)
@@ -21,10 +21,10 @@ along with GNU CC; see the file COPYING.  If not, write to
 the Free Software Foundation, 59 Temple Place - Suite 330,
 Boston, MA 02111-1307, USA.  */
     
+#include "config.h"
 #include <stdio.h>
 #include <string.h>
 #include "assert.h"
-#include "config.h"
 #include "rtl.h"
 #include "regs.h"
 #include "hard-reg-set.h"
@@ -376,7 +376,8 @@ use_return_insn ()
 
   if (!reload_completed ||current_function_pretend_args_size
       || current_function_anonymous_args
-      || (get_frame_size () && !(TARGET_APCS || frame_pointer_needed)))
+      || ((get_frame_size () + current_function_outgoing_args_size != 0)
+         && !(TARGET_APCS || frame_pointer_needed)))
     return 0;
 
   /* Can't be done if interworking with Thumb, and any registers have been
@@ -407,6 +408,13 @@ const_ok_for_arm (i)
 {
   unsigned HOST_WIDE_INT mask = ~0xFF;
 
+  /* For machines with >32 bit HOST_WIDE_INT, the bits above bit 31 must 
+     be all zero, or all one.  */
+  if ((i & ~(unsigned HOST_WIDE_INT) 0xffffffff) != 0
+      && ((i & ~(unsigned HOST_WIDE_INT) 0xffffffff) 
+         != (((HOST_WIDE_INT) -1) & ~(unsigned HOST_WIDE_INT) 0xffffffff)))
+    return FALSE;
+  
   /* Fast return for 0 and powers of 2 */
   if ((i & (i - 1)) == 0)
     return TRUE;
@@ -1501,6 +1509,17 @@ arm_rtx_costs (x, code, outer_code)
              + (REG_OR_SUBREG_REG (XEXP (x, 0)) ? 0 : 4)
              + (REG_OR_SUBREG_REG (XEXP (x, 1)) ? 0 : 4));
 
+    case TRUNCATE:
+      if (arm_fast_multiply && mode == SImode
+         && GET_CODE (XEXP (x, 0)) == LSHIFTRT
+         && GET_CODE (XEXP (XEXP (x, 0), 0)) == MULT
+         && (GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 0))
+             == GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 1)))
+         && (GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 0)) == ZERO_EXTEND
+             || GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 0)) == SIGN_EXTEND))
+       return 8;
+      return 99;
+
     case NEG:
       if (GET_MODE_CLASS (mode) == MODE_FLOAT)
        return 4 + (REG_OR_SUBREG_REG (XEXP (x, 0)) ? 0 : 6);
@@ -2352,6 +2371,10 @@ load_multiple_sequence (operands, nops, regs, base, load_offset)
       rtx reg;
       rtx offset;
 
+      /* Convert a subreg of a mem into the mem itself.  */
+      if (GET_CODE (operands[nops + i]) == SUBREG)
+       operands[nops + i] = alter_subreg(operands[nops + i]);
+
       if (GET_CODE (operands[nops + i]) != MEM)
        abort ();
 
@@ -2551,6 +2574,10 @@ store_multiple_sequence (operands, nops, regs, base, load_offset)
       rtx reg;
       rtx offset;
 
+      /* Convert a subreg of a mem into the mem itself.  */
+      if (GET_CODE (operands[nops + i]) == SUBREG)
+       operands[nops + i] = alter_subreg(operands[nops + i]);
+
       if (GET_CODE (operands[nops + i]) != MEM)
        abort ();
 
@@ -2761,16 +2788,20 @@ arm_naked_function_p (func)
 /* Routines for use in generating RTL */
 
 rtx
-arm_gen_load_multiple (base_regno, count, from, up, write_back)
+arm_gen_load_multiple (base_regno, count, from, up, write_back, unchanging_p,
+                      in_struct_p)
      int base_regno;
      int count;
      rtx from;
      int up;
      int write_back;
+     int unchanging_p;
+     int in_struct_p;
 {
   int i = 0, j;
   rtx result;
   int sign = up ? 1 : -1;
+  rtx mem;
 
   result = gen_rtx (PARALLEL, VOIDmode,
                     rtvec_alloc (count + (write_back ? 2 : 0)));
@@ -2785,10 +2816,13 @@ arm_gen_load_multiple (base_regno, count, from, up, write_back)
 
   for (j = 0; i < count; i++, j++)
     {
-      XVECEXP (result, 0, i)
-       = gen_rtx (SET, VOIDmode, gen_rtx (REG, SImode, base_regno + j),
-                  gen_rtx (MEM, SImode,
-                           plus_constant (from, j * 4 * sign)));
+      mem = gen_rtx (MEM, SImode, plus_constant (from, j * 4 * sign));
+      RTX_UNCHANGING_P (mem) = unchanging_p;
+      MEM_IN_STRUCT_P (mem) = in_struct_p;
+
+      XVECEXP (result, 0, i) = gen_rtx (SET, VOIDmode,
+                                       gen_rtx (REG, SImode, base_regno + j),
+                                       mem);
     }
 
   if (write_back)
@@ -2798,16 +2832,20 @@ arm_gen_load_multiple (base_regno, count, from, up, write_back)
 }
 
 rtx
-arm_gen_store_multiple (base_regno, count, to, up, write_back)
+arm_gen_store_multiple (base_regno, count, to, up, write_back, unchanging_p,
+                       in_struct_p)
      int base_regno;
      int count;
      rtx to;
      int up;
      int write_back;
+     int unchanging_p;
+     int in_struct_p;
 {
   int i = 0, j;
   rtx result;
   int sign = up ? 1 : -1;
+  rtx mem;
 
   result = gen_rtx (PARALLEL, VOIDmode,
                     rtvec_alloc (count + (write_back ? 2 : 0)));
@@ -2822,10 +2860,12 @@ arm_gen_store_multiple (base_regno, count, to, up, write_back)
 
   for (j = 0; i < count; i++, j++)
     {
-      XVECEXP (result, 0, i)
-       = gen_rtx (SET, VOIDmode,
-                  gen_rtx (MEM, SImode, plus_constant (to, j * 4 * sign)),
-                  gen_rtx (REG, SImode, base_regno + j));
+      mem = gen_rtx (MEM, SImode, plus_constant (to, j * 4 * sign));
+      RTX_UNCHANGING_P (mem) = unchanging_p;
+      MEM_IN_STRUCT_P (mem) = in_struct_p;
+
+      XVECEXP (result, 0, i) = gen_rtx (SET, VOIDmode, mem,
+                                       gen_rtx (REG, SImode, base_regno + j));
     }
 
   if (write_back)
@@ -2843,6 +2883,8 @@ arm_gen_movstrqi (operands)
   rtx src, dst;
   rtx st_src, st_dst, end_src, end_dst, fin_src, fin_dst;
   rtx part_bytes_reg = NULL;
+  rtx mem;
+  int dst_unchanging_p, dst_in_struct_p, src_unchanging_p, src_in_struct_p;
   extern int optimize;
 
   if (GET_CODE (operands[2]) != CONST_INT
@@ -2853,6 +2895,12 @@ arm_gen_movstrqi (operands)
 
   st_dst = XEXP (operands[0], 0);
   st_src = XEXP (operands[1], 0);
+
+  dst_unchanging_p = RTX_UNCHANGING_P (operands[0]);
+  dst_in_struct_p = MEM_IN_STRUCT_P (operands[0]);
+  src_unchanging_p = RTX_UNCHANGING_P (operands[1]);
+  src_in_struct_p = MEM_IN_STRUCT_P (operands[1]);
+
   fin_dst = dst = copy_to_mode_reg (SImode, st_dst);
   fin_src = src = copy_to_mode_reg (SImode, st_src);
 
@@ -2866,24 +2914,32 @@ arm_gen_movstrqi (operands)
   for (i = 0; in_words_to_go >= 2; i+=4)
     {
       if (in_words_to_go > 4)
-       emit_insn (arm_gen_load_multiple (0, 4, src, TRUE, TRUE));
+       emit_insn (arm_gen_load_multiple (0, 4, src, TRUE, TRUE,
+                                         src_unchanging_p, src_in_struct_p));
       else
        emit_insn (arm_gen_load_multiple (0, in_words_to_go, src, TRUE, 
-                                         FALSE));
+                                         FALSE, src_unchanging_p,
+                                         src_in_struct_p));
 
       if (out_words_to_go)
        {
          if (out_words_to_go > 4)
-           emit_insn (arm_gen_store_multiple (0, 4, dst, TRUE, TRUE));
+           emit_insn (arm_gen_store_multiple (0, 4, dst, TRUE, TRUE,
+                                              dst_unchanging_p,
+                                              dst_in_struct_p));
          else if (out_words_to_go != 1)
            emit_insn (arm_gen_store_multiple (0, out_words_to_go,
                                               dst, TRUE, 
                                               (last_bytes == 0
-                                               ? FALSE : TRUE)));
+                                               ? FALSE : TRUE),
+                                              dst_unchanging_p,
+                                              dst_in_struct_p));
          else
            {
-             emit_move_insn (gen_rtx (MEM, SImode, dst),
-                             gen_rtx (REG, SImode, 0));
+             mem = gen_rtx (MEM, SImode, dst);
+             RTX_UNCHANGING_P (mem) = dst_unchanging_p;
+             MEM_IN_STRUCT_P (mem) = dst_in_struct_p;
+             emit_move_insn (mem, gen_rtx (REG, SImode, 0));
              if (last_bytes != 0)
                emit_insn (gen_addsi3 (dst, dst, GEN_INT (4)));
            }
@@ -2898,9 +2954,16 @@ arm_gen_movstrqi (operands)
   {
     rtx sreg;
 
-    emit_move_insn (sreg = gen_reg_rtx (SImode), gen_rtx (MEM, SImode, src));
+    mem = gen_rtx (MEM, SImode, src);
+    RTX_UNCHANGING_P (mem) = src_unchanging_p;
+    MEM_IN_STRUCT_P (mem) = src_in_struct_p;
+    emit_move_insn (sreg = gen_reg_rtx (SImode), mem);
     emit_move_insn (fin_src = gen_reg_rtx (SImode), plus_constant (src, 4));
-    emit_move_insn (gen_rtx (MEM, SImode, dst), sreg);
+
+    mem = gen_rtx (MEM, SImode, dst);
+    RTX_UNCHANGING_P (mem) = dst_unchanging_p;
+    MEM_IN_STRUCT_P (mem) = dst_in_struct_p;
+    emit_move_insn (mem, sreg);
     emit_move_insn (fin_dst = gen_reg_rtx (SImode), plus_constant (dst, 4));
     in_words_to_go--;
 
@@ -2913,7 +2976,10 @@ arm_gen_movstrqi (operands)
       if (in_words_to_go < 0)
        abort ();
 
-      part_bytes_reg = copy_to_mode_reg (SImode, gen_rtx (MEM, SImode, src));
+      mem = gen_rtx (MEM, SImode, src);
+      RTX_UNCHANGING_P (mem) = src_unchanging_p;
+      MEM_IN_STRUCT_P (mem) = src_in_struct_p;
+      part_bytes_reg = copy_to_mode_reg (SImode, mem);
     }
 
   if (BYTES_BIG_ENDIAN && last_bytes)
@@ -2930,9 +2996,10 @@ arm_gen_movstrqi (operands)
       
       while (last_bytes)
        {
-         emit_move_insn (gen_rtx (MEM, QImode, 
-                                  plus_constant (dst, last_bytes - 1)),
-                         gen_rtx (SUBREG, QImode, part_bytes_reg, 0));
+         mem = gen_rtx (MEM, QImode, plus_constant (dst, last_bytes - 1));
+         RTX_UNCHANGING_P (mem) = dst_unchanging_p;
+         MEM_IN_STRUCT_P (mem) = dst_in_struct_p;
+         emit_move_insn (mem, gen_rtx (SUBREG, QImode, part_bytes_reg, 0));
          if (--last_bytes)
            {
              tmp = gen_reg_rtx (SImode);
@@ -2949,8 +3016,10 @@ arm_gen_movstrqi (operands)
          if (part_bytes_reg == NULL)
            abort ();
 
-         emit_move_insn (gen_rtx (MEM, QImode, dst),
-                         gen_rtx (SUBREG, QImode, part_bytes_reg, 0));
+         mem = gen_rtx (MEM, QImode, dst);
+         RTX_UNCHANGING_P (mem) = dst_unchanging_p;
+         MEM_IN_STRUCT_P (mem) = dst_in_struct_p;
+         emit_move_insn (mem, gen_rtx (SUBREG, QImode, part_bytes_reg, 0));
          if (--last_bytes)
            {
              rtx tmp = gen_reg_rtx (SImode);
@@ -3913,7 +3982,7 @@ output_move_double (operands)
 {
   enum rtx_code code0 = GET_CODE (operands[0]);
   enum rtx_code code1 = GET_CODE (operands[1]);
-  rtx otherops[2];
+  rtx otherops[3];
 
   if (code0 == REG)
     {
@@ -3964,7 +4033,21 @@ output_move_double (operands)
        }
       else if (code1 == CONST_INT)
        {
-         /* sign extend the intval into the high-order word */
+#if HOST_BITS_PER_WIDE_INT > 32
+         /* If HOST_WIDE_INT is more than 32 bits, the intval tells us
+            what the upper word is.  */
+         if (WORDS_BIG_ENDIAN)
+           {
+             otherops[1] = GEN_INT (ARM_SIGN_EXTEND (INTVAL (operands[1])));
+             operands[1] = GEN_INT (INTVAL (operands[1]) >> 32);
+           }
+         else
+           {
+             otherops[1] = GEN_INT (INTVAL (operands[1]) >> 32);
+             operands[1] = GEN_INT (ARM_SIGN_EXTEND (INTVAL (operands[1])));
+           }
+#else
+         /* Sign extend the intval into the high-order word */
          if (WORDS_BIG_ENDIAN)
            {
              otherops[1] = operands[1];
@@ -3973,6 +4056,7 @@ output_move_double (operands)
            }
          else
            otherops[1] = INTVAL (operands[1]) < 0 ? constm1_rtx : const0_rtx;
+#endif
          output_mov_immediate (otherops);
          output_mov_immediate (operands);
        }
@@ -4762,10 +4846,9 @@ output_func_epilogue (f, frame_size)
 
   if (use_return_insn() && return_used_this_function)
     {
-      if (frame_size && !(frame_pointer_needed || TARGET_APCS))
-        {
-          abort ();
-        }
+      if ((frame_size + current_function_outgoing_args_size) != 0
+         && !(frame_pointer_needed || TARGET_APCS))
+       abort ();
       goto epilogue_done;
     }
 
@@ -4853,10 +4936,11 @@ output_func_epilogue (f, frame_size)
   else
     {
       /* Restore stack pointer if necessary.  */
-      if (frame_size)
+      if (frame_size + current_function_outgoing_args_size != 0)
        {
          operands[0] = operands[1] = stack_pointer_rtx;
-         operands[2] = gen_rtx (CONST_INT, VOIDmode, frame_size);
+         operands[2] = GEN_INT (frame_size
+                                + current_function_outgoing_args_size);
          output_add_immediate (operands);
        }
 
@@ -5028,7 +5112,8 @@ void
 arm_expand_prologue ()
 {
   int reg;
-  rtx amount = GEN_INT (- get_frame_size ());
+  rtx amount = GEN_INT (-(get_frame_size ()
+                         + current_function_outgoing_args_size));
   rtx push_insn;
   int num_regs;
   int live_regs_mask = 0;
@@ -5295,34 +5380,6 @@ arm_print_operand (stream, x, code)
     }
 }
 
-/* Output a label definition.  */
-
-void
-arm_asm_output_label (stream, name)
-     FILE *stream;
-     char *name;
-{
-  ARM_OUTPUT_LABEL (stream, name);
-}
-
-/* Output code resembling an .lcomm directive.  /bin/as doesn't have this
-   directive hence this hack, which works by reserving some `.space' in the
-   bss segment directly.
-
-   XXX This is a severe hack, which is guaranteed NOT to work since it doesn't
-   define STATIC COMMON space but merely STATIC BSS space.  */
-
-void
-output_lcomm_directive (stream, name, size, align)
-     FILE *stream;
-     char *name;
-     int size, align;
-{
-  bss_section ();
-  ASM_OUTPUT_ALIGN (stream, floor_log2 (align / BITS_PER_UNIT));
-  ARM_OUTPUT_LABEL (stream, name);
-  fprintf (stream, "\t.space\t%d\n", size);
-}
 \f
 /* A finite state machine takes care of noticing whether or not instructions
    can be conditionally executed, and thus decrease execution time and code