]> gcc.gnu.org Git - gcc.git/commitdiff
General tidy up.
authorRichard Earnshaw <erich@gnu.org>
Wed, 1 Jun 1994 17:09:29 +0000 (17:09 +0000)
committerRichard Earnshaw <erich@gnu.org>
Wed, 1 Jun 1994 17:09:29 +0000 (17:09 +0000)
#include <string.h>.
Declare some prototypes.
(output_memory_reference_mode): Change type to enum machine_mode.
(arm_const_nmoves): Delete.
(adjacent_mem_locations, {load,store}_multiple_operation): Explicitly
declare to return int.
({load,store}_multiple_operation): Change type of 'count', 'base' and 'i' to
HOST_WIDE_INT.
(output_add_immediate): Change type of 'n' to HOST_WIDE_INT.
(output_multi_immediate): Change type of Argument 'n' to HOST_WIDE_INT, if
wider than 32 bits, mask out the high bits.
(output_arithmetic_with_immediate_multiply): Change type of 'shift'
to HOST_WIDE_INT.
(output_func_{prologue,epilogue}): Renamed from output_{prologue,epilogue}.
Check all registers to see if they are live, but only push/pop them if they
are not in call_used_regs.

(const_pool_offset): New function.
(get_prologue_size): New function.
(output_func_prologue): Eliminate variable code_size.
(output_func_epilogue): Only call arm_increase_location when optimizing; also
add the size of the function just compiled, and the size of the prologue.
(arm_output_asm_insn): Delete.  All callers changed to use output_asm_insn.
(arm_output_llc): Delete.
(output_load_symbol): New first parameter 'insn'.  Rewrite so that assembler
can detect whether we made a mistake.

From-SVN: r7416

gcc/config/arm/arm.c

index dae7f9825bce0f59e8615a86543760850d4054a8..0e8d7d7b6bb24049cd24829d355c960288f1a3ac 100644 (file)
@@ -21,6 +21,7 @@ along with GNU CC; see the file COPYING.  If not, write to
 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
     
 #include <stdio.h>
+#include <string.h>
 #include "assert.h"
 #include "config.h"
 #include "rtl.h"
@@ -42,9 +43,11 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 /* Some function declarations.  */
 extern FILE *asm_out_file;
 extern char *output_multi_immediate ();
-extern char *arm_output_asm_insn ();
 extern void arm_increase_location ();
 
+HOST_WIDE_INT int_log2 PROTO ((HOST_WIDE_INT));
+static int get_prologue_size PROTO ((void));
+
 /*  Define the information needed to generate branch insns.  This is
    stored from the compare operation. */
 
@@ -58,7 +61,7 @@ enum processor_type arm_cpu;
 /* In case of a PRE_INC, POST_INC, PRE_DEC, POST_DEC memory reference, we
    must report the mode of the memory reference from PRINT_OPERAND to
    PRINT_OPERAND_ADDRESS.  */
-int output_memory_reference_mode;
+enum machine_mode output_memory_reference_mode;
 
 /* Nonzero if the prologue must setup `fp'.  */
 int current_function_anonymous_args;
@@ -115,24 +118,6 @@ use_return_insn ()
   return 1;
 }
 
-/* Return the number of mov instructions needed to get the constant VALUE into
-   a register.  */
-
-int
-arm_const_nmoves (value)
-     register int value;
-{
-  register int i;
-
-  if (value == 0)
-    return (1);
-  for (i = 0; value; i++, value &= ~0xff)
-    while ((value & 3) == 0)
-      value = (value >> 2) | ((value & 3) << 30);
-  return (i);
-} /* arm_const_nmoves */
-
-
 /* Return TRUE if int I is a valid immediate ARM constant.  */
 
 int
@@ -144,14 +129,14 @@ const_ok_for_arm (i)
   do
     {
       if ((i & mask & (unsigned HOST_WIDE_INT) 0xffffffff) == 0)
-        return(TRUE);
+        return TRUE;
       mask =
          (mask << 2) | ((mask & (unsigned HOST_WIDE_INT) 0xffffffff)
                         >> (32 - 2)) | ~((unsigned HOST_WIDE_INT) 0xffffffff);
     } while (mask != ~0xFF);
 
-  return (FALSE);
-} /* const_ok_for_arm */
+  return FALSE;
+}
 
 /* This code has been fixed for cross compilation. */
 
@@ -181,6 +166,7 @@ init_fpa_table ()
       r = REAL_VALUE_ATOF (strings_fpa[i], DFmode);
       values_fpa[i] = r;
     }
+
   fpa_consts_inited = 1;
 }
 
@@ -199,11 +185,13 @@ const_double_rtx_ok_for_fpu (x)
   REAL_VALUE_FROM_CONST_DOUBLE (r, x);
   if (REAL_VALUE_MINUS_ZERO (r))
     return 0;
+
   for (i = 0; i < 8; i++)
     if (REAL_VALUES_EQUAL (r, values_fpa[i]))
       return 1;
+
   return 0;
-} /* const_double_rtx_ok_for_fpu */
+}
 
 /* Return TRUE if rtx X is a valid immediate FPU constant. */
 
@@ -221,11 +209,13 @@ neg_const_double_rtx_ok_for_fpu (x)
   r = REAL_VALUE_NEGATE (r);
   if (REAL_VALUE_MINUS_ZERO (r))
     return 0;
+
   for (i = 0; i < 8; i++)
     if (REAL_VALUES_EQUAL (r, values_fpa[i]))
       return 1;
+
   return 0;
-} /* neg_const_double_rtx_ok_for_fpu */
+}
 \f
 /* Predicates for `match_operand' and `match_operator'.  */
 
@@ -241,9 +231,7 @@ s_register_operand (op, mode)
     return 0;
 
   if (GET_CODE (op) == SUBREG)
-    {
-      op = SUBREG_REG (op);
-    }
+    op = SUBREG_REG (op);
 
   /* We don't consider registers whose class is NO_REGS
      to be a register operand.  */
@@ -276,7 +264,7 @@ arm_rhs_operand (op, mode)
 {
   return (s_register_operand (op, mode)
          || (GET_CODE (op) == CONST_INT && const_ok_for_arm (INTVAL (op))));
-} /* arm_rhs_operand */
+}
 
 /* Return TRUE for valid operands for the rhs of an ARM instruction, or a load.
  */
@@ -289,7 +277,7 @@ arm_rhsm_operand (op, mode)
   return (s_register_operand (op, mode)
          || (GET_CODE (op) == CONST_INT && const_ok_for_arm (INTVAL (op)))
          || memory_operand (op, mode));
-} /* arm_rhs_operand */
+}
 
 /* Return TRUE for valid operands for the rhs of an ARM instruction, or if a
    constant that is valid when negated.  */
@@ -303,7 +291,7 @@ arm_add_operand (op, mode)
          || (GET_CODE (op) == CONST_INT
              && (const_ok_for_arm (INTVAL (op))
                  || const_ok_for_arm (-INTVAL (op)))));
-} /* arm_rhs_operand */
+}
 
 int
 arm_not_operand (op, mode)
@@ -314,7 +302,7 @@ arm_not_operand (op, mode)
          || (GET_CODE (op) == CONST_INT
              && (const_ok_for_arm (INTVAL (op))
                  || const_ok_for_arm (~INTVAL (op)))));
-} /* arm_rhs_operand */
+}
 
 /* Return TRUE for valid operands for the rhs of an FPU instruction.  */
 
@@ -324,11 +312,12 @@ fpu_rhs_operand (op, mode)
      enum machine_mode mode;
 {
   if (s_register_operand (op, mode))
-    return(TRUE);
+    return TRUE;
   else if (GET_CODE (op) == CONST_DOUBLE)
     return (const_double_rtx_ok_for_fpu (op));
-  else return (FALSE);
-} /* fpu_rhs_operand */
+
+  return FALSE;
+}
 
 int
 fpu_add_operand (op, mode)
@@ -336,11 +325,12 @@ fpu_add_operand (op, mode)
      enum machine_mode mode;
 {
   if (s_register_operand (op, mode))
-    return(TRUE);
+    return TRUE;
   else if (GET_CODE (op) == CONST_DOUBLE)
-    return const_double_rtx_ok_for_fpu (op) 
-       || neg_const_double_rtx_ok_for_fpu (op);
-  return (FALSE);
+    return (const_double_rtx_ok_for_fpu (op) 
+           || neg_const_double_rtx_ok_for_fpu (op));
+
+  return FALSE;
 }
 
 /* Return nonzero if OP is a constant power of two.  */
@@ -352,11 +342,11 @@ power_of_two_operand (op, mode)
 {
   if (GET_CODE (op) == CONST_INT)
     {
-      int value = INTVAL(op);
-      return (value != 0  &&  (value & (value-1)) == 0);
+      HOST_WIDE_INT value = INTVAL(op);
+      return value != 0  &&  (value & (value - 1)) == 0;
     }
-  return (FALSE);
-} /* power_of_two_operand */
+  return FALSE;
+}
 
 /* Return TRUE for a valid operand of a DImode operation.
    Either: REG, CONST_DOUBLE or MEM(DImode_address).
@@ -369,19 +359,21 @@ di_operand (op, mode)
      enum machine_mode mode;
 {
   if (s_register_operand (op, mode))
-    return (TRUE);
+    return TRUE;
 
   switch (GET_CODE (op))
     {
     case CONST_DOUBLE:
     case CONST_INT:
-      return (TRUE);
+      return TRUE;
+
     case MEM:
-      return (memory_address_p (DImode, XEXP (op, 0)));
+      return memory_address_p (DImode, XEXP (op, 0));
+
     default:
-      return (FALSE);
+      return FALSE;
     }
-} /* di_operand */
+}
 
 /* Return TRUE for valid index operands. */
 
@@ -393,7 +385,7 @@ index_operand (op, mode)
   return (s_register_operand(op, mode)
          || (immediate_operand (op, mode)
              && INTVAL (op) < 4096 && INTVAL (op) > -4096));
-} /* index_operand */
+}
 
 /* Return TRUE for valid shifts by a constant. This also accepts any
    power of two on the (somewhat overly relaxed) assumption that the
@@ -407,7 +399,7 @@ const_shift_operand (op, mode)
   return (power_of_two_operand (op, mode)
          || (immediate_operand (op, mode)
              && (INTVAL (op) < 32 && INTVAL (op) > 0)));
-} /* const_shift_operand */
+}
 
 /* Return TRUE for arithmetic operators which can be combined with a multiply
    (shift).  */
@@ -426,7 +418,7 @@ shiftable_operator (x, mode)
       return (code == PLUS || code == MINUS
              || code == IOR || code == XOR || code == AND);
     }
-} /* shiftable_operator */
+}
 
 /* Return TRUE for shift operators. */
 
@@ -443,15 +435,16 @@ shift_operator (x, mode)
 
       if (code == MULT)
        return power_of_two_operand (XEXP (x, 1));
+
       return (code == ASHIFT || code == ASHIFTRT || code == LSHIFTRT);
     }
-} /* shift_operator */
+}
 
 int equality_operator (x, mode)
-rtx x;
-enum machine_mode mode;
+     rtx x;
+     enum machine_mode mode;
 {
-  return (GET_CODE (x) == EQ || GET_CODE (x) == NE);
+  return GET_CODE (x) == EQ || GET_CODE (x) == NE;
 }
 
 /* Return TRUE for SMIN SMAX UMIN UMAX operators. */
@@ -465,8 +458,9 @@ minmax_operator (x, mode)
 
   if (GET_MODE (x) != mode)
     return FALSE;
+
   return code == SMIN || code == SMAX || code == UMIN || code == UMAX;
-} /* minmax_operator */
+}
 
 /* return TRUE if x is EQ or NE */
 
@@ -475,8 +469,8 @@ minmax_operator (x, mode)
 
 int
 cc_register (x, mode)
-rtx x;
-enum machine_mode mode;
+     rtx x;
+     enum machine_mode mode;
 {
   if (mode == VOIDmode)
     {
@@ -484,30 +478,34 @@ enum machine_mode mode;
       if (GET_MODE_CLASS (mode) != MODE_CC)
        return FALSE;
     }
+
   if (mode == GET_MODE (x) && GET_CODE (x) == REG && REGNO (x) == 24)
     return TRUE;
+
   return FALSE;
 }
        
 enum rtx_code
 minmax_code (x)
-rtx x;
+     rtx x;
 {
   enum rtx_code code = GET_CODE (x);
 
   if (code == SMAX)
     return GE;
-  if (code == SMIN)
+  else if (code == SMIN)
     return LE;
-  if (code == UMIN)
+  else if (code == UMIN)
     return LEU;
-  if (code == UMAX)
+  else if (code == UMAX)
     return GEU;
+
   abort ();
 }
 
 /* Return 1 if memory locations are adjacent */
 
+int
 adjacent_mem_locations (a, b)
      rtx a, b;
 {
@@ -543,14 +541,15 @@ adjacent_mem_locations (a, b)
 /* Return 1 if OP is a load multiple operation.  It is known to be
    parallel and the first section will be tested. */
 
+int
 load_multiple_operation (op, mode)
      rtx op;
      enum machine_mode mode;
 {
-  int count = XVECLEN (op, 0);
+  HOST_WIDE_INT count = XVECLEN (op, 0);
   int dest_regno;
   rtx src_addr;
-  int i = 1, base = 0;
+  HOST_WIDE_INT i = 1, base = 0;
   rtx elt;
 
   if (count <= 1
@@ -574,6 +573,7 @@ load_multiple_operation (op, mode)
           || REGNO (XEXP (XVECEXP (op, 0, count - 1), 0))
               != REGNO (SET_DEST (elt)))
         return 0;
+
       count--;
     }
 
@@ -610,14 +610,15 @@ load_multiple_operation (op, mode)
 /* Return 1 if OP is a store multiple operation.  It is known to be
    parallel and the first section will be tested. */
 
+int
 store_multiple_operation (op, mode)
      rtx op;
      enum machine_mode mode;
 {
-  int count = XVECLEN (op, 0);
+  HOST_WIDE_INT count = XVECLEN (op, 0);
   int src_regno;
   rtx dest_addr;
-  int i = 1, base = 0;
+  HOST_WIDE_INT i = 1, base = 0;
   rtx elt;
 
   if (count <= 1
@@ -641,6 +642,7 @@ store_multiple_operation (op, mode)
           || REGNO (XEXP (XVECEXP (op, 0, count - 1), 0))
               != REGNO (SET_DEST (elt)))
         return 0;
+
       count--;
     }
 
@@ -674,9 +676,19 @@ store_multiple_operation (op, mode)
   return 1;
 }
 \f
+/* Routines for use with attributes */
+
+int
+const_pool_offset (symbol)
+     rtx (symbol);
+{
+  return get_pool_offset (symbol) - get_pool_size () - get_prologue_size ();
+}
+\f
 /* Routines for use in generating RTL */
 
-rtx arm_gen_load_multiple (base_regno, count, from, up, write_back)
+rtx
+arm_gen_load_multiple (base_regno, count, from, up, write_back)
      int base_regno;
      int count;
      rtx from;
@@ -690,27 +702,30 @@ rtx arm_gen_load_multiple (base_regno, count, from, up, write_back)
   result = gen_rtx (PARALLEL, VOIDmode,
                     rtvec_alloc (count + (write_back ? 2 : 0)));
   if (write_back)
-  {
+    {
       XVECEXP (result, 0, 0)
-          = gen_rtx (SET, GET_MODE (from), from,
-                     plus_constant (from, count * 4 * sign));
+       = gen_rtx (SET, GET_MODE (from), from,
+                  plus_constant (from, count * 4 * sign));
       i = 1;
       count++;
-  }
+    }
+
   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)));
-  }
+       = gen_rtx (SET, VOIDmode, gen_rtx (REG, SImode, base_regno + j),
+                  gen_rtx (MEM, SImode,
+                           plus_constant (from, j * 4 * sign)));
+    }
+
   if (write_back)
     XVECEXP (result, 0, i) = gen_rtx (CLOBBER, SImode, from);
 
   return result;
 }
 
-rtx arm_gen_store_multiple (base_regno, count, to, up, write_back)
+rtx
+arm_gen_store_multiple (base_regno, count, to, up, write_back)
      int base_regno;
      int count;
      rtx to;
@@ -724,20 +739,22 @@ rtx arm_gen_store_multiple (base_regno, count, to, up, write_back)
   result = gen_rtx (PARALLEL, VOIDmode,
                     rtvec_alloc (count + (write_back ? 2 : 0)));
   if (write_back)
-  {
+    {
       XVECEXP (result, 0, 0)
-          = gen_rtx (SET, GET_MODE (to), to,
-                     plus_constant (to, count * 4 * sign));
+       = gen_rtx (SET, GET_MODE (to), to,
+                  plus_constant (to, count * 4 * sign));
       i = 1;
       count++;
-  }
+    }
+
   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));
-  }
+       = gen_rtx (SET, VOIDmode,
+                  gen_rtx (MEM, SImode, plus_constant (to, j * 4 * sign)),
+                  gen_rtx (REG, SImode, base_regno + j));
+    }
+
   if (write_back)
     XVECEXP (result, 0, i) = gen_rtx (CLOBBER, SImode, to);
 
@@ -762,8 +779,9 @@ gen_compare_reg (code, x, y, fp)
   return cc_reg;
 }
 
+void
 arm_reload_out_hi (operands)
-rtx operands[];
+     rtx *operands;
 {
   rtx base = find_replacement (&XEXP (operands[0], 0));
 
@@ -785,16 +803,16 @@ rtx operands[];
 
 int
 arm_backwards_branch (from, to)
-int from, to;
+     int from, to;
 {
-  return (insn_addresses[to] <= insn_addresses[from]);
+  return insn_addresses[to] <= insn_addresses[from];
 }
 
 /* Check to see if a branch is within the distance that can be done using
    an arithmetic expression. */
 int
 short_branch (from, to)
-int from, to;
+     int from, to;
 {
   int delta = insn_addresses[from] + 8 - insn_addresses[to];
 
@@ -805,7 +823,7 @@ int from, to;
    code */
 int
 arm_insn_not_targeted (insn)
-rtx insn;
+     rtx insn;
 {
   return insn != arm_target_insn;
 }
@@ -813,13 +831,12 @@ rtx insn;
 \f
 /* Routines to output assembly language.  */
 
-/* fp_immediate_constant 
-   if the rtx is the correct value then return the string of the number.
+/* If the rtx is the correct value then return the string of the number.
    In this way we can ensure that valid double constants are generated even
    when cross compiling. */
 char *
 fp_immediate_constant (x)
-rtx (x);
+     rtx (x);
 {
   REAL_VALUE_TYPE r;
   int i;
@@ -831,6 +848,7 @@ rtx (x);
   for (i = 0; i < 8; i++)
     if (REAL_VALUES_EQUAL (r, values_fpa[i]))
       return strings_fpa[i];
+
   abort ();
 }
 
@@ -858,30 +876,31 @@ print_multi_reg (stream, instr, mask, hat)
        fprintf (stream, "%s", reg_names[i]);
        not_first = TRUE;
       }
+
   fprintf (stream, "}%s\n", hat ? "^" : "");
-} /* print_multi_reg */
+}
 
 /* Output a 'call' insn. */
 
 char *
 output_call (operands)
-       rtx operands[];
+     rtx *operands;
 {
   /* Handle calls to lr using ip (which may be clobbered in subr anyway). */
 
   if (REGNO (operands[0]) == 14)
     {
       operands[0] = gen_rtx (REG, SImode, 12);
-      arm_output_asm_insn ("mov\t%0, lr", operands);
+      output_asm_insn ("mov\t%0, lr", operands);
     }
-  arm_output_asm_insn ("mov\tlr, pc", operands);
-  arm_output_asm_insn ("mov\tpc, %0", operands);
-  return ("");
-} /* output_call */
+  output_asm_insn ("mov\tlr, pc", operands);
+  output_asm_insn ("mov\tpc, %0", operands);
+  return "";
+}
 
 static int
 eliminate_lr2ip (x)
-rtx *x;
+     rtx *x;
 {
   int something_changed = 0;
   rtx x0 = *x;
@@ -915,17 +934,18 @@ rtx *x;
 
 char *
 output_call_mem (operands)
-       rtx operands[];
+     rtx *operands;
 {
   operands[0] = copy_rtx (operands[0]); /* Be ultra careful */
   /* Handle calls using lr by using ip (which may be clobbered in subr anyway).
    */
   if (eliminate_lr2ip (&operands[0]))
-    arm_output_asm_insn ("mov\tip, lr", operands);
-  arm_output_asm_insn ("mov\tlr, pc", operands);
-  arm_output_asm_insn ("ldr\tpc, %0", operands);
-  return ("");
-} /* output_call */
+    output_asm_insn ("mov\tip, lr", operands);
+
+  output_asm_insn ("mov\tlr, pc", operands);
+  output_asm_insn ("ldr\tpc, %0", operands);
+  return "";
+}
 
 
 /* Output a move from arm registers to an fpu registers.
@@ -934,21 +954,22 @@ output_call_mem (operands)
 
 char *
 output_mov_long_double_fpu_from_arm (operands)
-     rtx operands[];
+     rtx *operands;
 {
   int arm_reg0 = REGNO (operands[1]);
   rtx ops[3];
 
   if (arm_reg0 == 12)
     abort();
+
   ops[0] = gen_rtx (REG, SImode, arm_reg0);
   ops[1] = gen_rtx (REG, SImode, 1 + arm_reg0);
   ops[2] = gen_rtx (REG, SImode, 2 + arm_reg0);
   
-  arm_output_asm_insn ("stmfd\tsp!, {%0, %1, %2}", ops);
-  arm_output_asm_insn ("ldfe\t%0, [sp], #12", operands);
-  return ("");
-} /* output_mov_long_double_fpu_from_arm */
+  output_asm_insn ("stmfd\tsp!, {%0, %1, %2}", ops);
+  output_asm_insn ("ldfe\t%0, [sp], #12", operands);
+  return "";
+}
 
 /* Output a move from an fpu register to arm registers.
    OPERANDS[0] is the first registers of an arm register pair.
@@ -956,28 +977,29 @@ output_mov_long_double_fpu_from_arm (operands)
 
 char *
 output_mov_long_double_arm_from_fpu (operands)
-     rtx operands[];
+     rtx *operands;
 {
   int arm_reg0 = REGNO (operands[0]);
   rtx ops[3];
 
   if (arm_reg0 == 12)
     abort();
+
   ops[0] = gen_rtx (REG, SImode, arm_reg0);
   ops[1] = gen_rtx (REG, SImode, 1 + arm_reg0);
   ops[2] = gen_rtx (REG, SImode, 2 + arm_reg0);
 
-  arm_output_asm_insn ("stfe\t%1, [sp, #-12]!", operands);
-  arm_output_asm_insn ("ldmfd\tsp!, {%0, %1, %2}", ops);
-  return("");
-} /* output_mov_long_double_arm_from_fpu */
+  output_asm_insn ("stfe\t%1, [sp, #-12]!", operands);
+  output_asm_insn ("ldmfd\tsp!, {%0, %1, %2}", ops);
+  return "";
+}
 
 /* Output a move from arm registers to arm registers of a long double
    OPERANDS[0] is the destination.
    OPERANDS[1] is the source.  */
 char *
 output_mov_long_double_arm_from_arm (operands)
-rtx operands[];
+     rtx *operands;
 {
   /* We have to be careful here because the two might overlap */
   int dest_start = REGNO (operands[0]);
@@ -991,7 +1013,7 @@ rtx operands[];
        {
          ops[0] = gen_rtx (REG, SImode, dest_start + i);
          ops[1] = gen_rtx (REG, SImode, src_start + i);
-         arm_output_asm_insn ("mov\t%0, %1", ops);
+         output_asm_insn ("mov\t%0, %1", ops);
        }
     }
   else
@@ -1000,9 +1022,10 @@ rtx operands[];
        {
          ops[0] = gen_rtx (REG, SImode, dest_start + i);
          ops[1] = gen_rtx (REG, SImode, src_start + i);
-         arm_output_asm_insn ("mov\t%0, %1", ops);
+         output_asm_insn ("mov\t%0, %1", ops);
        }
     }
+
   return "";
 }
 
@@ -1013,7 +1036,7 @@ rtx operands[];
 
 char *
 output_mov_double_fpu_from_arm (operands)
-     rtx operands[];
+     rtx *operands;
 {
   int arm_reg0 = REGNO (operands[1]);
   rtx ops[2];
@@ -1022,10 +1045,10 @@ output_mov_double_fpu_from_arm (operands)
     abort();
   ops[0] = gen_rtx (REG, SImode, arm_reg0);
   ops[1] = gen_rtx (REG, SImode, 1 + arm_reg0);
-  arm_output_asm_insn ("stmfd\tsp!, {%0, %1}", ops);
-  arm_output_asm_insn ("ldfd\t%0, [sp], #8", operands);
-  return ("");
-} /* output_mov_double_fpu_from_arm */
+  output_asm_insn ("stmfd\tsp!, {%0, %1}", ops);
+  output_asm_insn ("ldfd\t%0, [sp], #8", operands);
+  return "";
+}
 
 /* Output a move from an fpu register to arm registers.
    OPERANDS[0] is the first registers of an arm register pair.
@@ -1033,19 +1056,20 @@ output_mov_double_fpu_from_arm (operands)
 
 char *
 output_mov_double_arm_from_fpu (operands)
-     rtx operands[];
+     rtx *operands;
 {
   int arm_reg0 = REGNO (operands[0]);
   rtx ops[2];
 
   if (arm_reg0 == 12)
     abort();
+
   ops[0] = gen_rtx (REG, SImode, arm_reg0);
   ops[1] = gen_rtx (REG, SImode, 1 + arm_reg0);
-  arm_output_asm_insn ("stfd\t%1, [sp, #-8]!", operands);
-  arm_output_asm_insn ("ldmfd\tsp!, {%0, %1}", ops);
-  return("");
-} /* output_mov_double_arm_from_fpu */
+  output_asm_insn ("stfd\t%1, [sp, #-8]!", operands);
+  output_asm_insn ("ldmfd\tsp!, {%0, %1}", ops);
+  return "";
+}
 
 /* Output a move between double words.
    It must be REG<-REG, REG<-CONST_DOUBLE, REG<-CONST_INT, REG<-MEM
@@ -1053,7 +1077,7 @@ output_mov_double_arm_from_fpu (operands)
 
 char *
 output_move_double (operands)
-     rtx operands[];
+     rtx *operands;
 {
   enum rtx_code code0 = GET_CODE (operands[0]);
   enum rtx_code code1 = GET_CODE (operands[1]);
@@ -1069,18 +1093,19 @@ output_move_double (operands)
          int reg1 = REGNO (operands[1]);
          if (reg1 == 12)
            abort();
+
          otherops[1] = gen_rtx (REG, SImode, 1 + reg1);
 
          /* Ensure the second source is not overwritten */
          if (reg0 == 1 + reg1)
            {
-             arm_output_asm_insn("mov\t%0, %1", otherops);
-             arm_output_asm_insn("mov\t%0, %1", operands);
+             output_asm_insn("mov\t%0, %1", otherops);
+             output_asm_insn("mov\t%0, %1", operands);
            }
          else
            {
-             arm_output_asm_insn("mov\t%0, %1", operands);
-             arm_output_asm_insn("mov\t%0, %1", otherops);
+             output_asm_insn("mov\t%0, %1", operands);
+             output_asm_insn("mov\t%0, %1", otherops);
            }
        }
       else if (code1 == CONST_DOUBLE)
@@ -1099,9 +1124,9 @@ output_move_double (operands)
          /* Note: output_mov_immediate may clobber operands[1], so we
             put this out first */
          if (INTVAL (operands[1]) < 0)
-           arm_output_asm_insn ("mvn\t%0, %1", otherops);
+           output_asm_insn ("mvn\t%0, %1", otherops);
          else
-           arm_output_asm_insn ("mov\t%0, %1", otherops);
+           output_asm_insn ("mov\t%0, %1", otherops);
          output_mov_immediate (operands, FALSE, "");
        }
       else if (code1 == MEM)
@@ -1112,39 +1137,39 @@ output_move_double (operands)
              /* Handle the simple case where address is [r, #0] more
                 efficient.  */
              operands[1] = XEXP (operands[1], 0);
-             arm_output_asm_insn ("ldmia\t%1, %M0", operands);
+             output_asm_insn ("ldmia\t%1, %M0", operands);
              break;
            case PRE_INC:
              operands[1] = XEXP (XEXP (operands[1], 0), 0);
-             arm_output_asm_insn ("add\t%1, %1, #8", operands);
-             arm_output_asm_insn ("ldmia\t%1, %M0", operands);
+             output_asm_insn ("add\t%1, %1, #8", operands);
+             output_asm_insn ("ldmia\t%1, %M0", operands);
              break;
            case PRE_DEC:
              operands[1] = XEXP (XEXP (operands[1], 0), 0);
-             arm_output_asm_insn ("sub\t%1, %1, #8", operands);
-             arm_output_asm_insn ("ldmia\t%1, %M0", operands);
+             output_asm_insn ("sub\t%1, %1, #8", operands);
+             output_asm_insn ("ldmia\t%1, %M0", operands);
              break;
            case POST_INC:
              operands[1] = XEXP (XEXP (operands[1], 0), 0);
-             arm_output_asm_insn ("ldmia\t%1!, %M0", operands);
+             output_asm_insn ("ldmia\t%1!, %M0", operands);
              break;
            case POST_DEC:
              operands[1] = XEXP (XEXP (operands[1], 0), 0);
-             arm_output_asm_insn ("ldmia\t%1, %M0", operands);
-             arm_output_asm_insn ("sub\t%1, %1, #8", operands);
+             output_asm_insn ("ldmia\t%1, %M0", operands);
+             output_asm_insn ("sub\t%1, %1, #8", operands);
              break;
            default:
              otherops[1] = adj_offsettable_operand (operands[1], 4);
              /* Take care of overlapping base/data reg.  */
              if (reg_mentioned_p (operands[0], operands[1]))
                {
-                 arm_output_asm_insn ("ldr\t%0, %1", otherops);
-                 arm_output_asm_insn ("ldr\t%0, %1", operands);
+                 output_asm_insn ("ldr\t%0, %1", otherops);
+                 output_asm_insn ("ldr\t%0, %1", operands);
                }
              else
                {
-                 arm_output_asm_insn ("ldr\t%0, %1", operands);
-                 arm_output_asm_insn ("ldr\t%0, %1", otherops);
+                 output_asm_insn ("ldr\t%0, %1", operands);
+                 output_asm_insn ("ldr\t%0, %1", otherops);
                }
            }
        }
@@ -1158,32 +1183,32 @@ output_move_double (operands)
         {
        case REG:
          operands[0] = XEXP (operands[0], 0);
-         arm_output_asm_insn ("stmia\t%0, %M1", operands);
+         output_asm_insn ("stmia\t%0, %M1", operands);
          break;
         case PRE_INC:
          operands[0] = XEXP (XEXP (operands[0], 0), 0);
-         arm_output_asm_insn ("add\t%0, %0, #8", operands);
-         arm_output_asm_insn ("stmia\t%0, %M1", operands);
+         output_asm_insn ("add\t%0, %0, #8", operands);
+         output_asm_insn ("stmia\t%0, %M1", operands);
          break;
         case PRE_DEC:
          operands[0] = XEXP (XEXP (operands[0], 0), 0);
-         arm_output_asm_insn ("sub\t%0, %0, #8", operands);
-         arm_output_asm_insn ("stmia\t%0, %M1", operands);
+         output_asm_insn ("sub\t%0, %0, #8", operands);
+         output_asm_insn ("stmia\t%0, %M1", operands);
          break;
         case POST_INC:
          operands[0] = XEXP (XEXP (operands[0], 0), 0);
-         arm_output_asm_insn ("stmia\t%0!, %M1", operands);
+         output_asm_insn ("stmia\t%0!, %M1", operands);
          break;
         case POST_DEC:
          operands[0] = XEXP (XEXP (operands[0], 0), 0);
-         arm_output_asm_insn ("stmia\t%0, %M1", operands);
-         arm_output_asm_insn ("sub\t%0, %0, #8", operands);
+         output_asm_insn ("stmia\t%0, %M1", operands);
+         output_asm_insn ("sub\t%0, %0, #8", operands);
          break;
         default:
          otherops[0] = adj_offsettable_operand (operands[0], 4);
          otherops[1] = gen_rtx (REG, SImode, 1 + REGNO (operands[1]));
-         arm_output_asm_insn ("str\t%1, %0", operands);
-         arm_output_asm_insn ("str\t%1, %0", otherops);
+         output_asm_insn ("str\t%1, %0", operands);
+         output_asm_insn ("str\t%1, %0", otherops);
        }
     }
   else abort();  /* Constraints should prevent this */
@@ -1197,23 +1222,25 @@ output_move_double (operands)
 
 char *
 output_mov_immediate (operands)
-     rtx operands[2];
+     rtx *operands;
 {
-  int n = INTVAL (operands[1]);
+  HOST_WIDE_INT n = INTVAL (operands[1]);
   int n_ones = 0;
   int i;
 
   /* Try to use one MOV */
-
   if (const_ok_for_arm (n))
-    return (arm_output_asm_insn ("mov\t%0, %1", operands));
+    {
+      output_asm_insn ("mov\t%0, %1", operands);
+      return "";
+    }
 
   /* Try to use one MVN */
-
-  if (const_ok_for_arm(~n))
+  if (const_ok_for_arm (~n))
     {
-      operands[1] = gen_rtx (CONST_INT, VOIDmode, ~n);
-      return (arm_output_asm_insn ("mvn\t%0, %1", operands));
+      operands[1] = GEN_INT (~n);
+      output_asm_insn ("mvn\t%0, %1", operands);
+      return "";
     }
 
   /* If all else fails, make it out of ORRs or BICs as appropriate. */
@@ -1226,8 +1253,9 @@ output_mov_immediate (operands)
     output_multi_immediate(operands, "mvn\t%0, %1", "bic\t%0, %0, %1", 1, ~n);
   else
     output_multi_immediate(operands, "mov\t%0, %1", "orr\t%0, %0, %1", 1, n);
-  return("");
-} /* output_mov_immediate */
+
+  return "";
+}
 
 
 /* Output an ADD r, s, #n where n may be too big for one instruction.  If
@@ -1235,9 +1263,9 @@ output_mov_immediate (operands)
 
 char *
 output_add_immediate (operands)
-     rtx operands[3];
+     rtx *operands;
 {
-  int n = INTVAL (operands[2]);
+  HOST_WIDE_INT n = INTVAL (operands[2]);
 
   if (n != 0 || REGNO (operands[0]) != REGNO (operands[1]))
     {
@@ -1248,8 +1276,9 @@ output_add_immediate (operands)
        output_multi_immediate (operands,
                                "add\t%0, %1, %2", "add\t%0, %0, %2", 2, n);
     }
-  return("");
-} /* output_add_immediate */
+
+  return "";
+}
 
 
 /* Output a multiple immediate operation.
@@ -1261,14 +1290,19 @@ output_add_immediate (operands)
 
 char *
 output_multi_immediate (operands, instr1, instr2, immed_op, n)
-     rtx operands[];
+     rtx *operands;
      char *instr1, *instr2;
-     int immed_op, n;
+     int immed_op;
+     HOST_WIDE_INT n;
 {
+#if HOST_BITS_PER_WIDE_INT > 32
+  n &= 0xffffffff;
+#endif
+
   if (n == 0)
     {
       operands[immed_op] = const0_rtx;
-      arm_output_asm_insn (instr1, operands); /* Quick and easy output */
+      output_asm_insn (instr1, operands); /* Quick and easy output */
     }
   else
     {
@@ -1276,20 +1310,18 @@ output_multi_immediate (operands, instr1, instr2, immed_op, n)
       char *instr = instr1;
 
       /* Note that n is never zero here (which would give no output) */
-
       for (i = 0; i < 32; i += 2)
        {
          if (n & (3 << i))
            {
-             operands[immed_op] = gen_rtx (CONST_INT, VOIDmode,
-                                           n & (255 << i));
-             arm_output_asm_insn (instr, operands);
+             operands[immed_op] = GEN_INT (n & (255 << i));
+             output_asm_insn (instr, operands);
              instr = instr2;
              i += 6;
            }
        }
     }
-  return ("");
+  return "";
 } /* output_multi_immediate */
 
 
@@ -1301,27 +1333,29 @@ output_multi_immediate (operands, instr1, instr2, immed_op, n)
 char *
 arithmetic_instr (op, shift_first_arg)
      rtx op;
+     int shift_first_arg;
 {
   switch (GET_CODE(op))
     {
     case PLUS:
-      return ("add");
+      return "add";
+
     case MINUS:
-      if (shift_first_arg)
-       return ("rsb");
-      else
-       return ("sub");
+      return shift_first_arg ? "rsb" : "sub";
+
     case IOR:
-      return ("orr");
+      return "orr";
+
     case XOR:
-      return ("eor");
+      return "eor";
+
     case AND:
-      return ("and");
+      return "and";
+
     default:
-      abort();
+      abort ();
     }
-  return ("");                 /* stupid cc */
-} /* arithmetic_instr */
+}
 
 
 /* Ensure valid constant shifts and return the appropriate shift mnemonic
@@ -1343,20 +1377,23 @@ shift_instr (op, shift_ptr)
     case ASHIFT:
       mnem = "asl";
       break;
+
     case ASHIFTRT:
       mnem = "asr";
       max_shift = 32;
       break;
+
     case LSHIFTRT:
       mnem = "lsr";
       max_shift = 32;
       break;
+
     case MULT:
-      *shift_ptr = gen_rtx (CONST_INT, VOIDmode,
-                           int_log2 (INTVAL (*shift_ptr)));
-      return ("asl");
+      *shift_ptr = GEN_INT (int_log2 (INTVAL (*shift_ptr)));
+      return "asl";
+
     default:
-      abort();
+      abort ();
     }
 
   if (GET_CODE (*shift_ptr) == CONST_INT)
@@ -1374,20 +1411,21 @@ shift_instr (op, shift_ptr)
 
 /* Obtain the shift from the POWER of two. */
 
-int
+HOST_WIDE_INT
 int_log2 (power)
-     unsigned int power;
+     HOST_WIDE_INT power;
 {
-  int shift = 0;
+  HOST_WIDE_INT shift = 0;
 
   while (((1 << shift) & power) == 0)
     {
       if (shift > 31)
-       abort();
+       abort ();
       shift++;
     }
-  return (shift);
-} /* int_log2 */
+
+  return shift;
+}
 
 
 /* Output an arithmetic instruction which may set the condition code.
@@ -1400,7 +1438,7 @@ int_log2 (power)
 
 char *
 output_arithmetic (operands, const_first_arg, set_cond)
-     rtx operands[4];
+     rtx *operands;
      int const_first_arg;
      int set_cond;
 {
@@ -1408,8 +1446,9 @@ output_arithmetic (operands, const_first_arg, set_cond)
   char *instr = arithmetic_instr (operands[1], const_first_arg);
 
   sprintf (mnemonic, "%s%s\t%%0, %%2, %%3", instr, set_cond ? "s" : "");
-  return (arm_output_asm_insn (mnemonic, operands));
-} /* output_arithmetic */
+  output_asm_insn (mnemonic, operands);
+  return "";
+}
 
 
 /* Output an arithmetic instruction with a shift.
@@ -1424,7 +1463,7 @@ output_arithmetic (operands, const_first_arg, set_cond)
 
 char *
 output_arithmetic_with_shift (operands, shift_first_arg, set_cond)
-     rtx operands[6];
+     rtx *operands;
      int shift_first_arg;
      int set_cond;
 {
@@ -1434,9 +1473,9 @@ output_arithmetic_with_shift (operands, shift_first_arg, set_cond)
   char *shift = shift_instr (GET_CODE (operands[3]), &operands[5]);
 
   sprintf (mnemonic, "%s%s\t%%0, %%2, %%4, %s %%5", instr, condbit, shift);
-  return (arm_output_asm_insn (mnemonic, operands));
-} /* output_arithmetic_with_shift */
-
+  output_asm_insn (mnemonic, operands);
+  return "";
+}
 
 /* Output an arithmetic instruction with a power of two multiplication.
    OPERANDS[0] is the destination register.
@@ -1448,16 +1487,17 @@ output_arithmetic_with_shift (operands, shift_first_arg, set_cond)
 
 char *
 output_arithmetic_with_immediate_multiply (operands, shift_first_arg)
-     rtx operands[5];
+     rtx *operands;
      int shift_first_arg;
 {
   char mnemonic[80];
   char *instr = arithmetic_instr (operands[1], shift_first_arg);
-  int shift = int_log2 (INTVAL (operands[4]));
+  HOST_WIDE_INT shift = int_log2 (INTVAL (operands[4]));
 
-  sprintf (mnemonic, "%s\t%%0, %%2, %%3, asl#%d", instr, shift);
-  return (arm_output_asm_insn (mnemonic, operands));
-} /* output_arithmetic_with_immediate_multiply */
+  sprintf (mnemonic, "%s\t%%0, %%2, %%3, asl#%d", instr, (int) shift);
+  output_asm_insn (mnemonic, operands);
+  return "";
+}
 
 
 /* Output a move with a shift.
@@ -1469,7 +1509,7 @@ output_arithmetic_with_immediate_multiply (operands, shift_first_arg)
 char *
 output_shifted_move (op, operands)
      enum rtx_code op;
-     rtx operands[2];
+     rtx *operands;
 {
   char mnemonic[80];
 
@@ -1478,13 +1518,15 @@ output_shifted_move (op, operands)
   else
     sprintf (mnemonic, "mov\t%%0, %%1, %s %%2",
             shift_instr (op, &operands[2]));
-  return (arm_output_asm_insn (mnemonic, operands));
-} /* output_shifted_move */
+
+  output_asm_insn (mnemonic, operands);
+  return "";
+}
 
 char *
 output_shift_compare (operands, neg)
-rtx *operands;
-int neg;
+     rtx *operands;
+     int neg;
 {
   char buf[80];
 
@@ -1494,8 +1536,9 @@ int neg;
   else
     sprintf (buf, "cmp\t%%1, %%3, %s %%4", shift_instr (GET_CODE (operands[2]),
                                                        &operands[4]));
-  return arm_output_asm_insn (buf, operands);
-} /* output_shift_compare */
+  output_asm_insn (buf, operands);
+  return "";
+}
 
 /* Output a .ascii pseudo-op, keeping track of lengths.  This is because
    /bin/as is horribly restrictive.  */
@@ -1529,6 +1572,7 @@ output_ascii_pseudo_op (stream, p, len)
          putc('\\', stream);
          len_so_far++;
        }
+
       if (c >= ' ' && c < 0177)
        {
          putc (c, stream);
@@ -1539,11 +1583,13 @@ output_ascii_pseudo_op (stream, p, len)
          fprintf (stream, "\\%03o", c);
          len_so_far +=4;
        }
+
       chars_so_far++;
     }
+
   fputs ("\"\n", stream);
   arm_increase_location (chars_so_far);
-} /* output_ascii_pseudo_op */
+}
 \f
 
 /* Try to determine whether a pattern really clobbers the link register.
@@ -1556,7 +1602,7 @@ output_ascii_pseudo_op (stream, p, len)
 
 static int
 pattern_really_clobbers_lr (x)
-rtx x;
+     rtx x;
 {
   int i;
   
@@ -1567,34 +1613,43 @@ rtx x;
        {
        case REG:
          return REGNO (SET_DEST (x)) == 14;
+
         case SUBREG:
          if (GET_CODE (XEXP (SET_DEST (x), 0)) == REG)
            return REGNO (XEXP (SET_DEST (x), 0)) == 14;
+
          if (GET_CODE (XEXP (SET_DEST (x), 0)) == MEM)
            return 0;
          abort ();
+
         default:
          return 0;
         }
+
     case PARALLEL:
       for (i = 0; i < XVECLEN (x, 0); i++)
        if (pattern_really_clobbers_lr (XVECEXP (x, 0, i)))
          return 1;
       return 0;
+
     case CLOBBER:
       switch (GET_CODE (XEXP (x, 0)))
         {
        case REG:
          return REGNO (XEXP (x, 0)) == 14;
+
         case SUBREG:
          if (GET_CODE (XEXP (XEXP (x, 0), 0)) == REG)
            return REGNO (XEXP (XEXP (x, 0), 0)) == 14;
          abort ();
+
         default:
          return 0;
         }
+
     case UNSPEC:
       return 1;
+
     default:
       return 0;
     }
@@ -1602,7 +1657,7 @@ rtx x;
 
 static int
 function_really_clobbers_lr (first)
-rtx first;
+     rtx first;
 {
   rtx insn, next;
   
@@ -1616,15 +1671,18 @@ rtx first;
        case JUMP_INSN:         /* Jump insns only change the PC (and conds) */
        case INLINE_HEADER:
          break;
+
         case INSN:
          if (pattern_really_clobbers_lr (PATTERN (insn)))
            return 1;
          break;
+
         case CALL_INSN:
          /* Don't yet know how to handle those calls that are not to a 
             SYMBOL_REF */
          if (GET_CODE (PATTERN (insn)) != PARALLEL)
            abort ();
+
          switch (GET_CODE (XVECEXP (PATTERN (insn), 0, 0)))
            {
            case CALL:
@@ -1632,15 +1690,18 @@ rtx first;
                  != SYMBOL_REF)
                return 1;
              break;
+
            case SET:
              if (GET_CODE (XEXP (XEXP (SET_SRC (XVECEXP (PATTERN (insn),
                                                          0, 0)), 0), 0))
                  != SYMBOL_REF)
                return 1;
              break;
+
            default:    /* Don't recognize it, be safe */
              return 1;
            }
+
          /* A call can be made (by peepholing) not to clobber lr iff it is
             followed by a return.  There may, however, be a use insn iff
             we are returning the result of the call. 
@@ -1650,40 +1711,44 @@ rtx first;
             must reject this.  (Can this be fixed by adding our own insn?) */
          if ((next = next_nonnote_insn (insn)) == NULL)
            return 1;
+
          if (GET_CODE (next) == INSN && GET_CODE (PATTERN (next)) == USE
              && (GET_CODE (XVECEXP (PATTERN (insn), 0, 0)) == SET)
              && (REGNO (SET_DEST (XVECEXP (PATTERN (insn), 0, 0)))
                  == REGNO (XEXP (PATTERN (next), 0))))
            if ((next = next_nonnote_insn (next)) == NULL)
              return 1;
+
          if (GET_CODE (next) == JUMP_INSN
              && GET_CODE (PATTERN (next)) == RETURN)
            break;
          return 1;
+
         default:
          abort ();
         }
     }
+
   /* We have reached the end of the chain so lr was _not_ clobbered */
   return 0;
 }
 
 char *
 output_return_instruction (operand, really_return)
-rtx operand;
-int really_return;
+     rtx operand;
+     int really_return;
 {
   char instr[100];
   int reg, live_regs = 0;
 
-  if (current_function_calls_alloca && !really_return)
+  if (current_function_calls_alloca && ! really_return)
     abort();
     
-  for (reg = 4; reg < 10; reg++)
-    if (regs_ever_live[reg])
+  for (reg = 0; reg <= 10; reg++)
+    if (regs_ever_live[reg] && ! call_used_regs[reg])
       live_regs++;
 
-  if (live_regs || (regs_ever_live[14] && !lr_save_eliminated))
+  if (live_regs || (regs_ever_live[14] && ! lr_save_eliminated))
     live_regs++;
 
   if (frame_pointer_needed)
@@ -1691,19 +1756,22 @@ int really_return;
 
   if (live_regs)
     {
-      if (lr_save_eliminated || !regs_ever_live[14])
+      if (lr_save_eliminated || ! regs_ever_live[14])
         live_regs++;
+
       if (frame_pointer_needed)
         strcpy (instr, "ldm%d0ea\tfp, {");
       else
         strcpy (instr, "ldm%d0fd\tsp!, {");
-      for (reg = 4; reg < 10; reg++)
-        if (regs_ever_live[reg])
+
+      for (reg = 0; reg <= 10; reg++)
+        if (regs_ever_live[reg] && ! call_used_regs[reg])
           {
             strcat (instr, reg_names[reg]);
            if (--live_regs)
               strcat (instr, ", ");
           }
+
       if (frame_pointer_needed)
         {
           strcat (instr, reg_names[11]);
@@ -1715,17 +1783,61 @@ int really_return;
       else
         strcat (instr, really_return ? reg_names[15] : reg_names[14]);
       strcat (instr, (TARGET_6 || !really_return) ? "}" : "}^");
-      arm_output_asm_insn (instr, &operand);
+      output_asm_insn (instr, &operand);
     }
   else if (really_return)
     {
       strcpy (instr, TARGET_6 ? "mov%d0\tpc, lr" : "mov%d0s\tpc, lr");
-      arm_output_asm_insn (instr, &operand);
+      output_asm_insn (instr, &operand);
     }
+
   return_used_this_function = 1;
   return "";
 }
 
+/* Return the size of the prologue.  It's not too bad if we slightly 
+   over-estimate.  */
+
+static int
+get_prologue_size ()
+{
+  int amount = 0;
+  int regno;
+
+  /* Until we know which registers are really used return the maximum.  */
+  if (! reload_completed)
+    return 24;
+
+  /* Look for integer regs that have to be saved. */
+  for (regno = 0; regno < 15; regno++)
+    if (regs_ever_live[regno] && ! call_used_regs[regno])
+      {
+       amount = 4;
+       break;
+      }
+
+  /* Clobbering lr when none of the other regs have been saved also requires
+     a save.  */
+  if (regs_ever_live[14])
+    amount = 4;
+
+  /* If we need to push a stack frame then there is an extra instruction to
+     preserve the current value of the stack pointer. */
+  if (frame_pointer_needed)
+    amount = 8;
+
+  /* Now look for floating-point regs that need saving.  We need an 
+     instruction per register.  */
+  for (regno = 16; regno < 24; regno++)
+    if (regs_ever_live[regno] && ! call_used_regs[regno])
+      amount += 4;
+
+  if (current_function_anonymous_args && current_function_pretend_args_size)
+    amount += 4;
+
+  return amount;
+}
+
 /* The amount of stack adjustment that happens here, in output_return and in
    output_epilogue must be exactly the same as was calculated during reload,
    or things will point to the wrong place.  The only time we can safely
@@ -1736,11 +1848,11 @@ int really_return;
    onto the stack. */
    
 void
-output_prologue (f, frame_size)
+output_func_prologue (f, frame_size)
      FILE *f;
      int frame_size;
 {
-  int reg, live_regs_mask = 0, code_size = 0;
+  int reg, live_regs_mask = 0;
   rtx operands[3];
 
   /* Nonzero if we must stuff some register arguments onto the stack as if
@@ -1762,20 +1874,19 @@ output_prologue (f, frame_size)
   if (current_function_anonymous_args && current_function_pretend_args_size)
     store_arg_regs = 1;
 
-  for (reg = 4; reg < 10; reg++)
-    if (regs_ever_live[reg])
+  for (reg = 0; reg <= 10; reg++)
+    if (regs_ever_live[reg] && ! call_used_regs[reg])
       live_regs_mask |= (1 << reg);
 
   if (frame_pointer_needed)
     {
       live_regs_mask |= 0xD800;
       fputs ("\tmov\tip, sp\n", f);
-      code_size += 4;
     }
   else if (regs_ever_live[14])
     {
       if (! current_function_args_size
-         && !function_really_clobbers_lr (get_insns ()))
+         && ! function_really_clobbers_lr (get_insns ()))
        {
          fprintf (f,"\t@ I don't think this function clobbers lr\n");
          lr_save_eliminated = 1;
@@ -1798,7 +1909,6 @@ output_prologue (f, frame_size)
               arg_size > 0; reg--, arg_size -= 4)
            mask |= (1 << reg);
          print_multi_reg (f, "stmfd\tsp!", mask, FALSE);
-         code_size += 4;
        }
       else
        {
@@ -1818,16 +1928,14 @@ output_prologue (f, frame_size)
 
       live_regs_mask |= 0x4000;
       lr_save_eliminated = 0;
+
+      /* Now push all the call-saved regs onto the stack */
       print_multi_reg (f, "stmfd\tsp!", live_regs_mask, FALSE);
-      code_size += 4;
     }
 
-  for (reg = 23; reg > 19; reg--)
-    if (regs_ever_live[reg])
-      {
-       fprintf (f, "\tstfe\t%s, [sp, #-12]!\n", reg_names[reg]);
-       code_size += 4;
-      }
+  for (reg = 23; reg > 15; reg--)
+    if (regs_ever_live[reg] && !call_used_regs[reg])
+      fprintf (f, "\tstfe\t%s, [sp, #-12]!\n", reg_names[reg]);
 
   if (frame_pointer_needed)
     {
@@ -1835,24 +1943,21 @@ output_prologue (f, frame_size)
 
       operands[0] = gen_rtx (REG, SImode, HARD_FRAME_POINTER_REGNUM);
       operands[1] = gen_rtx (REG, SImode, 12);
-      operands[2] = gen_rtx (CONST_INT, VOIDmode,
-                            - (4 + current_function_pretend_args_size));
+      operands[2] = GEN_INT ( - (4 + current_function_pretend_args_size));
       output_add_immediate (operands);
     }
 
   if (frame_size)
     {
       operands[0] = operands[1] = stack_pointer_rtx;
-      operands[2] = gen_rtx (CONST_INT, VOIDmode, -frame_size);
+      operands[2] = GEN_INT (-frame_size);
       output_add_immediate (operands);
     }
-
-  arm_increase_location (code_size);
-} /* output_prologue */
+}
 
 
 void
-output_epilogue (f, frame_size)
+output_func_epilogue (f, frame_size)
      FILE *f;
      int frame_size;
 {
@@ -1867,21 +1972,20 @@ output_epilogue (f, frame_size)
         {
           abort ();
         }
-      return;
+      goto epilogue_done;
     }
 
-  for (reg = 4; reg <= 10; reg++)
-    if (regs_ever_live[reg])
+  for (reg = 0; reg <= 10; reg++)
+    if (regs_ever_live[reg] && ! call_used_regs[reg])
       {
         live_regs_mask |= (1 << reg);
        floats_offset += 4;
       }
 
-
   if (frame_pointer_needed)
     {
-      for (reg = 23; reg >= 20; reg--)
-       if (regs_ever_live[reg])
+      for (reg = 23; reg > 15; reg--)
+       if (regs_ever_live[reg] && ! call_used_regs[reg])
          {
            fprintf (f, "\tldfe\t%s, [fp, #-%d]\n", reg_names[reg],
                     floats_offset);
@@ -1904,8 +2008,8 @@ output_epilogue (f, frame_size)
          output_add_immediate (operands);
        }
 
-      for (reg = 20; reg < 24; reg++)
-       if (regs_ever_live[reg])
+      for (reg = 16; reg < 24; reg++)
+       if (regs_ever_live[reg] && ! call_used_regs[reg])
          {
            fprintf (f, "\tldfe\t%s, [sp], #12\n", reg_names[reg]);
            code_size += 4;
@@ -1935,9 +2039,18 @@ output_epilogue (f, frame_size)
          code_size += 4;
        }
     }
-  arm_increase_location (code_size);
+
+ epilogue_done:
+
+  /* insn_addresses isn't allocated when not optimizing */
+
+  if (optimize > 0)
+    arm_increase_location (code_size
+                          + insn_addresses[INSN_UID (get_last_insn ())]
+                          + get_prologue_size ());
+
   current_function_anonymous_args = 0;
-} /* output_epilogue */
+}
 \f
 /* Increase the `arm_text_location' by AMOUNT if we're in the text
    segment.  */
@@ -1948,26 +2061,7 @@ arm_increase_location (amount)
 {
   if (in_text_section ())
     arm_text_location += amount;
-} /* arm_increase_location */
-
-
-/* Like output_asm_insn (), but also increases the arm_text_location (if in
-   the .text segment, of course, even though this will always be true).
-   Returns the empty string.  */
-
-char *
-arm_output_asm_insn (template, operands)
-     char *template;
-     rtx *operands;
-{
-  extern FILE *asm_out_file;
-
-  output_asm_insn (template, operands);
-  if (in_text_section ())
-    arm_text_location += 4;
-  fflush (asm_out_file);
-  return ("");
-} /* arm_output_asm_insn */
+}
 
 
 /* Output a label definition.  If this label is within the .text segment, it
@@ -2003,91 +2097,38 @@ arm_asm_output_label (stream, name)
     }
   for (s = real_name; *s; s++)
     hash += *s;
+
   hash = hash % LABEL_HASH_SIZE;
   cur = (struct label_offset *) xmalloc (sizeof (struct label_offset));
   cur->name = real_name;
   cur->offset = arm_text_location;
   cur->cdr = offset_table[hash];
   offset_table[hash] = cur;
-} /* arm_asm_output_label */
-
-
-/* Output the instructions needed to perform what Martin's /bin/as called
-   llc: load an SImode thing from the function's constant pool.
+}
 
-   XXX This could be enhanced in that we do not really need a pointer in the
-   constant pool pointing to the real thing.  If we can address this pointer,
-   we can also address what it is pointing at, in fact, anything in the text
-   segment which has been defined already within this .s file.  */
+/* Load a symbol that is known to be in the text segment into a register.
+   This should never be called when not optimizing.  */
 
 char *
-arm_output_llc (operands)
+output_load_symbol (insn, operands)
+     rtx insn;
      rtx *operands;
 {
-  char *s, *name = XSTR (XEXP (operands[1], 0), 0);
-  struct label_offset *he;
-  int hash = 0, conditional = (arm_ccfsm_state == 3 || arm_ccfsm_state == 4);
-
-  if (*name != '*')
-    abort ();
-
-  for (s = &name[1]; *s; s++)
-    hash += *s;
-  hash = hash % LABEL_HASH_SIZE;
-  he = offset_table[hash];
-  while (he && strcmp (he->name, &name[1]))
-    he = he->cdr;
-
-  if (!he)
-    abort ();
-
-  if (arm_text_location + 8 - he->offset < 4095)
-    {
-      fprintf (asm_out_file, "\tldr%s\t%s, [pc, #%s - . - 8]\n",
-              conditional ? arm_condition_codes[arm_current_cc] : "",
-              reg_names[REGNO (operands[0])], &name[1]);
-      arm_increase_location (4);
-      return ("");
-    }
-  else
-    {
-      int offset = - (arm_text_location + 8 - he->offset);
-      char *reg_name = reg_names[REGNO (operands[0])];
-
-      /* ??? This is a hack, assuming the constant pool never is more than
-        (1 + 255) * 4096 == 1Meg away from the PC.  */
-
-      if (offset > 1000000)
-       abort ();
-
-      fprintf (asm_out_file, "\tsub%s\t%s, pc, #(8 + . - %s) & ~4095\n",
-              conditional ? arm_condition_codes[arm_current_cc] : "",
-              reg_name, &name[1]);
-      fprintf (asm_out_file, "\tldr%s\t%s, [%s, #- ((4 + . - %s) & 4095)]\n",
-              conditional ? arm_condition_codes[arm_current_cc] : "",
-              reg_name, reg_name, &name[1]);
-      arm_increase_location (8);
-    }
-  return ("");
-} /* arm_output_llc */
-
-/* output_load_symbol ()
-   load a symbol that is known to be in the text segment into a register */
-
-char *
-output_load_symbol (operands)
-rtx *operands;
-{
-  char *s, *name = XSTR (operands[1], 0);
+  char *s;
+  char *name = XSTR (operands[1], 0);
   struct label_offset *he;
   int hash = 0;
   int offset;
-  
-  if (*name != '*')
+  unsigned int mask, never_mask = 0xffffffff;
+  int shift, inst;
+  char buffer[100];
+
+  if (optimize == 0 || *name != '*')
     abort ();
 
   for (s = &name[1]; *s; s++)
     hash += *s;
+
   hash = hash % LABEL_HASH_SIZE;
   he = offset_table[hash];
   while (he && strcmp (he->name, &name[1]))
@@ -2096,45 +2137,48 @@ rtx *operands;
   if (!he)
     abort ();
   
-  offset = (arm_text_location + 8 - he->offset);
+  offset = (arm_text_location + insn_addresses[INSN_UID (insn)]
+           + get_prologue_size () + 8 - he->offset);
   if (offset < 0)
     abort ();
 
+  /* When generating the instructions, we never mask out the bits that we
+     think will be always zero, then if a mistake has occureed somewhere, the
+     assembler will spot it and generate an error.  */
+
   /* If the symbol is word aligned then we might be able to reduce the
-     number of loads */
-  if ((offset & 3) == 0)
+     number of loads.  */
+  shift = ((offset & 3) == 0) ? 2 : 0;
+
+  /* Clear the bits from NEVER_MASK that will be orred in with the individual
+     instructions.  */
+  for (; shift < 32; shift += 8)
     {
-      arm_output_asm_insn ("sub\t%0, pc, #(8 + . -%a1) & 1023", operands);
-      if (offset > 0x3ff)
-        {
-         arm_output_asm_insn ("sub\t%0, %0, #(4 + . -%a1) & 261120",
-                              operands);
-         if (offset > 0x3ffff)
-           {
-             arm_output_asm_insn ("sub\t%0, %0, #(. -%a1) & 66846720",
-                                  operands);
-             if (offset > 0x3ffffff)
-               arm_output_asm_insn ("sub\t%0, %0, #(. - 4 -%a1) & -67108864",
-                                      operands);
-           }
-        }
+      mask = 0xff << shift;
+      if ((offset & mask) || ((unsigned) offset) > mask)
+       never_mask &= ~mask;
     }
-  else
+
+  inst = 8;
+  mask = 0xff << (shift - 32);
+
+  while (mask && (never_mask & mask) == 0)
     {
-      arm_output_asm_insn ("sub\t%0, pc, #(8 + . -%a1) & 255", operands);
-      if (offset > 0x0ff)
-        {
-         arm_output_asm_insn ("sub\t%0, %0, #(4 + . -%a1) & 65280", operands);
-         if (offset > 0x0ffff)
-           {
-             arm_output_asm_insn ("sub\t%0, %0, #(. -%a1) & 16711680",
-                                  operands);
-             if (offset > 0x0ffffff)
-               arm_output_asm_insn ("sub\t%0, %0, #(. - 4 -%a1) & -16777216",
-                                    operands);
-           }
-        }
+      if (inst == 8)
+       {
+         strcpy (buffer, "sub\t%0, pc, #(8 + . -%a1)");
+         if ((never_mask | mask) != 0xffffffff)
+           sprintf (buffer + strlen (buffer), " & 0x%x", mask | never_mask);
+       }
+      else
+       sprintf (buffer, "sub\t%%0, %%0, #(%d + . -%%a1) & 0x%x",
+                inst, mask | never_mask);
+
+      output_asm_insn (buffer, operands);
+      mask <<= 8;
+      inst -= 4;
     }
+
   return "";
 }
 
@@ -2158,7 +2202,7 @@ output_lcomm_directive (stream, name, size, rounded)
     fputs ("\n\t.text\n", stream);
   else
     fputs ("\n\t.data\n", stream);
-} /* output_lcomm_directive */
+}
 \f
 /* A finite state machine takes care of noticing whether or not instructions
    can be conditionally executed, and thus decrease execution time and code
@@ -2224,7 +2268,7 @@ get_arm_condition_code (comparison)
     }
   /*NOTREACHED*/
   return (42);
-} /* get_arm_condition_code */
+}
 
 
 void
@@ -2526,6 +2570,6 @@ final_prescan_insn (insn, opvec, noperands)
         call recog direct). */
       recog (PATTERN (insn), insn, NULL_PTR);
     }
-} /* final_prescan_insn */
+}
 
 /* EOF */
This page took 0.114734 seconds and 5 git commands to generate.