OSDN Git Service

* alpha.c (alpha_write_verstamp): Only emit MS_STAMP and LS_STAMP,
[pf3gnuchains/gcc-fork.git] / gcc / config / alpha / alpha.c
index bdcd305..b5a42b7 100644 (file)
@@ -370,9 +370,7 @@ call_operand (op, mode)
   if (mode != Pmode)
     return 0;
 
-  return (GET_CODE (op) == SYMBOL_REF
-         || (GET_CODE (op) == REG
-             && (REGNO (op) == 27 || WINDOWS_NT)));
+  return (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == REG);
 }
 
 /* Return 1 if OP is a valid Alpha comparison operator.  Here we know which
@@ -461,10 +459,7 @@ aligned_memory_operand (op, mode)
     op = XEXP (op, 0);
 
   return (GET_CODE (op) == REG
-         && (REGNO (op) == STACK_POINTER_REGNUM
-             || op == hard_frame_pointer_rtx
-             || (REGNO (op) >= FIRST_VIRTUAL_REGISTER
-                 && REGNO (op) <= LAST_VIRTUAL_REGISTER)));
+         && REGNO_POINTER_ALIGN (REGNO (op)) >= 4);
 }
 
 /* Similar, but return 1 if OP is a MEM which is not alignable.  */
@@ -498,10 +493,17 @@ unaligned_memory_operand (op, mode)
     op = XEXP (op, 0);
 
   return (GET_CODE (op) != REG
-         || (REGNO (op) != STACK_POINTER_REGNUM
-             && op != hard_frame_pointer_rtx
-             && (REGNO (op) < FIRST_VIRTUAL_REGISTER
-                 || REGNO (op) > LAST_VIRTUAL_REGISTER)));
+         || REGNO_POINTER_ALIGN (REGNO (op)) < 4);
+}
+
+/* Return 1 if OP is either a register or an unaligned memory location.  */
+
+int
+reg_or_unaligned_mem_operand (op, mode)
+     rtx op;
+     enum machine_mode mode;
+{
+  return register_operand (op, mode) || unaligned_memory_operand (op, mode);
 }
 
 /* Return 1 if OP is any memory location.  During reload a pseudo matches.  */
@@ -562,11 +564,13 @@ get_aligned_mem (ref, paligned_mem, pbitnum)
   *pbitnum = GEN_INT ((offset & 3) * 8);
 }
 
-/* Similar, but just get the address.  Handle the two reload cases.  */
+/* Similar, but just get the address.  Handle the two reload cases.  
+   Add EXTRA_OFFSET to the address we return.  */
 
 rtx
-get_unaligned_address (ref)
+get_unaligned_address (ref, extra_offset)
      rtx ref;
+     int extra_offset;
 {
   rtx base;
   HOST_WIDE_INT offset = 0;
@@ -592,7 +596,7 @@ get_unaligned_address (ref)
   if (GET_CODE (base) == PLUS)
     offset += INTVAL (XEXP (base, 1)), base = XEXP (base, 0);
 
-  return plus_constant (base, offset);
+  return plus_constant (base, offset + extra_offset);
 }
 \f
 /* Subfunction of the following function.  Update the flags of any MEM
@@ -695,7 +699,7 @@ alpha_emit_set_const (target, mode, c, n)
 
   if ((HOST_BITS_PER_WIDE_INT != 64
        || c >> 31 == -1 || c >> 31 == 0)
-      && c != 0x80000000u)
+      && c != 0x80000000U)
     {
       HOST_WIDE_INT low = (c & 0xffff) - 2 * (c & 0x8000);
       HOST_WIDE_INT tmp1 = c - low;
@@ -715,7 +719,12 @@ alpha_emit_set_const (target, mode, c, n)
 
       if (c == low || (low == 0 && extra == 0))
        return copy_to_suggested_reg (GEN_INT (c), target, mode);
-      else if (n >= 2 + (extra != 0))
+      else if (n >= 2 + (extra != 0)
+              /* We can't do this when SImode if HIGH required adjustment.
+                 This is because the code relies on an implicit overflow
+                 which is invisible to the RTL.  We can thus get incorrect
+                 code if the two ldah instructions are combined.  */
+              && ! (mode == SImode && extra != 0))
        {
          temp = copy_to_suggested_reg (GEN_INT (low), subtarget, mode);
 
@@ -746,7 +755,14 @@ alpha_emit_set_const (target, mode, c, n)
     if ((new & ((HOST_WIDE_INT) 0xff << i)) == 0)
       new |= (HOST_WIDE_INT) 0xff << i;
 
-  if ((temp = alpha_emit_set_const (subtarget, mode, new, n - 1)) != 0)
+  /* We are only called for SImode and DImode.  If this is SImode, ensure that
+     we are sign extended to a full word.  */
+
+  if (mode == SImode)
+    new = (new & 0xffffffff) - 2 * (new & 0x80000000);
+
+  if (new != c
+      && (temp = alpha_emit_set_const (subtarget, mode, new, n - 1)) != 0)
     return expand_binop (mode, and_optab, temp, GEN_INT (c | ~ new),
                         target, 0, OPTAB_WIDEN);
 #endif
@@ -783,9 +799,11 @@ alpha_emit_set_const (target, mode, c, n)
                                 target, 0, OPTAB_WIDEN);
 
       /* Now try high-order zero bits.  Here we try the shifted-in bits as
-        all zero and all ones.  */
+        all zero and all ones.  Be careful to avoid shifting outside the
+        mode and to avoid shifting outside the host wide int size.  */
 
-      if ((bits = HOST_BITS_PER_WIDE_INT - floor_log2 (c) - 1) > 0)
+      if ((bits = (MIN (HOST_BITS_PER_WIDE_INT, GET_MODE_SIZE (mode) * 8)
+                  - floor_log2 (c) - 1)) > 0)
        for (; bits > 0; bits--)
          if ((temp = alpha_emit_set_const (subtarget, mode,
                                            c << bits, i)) != 0
@@ -795,12 +813,14 @@ alpha_emit_set_const (target, mode, c, n)
                            i)))
                  != 0))
            return expand_binop (mode, lshr_optab, temp, GEN_INT (bits),
-                                target, 0, OPTAB_WIDEN);
+                                target, 1, OPTAB_WIDEN);
 
       /* Now try high-order 1 bits.  We get that with a sign-extension.
-        But one bit isn't enough here.  */
+        But one bit isn't enough here.  Be careful to avoid shifting outside
+        the mode and to avoid shifting outside the host wide int size. */
       
-      if ((bits = HOST_BITS_PER_WIDE_INT - floor_log2 (~ c) - 2) > 0)
+      if ((bits = (MIN (HOST_BITS_PER_WIDE_INT, GET_MODE_SIZE (mode) * 8)
+                  - floor_log2 (~ c) - 2)) > 0)
        for (; bits > 0; bits--)
          if ((temp = alpha_emit_set_const (subtarget, mode,
                                            c << bits, i)) != 0
@@ -1156,21 +1176,26 @@ alpha_builtin_saveregs (arglist)
          ? plus_constant (virtual_incoming_args_rtx, 6 * UNITS_PER_WORD)
          : plus_constant (virtual_incoming_args_rtx, - (6 * UNITS_PER_WORD)));
 
+  addr = force_operand (addr, NULL_RTX);
+
   /* Allocate the va_list constructor */
   block = assign_stack_local (BLKmode, 2 * UNITS_PER_WORD, BITS_PER_WORD);
   RTX_UNCHANGING_P (block) = 1;
   RTX_UNCHANGING_P (XEXP (block, 0)) = 1;
 
-  /* Store the address of the first integer register in the
-     __va_base member.  */
-  emit_move_insn (change_address (block, Pmode, XEXP (block, 0)),
-                 force_operand (addr, NULL_RTX));
+  /* Store the address of the first integer register in the __base member.  */
+
+#ifdef POINTERS_EXTEND_UNSIGNED
+  addr = convert_memory_address (ptr_mode, addr);
+#endif
+
+  emit_move_insn (change_address (block, ptr_mode, XEXP (block, 0)), addr);
 
   /* Store the argsize as the __va_offset member.  */
-  emit_move_insn (change_address (block, Pmode,
+  emit_move_insn (change_address (block, TYPE_MODE (integer_type_node),
                                  plus_constant (XEXP (block, 0),
-                                                UNITS_PER_WORD)),
-                 force_operand (argsize, NULL_RTX));
+                                                POINTER_SIZE/BITS_PER_UNIT)),
+                 argsize);
 
   /* Return the address of the va_list constructor, but don't put it in a
      register.  Doing so would fail when not optimizing and produce worse
@@ -1228,12 +1253,7 @@ alpha_write_verstamp (file)
      FILE *file;
 {
 #ifdef MS_STAMP
-  char *p;
-
-  fprintf (file, "\t.verstamp %d %d ", MS_STAMP, LS_STAMP);
-  for (p = version_string; *p != ' ' && *p != 0; p++)
-    fprintf (file, "%c", *p == '.' ? ' ' : *p);
-  fprintf (file, "\n");
+  fprintf (file, "\t.verstamp %d %d\n", MS_STAMP, LS_STAMP);
 #endif
 }
 \f