• Main Page
  • Modules
  • Data Types
  • Files

osprey/kg++fe/gnu/config/arm/arm.c

Go to the documentation of this file.
00001 /* Output routines for GCC for ARM.
00002    Copyright (C) 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
00003    Free Software Foundation, Inc.
00004    Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
00005    and Martin Simmons (@harleqn.co.uk).
00006    More major hacks by Richard Earnshaw (rearnsha@arm.com).
00007 
00008 This file is part of GNU CC.
00009 
00010 GNU CC is free software; you can redistribute it and/or modify
00011 it under the terms of the GNU General Public License as published by
00012 the Free Software Foundation; either version 2, or (at your option)
00013 any later version.
00014 
00015 GNU CC is distributed in the hope that it will be useful,
00016 but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018 GNU General Public License for more details.
00019 
00020 You should have received a copy of the GNU General Public License
00021 along with GNU CC; see the file COPYING.  If not, write to
00022 the Free Software Foundation, 59 Temple Place - Suite 330,
00023 Boston, MA 02111-1307, USA.  */
00024     
00025 #include "config.h"
00026 #include "system.h"
00027 #include "rtl.h"
00028 #include "tree.h"
00029 #include "obstack.h"
00030 #include "regs.h"
00031 #include "hard-reg-set.h"
00032 #include "real.h"
00033 #include "insn-config.h"
00034 #include "conditions.h"
00035 #include "output.h"
00036 #include "insn-attr.h"
00037 #include "flags.h"
00038 #include "reload.h"
00039 #include "function.h"
00040 #include "expr.h"
00041 #include "optabs.h"
00042 #include "toplev.h"
00043 #include "recog.h"
00044 #include "ggc.h"
00045 #include "except.h"
00046 #include "c-pragma.h"
00047 #include "integrate.h"
00048 #include "tm_p.h"
00049 #include "target.h"
00050 #include "target-def.h"
00051 
00052 /* Forward definitions of types.  */
00053 typedef struct minipool_node    Mnode;
00054 typedef struct minipool_fixup   Mfix;
00055 
00056 /* In order to improve the layout of the prototypes below
00057    some short type abbreviations are defined here.  */
00058 #define Hint     HOST_WIDE_INT
00059 #define Mmode    enum machine_mode
00060 #define Ulong    unsigned long
00061 #define Ccstar   const char *
00062 
00063 const struct attribute_spec arm_attribute_table[];
00064 
00065 /* Forward function declarations.  */
00066 static void      arm_add_gc_roots     PARAMS ((void));
00067 static int       arm_gen_constant   PARAMS ((enum rtx_code, Mmode, Hint, rtx, rtx, int, int));
00068 static Ulong     bit_count      PARAMS ((signed int));
00069 static int       const_ok_for_op    PARAMS ((Hint, enum rtx_code));
00070 static int       eliminate_lr2ip    PARAMS ((rtx *));
00071 static rtx   emit_multi_reg_push    PARAMS ((int));
00072 static rtx   emit_sfm     PARAMS ((int, int));
00073 #ifndef AOF_ASSEMBLER
00074 static bool  arm_assemble_integer   PARAMS ((rtx, unsigned int, int));
00075 #endif
00076 static Ccstar    fp_const_from_val    PARAMS ((REAL_VALUE_TYPE *));
00077 static arm_cc    get_arm_condition_code   PARAMS ((rtx));
00078 static void      init_fpa_table     PARAMS ((void));
00079 static Hint      int_log2     PARAMS ((Hint));
00080 static rtx       is_jump_table      PARAMS ((rtx));
00081 static Ccstar    output_multi_immediate   PARAMS ((rtx *, Ccstar, Ccstar, int, Hint));
00082 static void      print_multi_reg    PARAMS ((FILE *, Ccstar, int, int));
00083 static Mmode     select_dominance_cc_mode PARAMS ((rtx, rtx, Hint));
00084 static Ccstar    shift_op     PARAMS ((rtx, Hint *));
00085 static void      arm_init_machine_status  PARAMS ((struct function *));
00086 static void      arm_mark_machine_status        PARAMS ((struct function *));
00087 static void      arm_free_machine_status        PARAMS ((struct function *));
00088 static int       number_of_first_bit_set        PARAMS ((int));
00089 static void      replace_symbols_in_block       PARAMS ((tree, rtx, rtx));
00090 static void      thumb_exit                     PARAMS ((FILE *, int, rtx));
00091 static void      thumb_pushpop                  PARAMS ((FILE *, int, int));
00092 static Ccstar    thumb_condition_code           PARAMS ((rtx, int));
00093 static rtx   is_jump_table            PARAMS ((rtx));
00094 static Hint  get_jump_table_size          PARAMS ((rtx));
00095 static Mnode *   move_minipool_fix_forward_ref  PARAMS ((Mnode *, Mnode *, Hint));
00096 static Mnode *   add_minipool_forward_ref PARAMS ((Mfix *));
00097 static Mnode *   move_minipool_fix_backward_ref PARAMS ((Mnode *, Mnode *, Hint));
00098 static Mnode *   add_minipool_backward_ref      PARAMS ((Mfix *));
00099 static void  assign_minipool_offsets  PARAMS ((Mfix *));
00100 static void  arm_print_value    PARAMS ((FILE *, rtx));
00101 static void  dump_minipool            PARAMS ((rtx));
00102 static int   arm_barrier_cost   PARAMS ((rtx));
00103 static Mfix *    create_fix_barrier   PARAMS ((Mfix *, Hint));
00104 static void  push_minipool_barrier          PARAMS ((rtx, Hint));
00105 static void  push_minipool_fix    PARAMS ((rtx, Hint, rtx *, Mmode, rtx));
00106 static void  note_invalid_constants         PARAMS ((rtx, Hint));
00107 static int       current_file_function_operand  PARAMS ((rtx));
00108 static Ulong   arm_compute_save_reg0_reg12_mask  PARAMS ((void));
00109 static Ulong     arm_compute_save_reg_mask  PARAMS ((void));
00110 static Ulong     arm_isr_value      PARAMS ((tree));
00111 static Ulong     arm_compute_func_type    PARAMS ((void));
00112 static tree      arm_handle_fndecl_attribute    PARAMS ((tree *, tree, tree, int, bool *));
00113 static tree      arm_handle_isr_attribute       PARAMS ((tree *, tree, tree, int, bool *));
00114 static void  arm_output_function_epilogue PARAMS ((FILE *, Hint));
00115 static void  arm_output_function_prologue PARAMS ((FILE *, Hint));
00116 static void  thumb_output_function_prologue PARAMS ((FILE *, Hint));
00117 static int   arm_comp_type_attributes PARAMS ((tree, tree));
00118 static void  arm_set_default_type_attributes  PARAMS ((tree));
00119 static int   arm_adjust_cost    PARAMS ((rtx, rtx, rtx, int));
00120 #ifdef OBJECT_FORMAT_ELF
00121 static void  arm_elf_asm_named_section  PARAMS ((const char *, unsigned int));
00122 #endif
00123 
00124 #undef Hint
00125 #undef Mmode
00126 #undef Ulong
00127 #undef Ccstar
00128 
00129 /* Initialize the GCC target structure.  */
00130 #ifdef TARGET_DLLIMPORT_DECL_ATTRIBUTES
00131 #undef  TARGET_MERGE_DECL_ATTRIBUTES
00132 #define TARGET_MERGE_DECL_ATTRIBUTES merge_dllimport_decl_attributes
00133 #endif
00134 
00135 #undef  TARGET_ATTRIBUTE_TABLE
00136 #define TARGET_ATTRIBUTE_TABLE arm_attribute_table
00137 
00138 #ifdef AOF_ASSEMBLER
00139 #undef  TARGET_ASM_BYTE_OP
00140 #define TARGET_ASM_BYTE_OP "\tDCB\t"
00141 #undef  TARGET_ASM_ALIGNED_HI_OP
00142 #define TARGET_ASM_ALIGNED_HI_OP "\tDCW\t"
00143 #undef  TARGET_ASM_ALIGNED_SI_OP
00144 #define TARGET_ASM_ALIGNED_SI_OP "\tDCD\t"
00145 #else
00146 #undef  TARGET_ASM_ALIGNED_SI_OP
00147 #define TARGET_ASM_ALIGNED_SI_OP NULL
00148 #undef  TARGET_ASM_INTEGER
00149 #define TARGET_ASM_INTEGER arm_assemble_integer
00150 #endif
00151 
00152 #undef  TARGET_ASM_FUNCTION_PROLOGUE
00153 #define TARGET_ASM_FUNCTION_PROLOGUE arm_output_function_prologue
00154 
00155 #undef  TARGET_ASM_FUNCTION_EPILOGUE
00156 #define TARGET_ASM_FUNCTION_EPILOGUE arm_output_function_epilogue
00157 
00158 #undef  TARGET_COMP_TYPE_ATTRIBUTES
00159 #define TARGET_COMP_TYPE_ATTRIBUTES arm_comp_type_attributes
00160 
00161 #undef  TARGET_SET_DEFAULT_TYPE_ATTRIBUTES
00162 #define TARGET_SET_DEFAULT_TYPE_ATTRIBUTES arm_set_default_type_attributes
00163 
00164 #undef  TARGET_INIT_BUILTINS
00165 #define TARGET_INIT_BUILTINS arm_init_builtins
00166 
00167 #undef  TARGET_EXPAND_BUILTIN
00168 #define TARGET_EXPAND_BUILTIN arm_expand_builtin
00169 
00170 #undef  TARGET_SCHED_ADJUST_COST
00171 #define TARGET_SCHED_ADJUST_COST arm_adjust_cost
00172 
00173 struct gcc_target targetm = TARGET_INITIALIZER;
00174 
00175 /* Obstack for minipool constant handling.  */
00176 static struct obstack minipool_obstack;
00177 static char *         minipool_startobj;
00178 
00179 #define obstack_chunk_alloc   xmalloc
00180 #define obstack_chunk_free    free
00181 
00182 /* The maximum number of insns skipped which
00183    will be conditionalised if possible.  */
00184 static int max_insns_skipped = 5;
00185 
00186 extern FILE * asm_out_file;
00187 
00188 /* True if we are currently building a constant table.  */
00189 int making_const_table;
00190 
00191 /* Define the information needed to generate branch insns.  This is
00192    stored from the compare operation.  */
00193 rtx arm_compare_op0, arm_compare_op1;
00194 
00195 /* What type of floating point are we tuning for?  */
00196 enum floating_point_type arm_fpu;
00197 
00198 /* What type of floating point instructions are available?  */
00199 enum floating_point_type arm_fpu_arch;
00200 
00201 /* What program mode is the cpu running in? 26-bit mode or 32-bit mode.  */
00202 enum prog_mode_type arm_prgmode;
00203 
00204 /* Set by the -mfp=... option.  */
00205 const char * target_fp_name = NULL;
00206 
00207 /* Used to parse -mstructure_size_boundary command line option.  */
00208 const char * structure_size_string = NULL;
00209 int    arm_structure_size_boundary = DEFAULT_STRUCTURE_SIZE_BOUNDARY;
00210 
00211 /* Bit values used to identify processor capabilities.  */
00212 #define FL_CO_PROC    (1 << 0)        /* Has external co-processor bus */
00213 #define FL_FAST_MULT  (1 << 1)        /* Fast multiply */
00214 #define FL_MODE26     (1 << 2)        /* 26-bit mode support */
00215 #define FL_MODE32     (1 << 3)        /* 32-bit mode support */
00216 #define FL_ARCH4      (1 << 4)        /* Architecture rel 4 */
00217 #define FL_ARCH5      (1 << 5)        /* Architecture rel 5 */
00218 #define FL_THUMB      (1 << 6)        /* Thumb aware */
00219 #define FL_LDSCHED    (1 << 7)        /* Load scheduling necessary */
00220 #define FL_STRONG     (1 << 8)        /* StrongARM */
00221 #define FL_ARCH5E     (1 << 9)        /* DSP extenstions to v5 */
00222 #define FL_XSCALE     (1 << 10)       /* XScale */
00223 
00224 /* The bits in this mask specify which
00225    instructions we are allowed to generate.  */
00226 static int insn_flags = 0;
00227 
00228 /* The bits in this mask specify which instruction scheduling options should
00229    be used.  Note - there is an overlap with the FL_FAST_MULT.  For some
00230    hardware we want to be able to generate the multiply instructions, but to
00231    tune as if they were not present in the architecture.  */
00232 static int tune_flags = 0;
00233 
00234 /* The following are used in the arm.md file as equivalents to bits
00235    in the above two flag variables.  */
00236 
00237 /* Nonzero if this is an "M" variant of the processor.  */
00238 int arm_fast_multiply = 0;
00239 
00240 /* Nonzero if this chip supports the ARM Architecture 4 extensions.  */
00241 int arm_arch4 = 0;
00242 
00243 /* Nonzero if this chip supports the ARM Architecture 5 extensions.  */
00244 int arm_arch5 = 0;
00245 
00246 /* Nonzero if this chip supports the ARM Architecture 5E extensions.  */
00247 int arm_arch5e = 0;
00248 
00249 /* Nonzero if this chip can benefit from load scheduling.  */
00250 int arm_ld_sched = 0;
00251 
00252 /* Nonzero if this chip is a StrongARM.  */
00253 int arm_is_strong = 0;
00254 
00255 /* Nonzero if this chip is an XScale.  */
00256 int arm_is_xscale = 0;
00257 
00258 /* Nonzero if this chip is an ARM6 or an ARM7.  */
00259 int arm_is_6_or_7 = 0;
00260 
00261 /* Nonzero if generating Thumb instructions.  */
00262 int thumb_code = 0;
00263 
00264 /* In case of a PRE_INC, POST_INC, PRE_DEC, POST_DEC memory reference, we
00265    must report the mode of the memory reference from PRINT_OPERAND to
00266    PRINT_OPERAND_ADDRESS.  */
00267 enum machine_mode output_memory_reference_mode;
00268 
00269 /* The register number to be used for the PIC offset register.  */
00270 const char * arm_pic_register_string = NULL;
00271 int arm_pic_register = INVALID_REGNUM;
00272 
00273 /* Set to 1 when a return insn is output, this means that the epilogue
00274    is not needed.  */
00275 int return_used_this_function;
00276 
00277 /* Set to 1 after arm_reorg has started.  Reset to start at the start of
00278    the next function.  */
00279 static int after_arm_reorg = 0;
00280 
00281 /* The maximum number of insns to be used when loading a constant.  */
00282 static int arm_constant_limit = 3;
00283 
00284 /* For an explanation of these variables, see final_prescan_insn below.  */
00285 int arm_ccfsm_state;
00286 enum arm_cond_code arm_current_cc;
00287 rtx arm_target_insn;
00288 int arm_target_label;
00289 
00290 /* The condition codes of the ARM, and the inverse function.  */
00291 static const char * const arm_condition_codes[] =
00292 {
00293   "eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc",
00294   "hi", "ls", "ge", "lt", "gt", "le", "al", "nv"
00295 };
00296 
00297 #define streq(string1, string2) (strcmp (string1, string2) == 0)
00298 
00299 /* Initialization code.  */
00300 
00301 struct processors
00302 {
00303   const char *const name;
00304   const unsigned int flags;
00305 };
00306 
00307 /* Not all of these give usefully different compilation alternatives,
00308    but there is no simple way of generalizing them.  */
00309 static const struct processors all_cores[] =
00310 {
00311   /* ARM Cores */
00312   
00313   {"arm2",  FL_CO_PROC | FL_MODE26 },
00314   {"arm250",  FL_CO_PROC | FL_MODE26 },
00315   {"arm3",  FL_CO_PROC | FL_MODE26 },
00316   {"arm6",  FL_CO_PROC | FL_MODE26 | FL_MODE32 },
00317   {"arm60", FL_CO_PROC | FL_MODE26 | FL_MODE32 },
00318   {"arm600",  FL_CO_PROC | FL_MODE26 | FL_MODE32 },
00319   {"arm610",               FL_MODE26 | FL_MODE32 },
00320   {"arm620",  FL_CO_PROC | FL_MODE26 | FL_MODE32 },
00321   {"arm7",  FL_CO_PROC | FL_MODE26 | FL_MODE32 },
00322   /* arm7m doesn't exist on its own, but only with D, (and I), but
00323      those don't alter the code, so arm7m is sometimes used.  */
00324   {"arm7m", FL_CO_PROC | FL_MODE26 | FL_MODE32 | FL_FAST_MULT },
00325   {"arm7d", FL_CO_PROC | FL_MODE26 | FL_MODE32 },
00326   {"arm7dm",  FL_CO_PROC | FL_MODE26 | FL_MODE32 | FL_FAST_MULT },
00327   {"arm7di",  FL_CO_PROC | FL_MODE26 | FL_MODE32 },
00328   {"arm7dmi", FL_CO_PROC | FL_MODE26 | FL_MODE32 | FL_FAST_MULT },
00329   {"arm70", FL_CO_PROC | FL_MODE26 | FL_MODE32 },
00330   {"arm700",  FL_CO_PROC | FL_MODE26 | FL_MODE32 },
00331   {"arm700i", FL_CO_PROC | FL_MODE26 | FL_MODE32 },
00332   {"arm710",               FL_MODE26 | FL_MODE32 },
00333   {"arm710t",              FL_MODE26 | FL_MODE32                           | FL_THUMB },
00334   {"arm720",               FL_MODE26 | FL_MODE32 },
00335   {"arm720t",              FL_MODE26 | FL_MODE32                           | FL_THUMB },
00336   {"arm740t",              FL_MODE26 | FL_MODE32                           | FL_THUMB },
00337   {"arm710c",              FL_MODE26 | FL_MODE32 },
00338   {"arm7100",              FL_MODE26 | FL_MODE32 },
00339   {"arm7500",              FL_MODE26 | FL_MODE32 },
00340   /* Doesn't have an external co-proc, but does have embedded fpu.  */
00341   {"arm7500fe", FL_CO_PROC | FL_MODE26 | FL_MODE32 },
00342   {"arm7tdmi",  FL_CO_PROC |             FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_THUMB },
00343   {"arm8",               FL_MODE26 | FL_MODE32 | FL_FAST_MULT | FL_ARCH4 |            FL_LDSCHED },
00344   {"arm810",               FL_MODE26 | FL_MODE32 | FL_FAST_MULT | FL_ARCH4 |            FL_LDSCHED },
00345   {"arm9",                           FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_THUMB | FL_LDSCHED },
00346   {"arm920",                           FL_MODE32 | FL_FAST_MULT | FL_ARCH4 |            FL_LDSCHED },
00347   {"arm920t",                          FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_THUMB | FL_LDSCHED },
00348   {"arm940t",                          FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_THUMB | FL_LDSCHED },
00349   {"arm9tdmi",                           FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_THUMB | FL_LDSCHED },
00350   {"arm9e",                    FL_MODE32 | FL_FAST_MULT | FL_ARCH4 |            FL_LDSCHED },
00351   {"strongarm",              FL_MODE26 | FL_MODE32 | FL_FAST_MULT | FL_ARCH4 |            FL_LDSCHED | FL_STRONG },
00352   {"strongarm110",           FL_MODE26 | FL_MODE32 | FL_FAST_MULT | FL_ARCH4 |            FL_LDSCHED | FL_STRONG },
00353   {"strongarm1100",          FL_MODE26 | FL_MODE32 | FL_FAST_MULT | FL_ARCH4 |            FL_LDSCHED | FL_STRONG },
00354   {"strongarm1110",          FL_MODE26 | FL_MODE32 | FL_FAST_MULT | FL_ARCH4 |            FL_LDSCHED | FL_STRONG },
00355   {"arm10tdmi",                          FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_THUMB | FL_LDSCHED             | FL_ARCH5 },
00356   {"arm1020t",                           FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_THUMB | FL_LDSCHED             | FL_ARCH5 },
00357   {"xscale",                             FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_THUMB | FL_LDSCHED | FL_STRONG | FL_ARCH5 | FL_ARCH5E | FL_XSCALE },
00358   
00359   {NULL, 0}
00360 };
00361 
00362 static const struct processors all_architectures[] =
00363 {
00364   /* ARM Architectures */
00365   
00366   { "armv2",     FL_CO_PROC | FL_MODE26 },
00367   { "armv2a",    FL_CO_PROC | FL_MODE26 },
00368   { "armv3",     FL_CO_PROC | FL_MODE26 | FL_MODE32 },
00369   { "armv3m",    FL_CO_PROC | FL_MODE26 | FL_MODE32 | FL_FAST_MULT },
00370   { "armv4",     FL_CO_PROC | FL_MODE26 | FL_MODE32 | FL_FAST_MULT | FL_ARCH4 },
00371   /* Strictly, FL_MODE26 is a permitted option for v4t, but there are no
00372      implementations that support it, so we will leave it out for now.  */
00373   { "armv4t",    FL_CO_PROC |             FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_THUMB },
00374   { "armv5",     FL_CO_PROC |             FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_THUMB | FL_ARCH5 },
00375   { "armv5t",    FL_CO_PROC |             FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_THUMB | FL_ARCH5 },
00376   { "armv5te",   FL_CO_PROC |             FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_THUMB | FL_ARCH5 | FL_ARCH5E },
00377   { NULL, 0 }
00378 };
00379 
00380 /* This is a magic stucture.  The 'string' field is magically filled in
00381    with a pointer to the value specified by the user on the command line
00382    assuming that the user has specified such a value.  */
00383 
00384 struct arm_cpu_select arm_select[] =
00385 {
00386   /* string   name            processors  */  
00387   { NULL, "-mcpu=", all_cores  },
00388   { NULL, "-march=",  all_architectures },
00389   { NULL, "-mtune=",  all_cores }
00390 };
00391 
00392 /* Return the number of bits set in value' */
00393 static unsigned long
00394 bit_count (value)
00395      signed int value;
00396 {
00397   unsigned long count = 0;
00398   
00399   while (value)
00400     {
00401       value &= ~(value & -value);
00402       ++count;
00403     }
00404 
00405   return count;
00406 }
00407 
00408 /* Fix up any incompatible options that the user has specified.
00409    This has now turned into a maze.  */
00410 void
00411 arm_override_options ()
00412 {
00413   unsigned i;
00414   
00415   /* Set up the flags based on the cpu/architecture selected by the user.  */
00416   for (i = ARRAY_SIZE (arm_select); i--;)
00417     {
00418       struct arm_cpu_select * ptr = arm_select + i;
00419       
00420       if (ptr->string != NULL && ptr->string[0] != '\0')
00421         {
00422     const struct processors * sel;
00423 
00424           for (sel = ptr->processors; sel->name != NULL; sel++)
00425             if (streq (ptr->string, sel->name))
00426               {
00427     if (i == 2)
00428       tune_flags = sel->flags;
00429     else
00430       {
00431         /* If we have been given an architecture and a processor
00432            make sure that they are compatible.  We only generate
00433            a warning though, and we prefer the CPU over the
00434            architecture.  */
00435         if (insn_flags != 0 && (insn_flags ^ sel->flags))
00436           warning ("switch -mcpu=%s conflicts with -march= switch",
00437              ptr->string);
00438         
00439         insn_flags = sel->flags;
00440       }
00441     
00442                 break;
00443               }
00444 
00445           if (sel->name == NULL)
00446             error ("bad value (%s) for %s switch", ptr->string, ptr->name);
00447         }
00448     }
00449   
00450   /* If the user did not specify a processor, choose one for them.  */
00451   if (insn_flags == 0)
00452     {
00453       const struct processors * sel;
00454       unsigned int        sought;
00455       static const struct cpu_default
00456       {
00457   const int cpu;
00458   const char *const name;
00459       }
00460       cpu_defaults[] =
00461       {
00462   { TARGET_CPU_arm2,      "arm2" },
00463   { TARGET_CPU_arm6,      "arm6" },
00464   { TARGET_CPU_arm610,    "arm610" },
00465   { TARGET_CPU_arm710,  "arm710" },
00466   { TARGET_CPU_arm7m,     "arm7m" },
00467   { TARGET_CPU_arm7500fe, "arm7500fe" },
00468   { TARGET_CPU_arm7tdmi,  "arm7tdmi" },
00469   { TARGET_CPU_arm8,      "arm8" },
00470   { TARGET_CPU_arm810,    "arm810" },
00471   { TARGET_CPU_arm9,      "arm9" },
00472   { TARGET_CPU_strongarm, "strongarm" },
00473   { TARGET_CPU_xscale,    "xscale" },
00474   { TARGET_CPU_generic,   "arm" },
00475   { 0, 0 }
00476       };
00477       const struct cpu_default * def;
00478     
00479       /* Find the default.  */
00480       for (def = cpu_defaults; def->name; def++)
00481   if (def->cpu == TARGET_CPU_DEFAULT)
00482     break;
00483 
00484       /* Make sure we found the default CPU.  */
00485       if (def->name == NULL)
00486   abort ();
00487       
00488       /* Find the default CPU's flags.  */
00489       for (sel = all_cores; sel->name != NULL; sel++)
00490   if (streq (def->name, sel->name))
00491     break;
00492       
00493       if (sel->name == NULL)
00494   abort ();
00495 
00496       insn_flags = sel->flags;
00497       
00498       /* Now check to see if the user has specified some command line
00499    switch that require certain abilities from the cpu.  */
00500       sought = 0;
00501       
00502       if (TARGET_INTERWORK || TARGET_THUMB)
00503   {
00504     sought |= (FL_THUMB | FL_MODE32);
00505     
00506     /* Force apcs-32 to be used for interworking.  */
00507     target_flags |= ARM_FLAG_APCS_32;
00508 
00509     /* There are no ARM processors that support both APCS-26 and
00510        interworking.  Therefore we force FL_MODE26 to be removed
00511        from insn_flags here (if it was set), so that the search
00512        below will always be able to find a compatible processor.  */
00513     insn_flags &= ~FL_MODE26;
00514   }
00515       else if (!TARGET_APCS_32)
00516   sought |= FL_MODE26;
00517       
00518       if (sought != 0 && ((sought & insn_flags) != sought))
00519   {
00520     /* Try to locate a CPU type that supports all of the abilities
00521        of the default CPU, plus the extra abilities requested by
00522        the user.  */
00523     for (sel = all_cores; sel->name != NULL; sel++)
00524       if ((sel->flags & sought) == (sought | insn_flags))
00525         break;
00526 
00527     if (sel->name == NULL)
00528       {
00529         unsigned int        current_bit_count = 0;
00530         const struct processors * best_fit = NULL;
00531         
00532         /* Ideally we would like to issue an error message here
00533      saying that it was not possible to find a CPU compatible
00534      with the default CPU, but which also supports the command
00535      line options specified by the programmer, and so they
00536      ought to use the -mcpu=<name> command line option to
00537      override the default CPU type.
00538 
00539      Unfortunately this does not work with multilibing.  We
00540      need to be able to support multilibs for -mapcs-26 and for
00541      -mthumb-interwork and there is no CPU that can support both
00542      options.  Instead if we cannot find a cpu that has both the
00543      characteristics of the default cpu and the given command line
00544      options we scan the array again looking for a best match.  */
00545         for (sel = all_cores; sel->name != NULL; sel++)
00546     if ((sel->flags & sought) == sought)
00547       {
00548         unsigned int count;
00549 
00550         count = bit_count (sel->flags & insn_flags);
00551 
00552         if (count >= current_bit_count)
00553           {
00554       best_fit = sel;
00555       current_bit_count = count;
00556           }
00557       }
00558 
00559         if (best_fit == NULL)
00560     abort ();
00561         else
00562     sel = best_fit;
00563       }
00564 
00565     insn_flags = sel->flags;
00566   }
00567     }
00568   
00569   /* If tuning has not been specified, tune for whichever processor or
00570      architecture has been selected.  */
00571   if (tune_flags == 0)
00572     tune_flags = insn_flags;
00573   
00574   /* Make sure that the processor choice does not conflict with any of the
00575      other command line choices.  */
00576   if (TARGET_APCS_32 && !(insn_flags & FL_MODE32))
00577     {
00578       /* If APCS-32 was not the default then it must have been set by the
00579    user, so issue a warning message.  If the user has specified
00580    "-mapcs-32 -mcpu=arm2" then we loose here.  */
00581       if ((TARGET_DEFAULT & ARM_FLAG_APCS_32) == 0)
00582   warning ("target CPU does not support APCS-32" );
00583       target_flags &= ~ARM_FLAG_APCS_32;
00584     }
00585   else if (!TARGET_APCS_32 && !(insn_flags & FL_MODE26))
00586     {
00587       warning ("target CPU does not support APCS-26" );
00588       target_flags |= ARM_FLAG_APCS_32;
00589     }
00590   
00591   if (TARGET_INTERWORK && !(insn_flags & FL_THUMB))
00592     {
00593       warning ("target CPU does not support interworking" );
00594       target_flags &= ~ARM_FLAG_INTERWORK;
00595     }
00596   
00597   if (TARGET_THUMB && !(insn_flags & FL_THUMB))
00598     {
00599       warning ("target CPU does not support THUMB instructions");
00600       target_flags &= ~ARM_FLAG_THUMB;
00601     }
00602 
00603   if (TARGET_APCS_FRAME && TARGET_THUMB)
00604     {
00605       /* warning ("ignoring -mapcs-frame because -mthumb was used"); */
00606       target_flags &= ~ARM_FLAG_APCS_FRAME;
00607     }
00608 
00609   /* TARGET_BACKTRACE calls leaf_function_p, which causes a crash if done
00610      from here where no function is being compiled currently.  */
00611   if ((target_flags & (THUMB_FLAG_LEAF_BACKTRACE | THUMB_FLAG_BACKTRACE))
00612       && TARGET_ARM)
00613     warning ("enabling backtrace support is only meaningful when compiling for the Thumb");
00614 
00615   if (TARGET_ARM && TARGET_CALLEE_INTERWORKING)
00616     warning ("enabling callee interworking support is only meaningful when compiling for the Thumb");
00617 
00618   if (TARGET_ARM && TARGET_CALLER_INTERWORKING)
00619     warning ("enabling caller interworking support is only meaningful when compiling for the Thumb");
00620 
00621   /* If interworking is enabled then APCS-32 must be selected as well.  */
00622   if (TARGET_INTERWORK)
00623     {
00624       if (!TARGET_APCS_32)
00625   warning ("interworking forces APCS-32 to be used" );
00626       target_flags |= ARM_FLAG_APCS_32;
00627     }
00628   
00629   if (TARGET_APCS_STACK && !TARGET_APCS_FRAME)
00630     {
00631       warning ("-mapcs-stack-check incompatible with -mno-apcs-frame");
00632       target_flags |= ARM_FLAG_APCS_FRAME;
00633     }
00634   
00635   if (TARGET_POKE_FUNCTION_NAME)
00636     target_flags |= ARM_FLAG_APCS_FRAME;
00637   
00638   if (TARGET_APCS_REENT && flag_pic)
00639     error ("-fpic and -mapcs-reent are incompatible");
00640   
00641   if (TARGET_APCS_REENT)
00642     warning ("APCS reentrant code not supported.  Ignored");
00643   
00644   /* If this target is normally configured to use APCS frames, warn if they
00645      are turned off and debugging is turned on.  */
00646   if (TARGET_ARM
00647       && write_symbols != NO_DEBUG
00648       && !TARGET_APCS_FRAME
00649       && (TARGET_DEFAULT & ARM_FLAG_APCS_FRAME))
00650     warning ("-g with -mno-apcs-frame may not give sensible debugging");
00651   
00652   /* If stack checking is disabled, we can use r10 as the PIC register,
00653      which keeps r9 available.  */
00654   if (flag_pic)
00655     arm_pic_register = TARGET_APCS_STACK ? 9 : 10;
00656   
00657   if (TARGET_APCS_FLOAT)
00658     warning ("passing floating point arguments in fp regs not yet supported");
00659   
00660   /* Initialise boolean versions of the flags, for use in the arm.md file.  */
00661   arm_fast_multiply = (insn_flags & FL_FAST_MULT) != 0;
00662   arm_arch4         = (insn_flags & FL_ARCH4) != 0;
00663   arm_arch5         = (insn_flags & FL_ARCH5) != 0;
00664   arm_arch5e        = (insn_flags & FL_ARCH5E) != 0;
00665   arm_is_xscale     = (insn_flags & FL_XSCALE) != 0;
00666 
00667   arm_ld_sched      = (tune_flags & FL_LDSCHED) != 0;
00668   arm_is_strong     = (tune_flags & FL_STRONG) != 0;
00669   thumb_code      = (TARGET_ARM == 0);
00670   arm_is_6_or_7     = (((tune_flags & (FL_MODE26 | FL_MODE32))
00671            && !(tune_flags & FL_ARCH4))) != 0;
00672 
00673   /* Default value for floating point code... if no co-processor
00674      bus, then schedule for emulated floating point.  Otherwise,
00675      assume the user has an FPA.
00676      Note: this does not prevent use of floating point instructions,
00677      -msoft-float does that.  */
00678   arm_fpu = (tune_flags & FL_CO_PROC) ? FP_HARD : FP_SOFT3;
00679   
00680   if (target_fp_name)
00681     {
00682       if (streq (target_fp_name, "2"))
00683   arm_fpu_arch = FP_SOFT2;
00684       else if (streq (target_fp_name, "3"))
00685   arm_fpu_arch = FP_SOFT3;
00686       else
00687   error ("invalid floating point emulation option: -mfpe-%s",
00688          target_fp_name);
00689     }
00690   else
00691     arm_fpu_arch = FP_DEFAULT;
00692   
00693   if (TARGET_FPE && arm_fpu != FP_HARD)
00694     arm_fpu = FP_SOFT2;
00695   
00696   /* For arm2/3 there is no need to do any scheduling if there is only
00697      a floating point emulator, or we are doing software floating-point.  */
00698   if ((TARGET_SOFT_FLOAT || arm_fpu != FP_HARD)
00699       && (tune_flags & FL_MODE32) == 0)
00700     flag_schedule_insns = flag_schedule_insns_after_reload = 0;
00701   
00702   arm_prgmode = TARGET_APCS_32 ? PROG_MODE_PROG32 : PROG_MODE_PROG26;
00703   
00704   if (structure_size_string != NULL)
00705     {
00706       int size = strtol (structure_size_string, NULL, 0);
00707       
00708       if (size == 8 || size == 32)
00709   arm_structure_size_boundary = size;
00710       else
00711   warning ("structure size boundary can only be set to 8 or 32");
00712     }
00713 
00714   if (arm_pic_register_string != NULL)
00715     {
00716       int pic_register = decode_reg_name (arm_pic_register_string);
00717       
00718       if (!flag_pic)
00719   warning ("-mpic-register= is useless without -fpic");
00720 
00721       /* Prevent the user from choosing an obviously stupid PIC register.  */
00722       else if (pic_register < 0 || call_used_regs[pic_register]
00723          || pic_register == HARD_FRAME_POINTER_REGNUM
00724          || pic_register == STACK_POINTER_REGNUM
00725          || pic_register >= PC_REGNUM)
00726   error ("unable to use '%s' for PIC register", arm_pic_register_string);
00727       else
00728   arm_pic_register = pic_register;
00729     }
00730 
00731   if (TARGET_THUMB && flag_schedule_insns)
00732     {
00733       /* Don't warn since it's on by default in -O2.  */
00734       flag_schedule_insns = 0;
00735     }
00736 
00737   /* If optimizing for space, don't synthesize constants.
00738      For processors with load scheduling, it never costs more than 2 cycles
00739      to load a constant, and the load scheduler may well reduce that to 1.  */
00740   if (optimize_size || (tune_flags & FL_LDSCHED))
00741     arm_constant_limit = 1;
00742   
00743   if (arm_is_xscale)
00744     arm_constant_limit = 2;
00745 
00746   /* If optimizing for size, bump the number of instructions that we
00747      are prepared to conditionally execute (even on a StrongARM). 
00748      Otherwise for the StrongARM, which has early execution of branches,
00749      a sequence that is worth skipping is shorter.  */
00750   if (optimize_size)
00751     max_insns_skipped = 6;
00752   else if (arm_is_strong)
00753     max_insns_skipped = 3;
00754 
00755   /* Register global variables with the garbage collector.  */
00756   arm_add_gc_roots ();
00757 }
00758 
00759 static void
00760 arm_add_gc_roots ()
00761 {
00762   ggc_add_rtx_root (&arm_compare_op0, 1);
00763   ggc_add_rtx_root (&arm_compare_op1, 1);
00764   ggc_add_rtx_root (&arm_target_insn, 1); /* Not sure this is really a root.  */
00765 
00766   gcc_obstack_init(&minipool_obstack);
00767   minipool_startobj = (char *) obstack_alloc (&minipool_obstack, 0);
00768 }
00769 
00770 /* A table of known ARM exception types.
00771    For use with the interrupt function attribute.  */
00772 
00773 typedef struct
00774 {
00775   const char *const arg;
00776   const unsigned long return_value;
00777 }
00778 isr_attribute_arg;
00779 
00780 static const isr_attribute_arg isr_attribute_args [] =
00781 {
00782   { "IRQ",   ARM_FT_ISR },
00783   { "irq",   ARM_FT_ISR },
00784   { "FIQ",   ARM_FT_FIQ },
00785   { "fiq",   ARM_FT_FIQ },
00786   { "ABORT", ARM_FT_ISR },
00787   { "abort", ARM_FT_ISR },
00788   { "ABORT", ARM_FT_ISR },
00789   { "abort", ARM_FT_ISR },
00790   { "UNDEF", ARM_FT_EXCEPTION },
00791   { "undef", ARM_FT_EXCEPTION },
00792   { "SWI",   ARM_FT_EXCEPTION },
00793   { "swi",   ARM_FT_EXCEPTION },
00794   { NULL,    ARM_FT_NORMAL }
00795 };
00796 
00797 /* Returns the (interrupt) function type of the current
00798    function, or ARM_FT_UNKNOWN if the type cannot be determined.  */
00799 
00800 static unsigned long
00801 arm_isr_value (argument)
00802      tree argument;
00803 {
00804   const isr_attribute_arg * ptr;
00805   const char *              arg;
00806 
00807   /* No argument - default to IRQ.  */
00808   if (argument == NULL_TREE)
00809     return ARM_FT_ISR;
00810 
00811   /* Get the value of the argument.  */
00812   if (TREE_VALUE (argument) == NULL_TREE
00813       || TREE_CODE (TREE_VALUE (argument)) != STRING_CST)
00814     return ARM_FT_UNKNOWN;
00815 
00816   arg = TREE_STRING_POINTER (TREE_VALUE (argument));
00817 
00818   /* Check it against the list of known arguments.  */
00819   for (ptr = isr_attribute_args; ptr->arg != NULL; ptr ++)
00820     if (streq (arg, ptr->arg))
00821       return ptr->return_value;
00822 
00823   /* An unrecognised interrupt type.  */
00824   return ARM_FT_UNKNOWN;
00825 }
00826 
00827 /* Computes the type of the current function.  */
00828 
00829 static unsigned long
00830 arm_compute_func_type ()
00831 {
00832   unsigned long type = ARM_FT_UNKNOWN;
00833   tree a;
00834   tree attr;
00835   
00836   if (TREE_CODE (current_function_decl) != FUNCTION_DECL)
00837     abort ();
00838 
00839   /* Decide if the current function is volatile.  Such functions
00840      never return, and many memory cycles can be saved by not storing
00841      register values that will never be needed again.  This optimization
00842      was added to speed up context switching in a kernel application.  */
00843   if (optimize > 0
00844       && current_function_nothrow
00845       && TREE_THIS_VOLATILE (current_function_decl))
00846     type |= ARM_FT_VOLATILE;
00847   
00848   if (current_function_needs_context)
00849     type |= ARM_FT_NESTED;
00850 
00851   attr = DECL_ATTRIBUTES (current_function_decl);
00852   
00853   a = lookup_attribute ("naked", attr);
00854   if (a != NULL_TREE)
00855     type |= ARM_FT_NAKED;
00856 
00857   if (cfun->machine->eh_epilogue_sp_ofs != NULL_RTX)
00858     type |= ARM_FT_EXCEPTION_HANDLER;
00859   else
00860     {
00861       a = lookup_attribute ("isr", attr);
00862       if (a == NULL_TREE)
00863   a = lookup_attribute ("interrupt", attr);
00864       
00865       if (a == NULL_TREE)
00866   type |= TARGET_INTERWORK ? ARM_FT_INTERWORKED : ARM_FT_NORMAL;
00867       else
00868   type |= arm_isr_value (TREE_VALUE (a));
00869     }
00870   
00871   return type;
00872 }
00873 
00874 /* Returns the type of the current function.  */
00875 
00876 unsigned long
00877 arm_current_func_type ()
00878 {
00879   if (ARM_FUNC_TYPE (cfun->machine->func_type) == ARM_FT_UNKNOWN)
00880     cfun->machine->func_type = arm_compute_func_type ();
00881 
00882   return cfun->machine->func_type;
00883 }
00884 
00885 /* Return 1 if it is possible to return using a single instruction.  */
00886 
00887 int
00888 use_return_insn (iscond)
00889      int iscond;
00890 {
00891   int regno;
00892   unsigned int func_type;
00893   unsigned long saved_int_regs;
00894 
00895   /* Never use a return instruction before reload has run.  */
00896   if (!reload_completed)
00897     return 0;
00898       
00899   func_type = arm_current_func_type ();
00900 
00901   /* Naked functions and volatile functions need special
00902      consideration.  */
00903   if (func_type & (ARM_FT_VOLATILE | ARM_FT_NAKED))
00904     return 0;
00905   
00906   /* As do variadic functions.  */
00907   if (current_function_pretend_args_size
00908       || cfun->machine->uses_anonymous_args
00909       /* Of if the function calls __builtin_eh_return () */
00910       || ARM_FUNC_TYPE (func_type) == ARM_FT_EXCEPTION_HANDLER
00911       /* Or if there is no frame pointer and there is a stack adjustment.  */
00912       || ((get_frame_size () + current_function_outgoing_args_size != 0)
00913     && !frame_pointer_needed))
00914     return 0;
00915 
00916   saved_int_regs = arm_compute_save_reg_mask ();
00917 
00918   /* Can't be done if interworking with Thumb, and any registers have been
00919      stacked.  */
00920   if (TARGET_INTERWORK && saved_int_regs != 0)
00921     return 0;
00922 
00923   /* On StrongARM, conditional returns are expensive if they aren't
00924      taken and multiple registers have been stacked.  */
00925   if (iscond && arm_is_strong)
00926     {
00927       /* Conditional return when just the LR is stored is a simple 
00928    conditional-load instruction, that's not expensive.  */
00929       if (saved_int_regs != 0 && saved_int_regs != (1 << LR_REGNUM))
00930   return 0;
00931 
00932       if (flag_pic && regs_ever_live[PIC_OFFSET_TABLE_REGNUM])
00933   return 0;
00934     }
00935 
00936   /* If there are saved registers but the LR isn't saved, then we need
00937      two instructions for the return.  */
00938   if (saved_int_regs && !(saved_int_regs & (1 << LR_REGNUM)))
00939     return 0;
00940 
00941   /* Can't be done if any of the FPU regs are pushed,
00942      since this also requires an insn.  */
00943   if (TARGET_HARD_FLOAT)
00944     for (regno = FIRST_ARM_FP_REGNUM; regno <= LAST_ARM_FP_REGNUM; regno++)
00945       if (regs_ever_live[regno] && !call_used_regs[regno])
00946   return 0;
00947 
00948   return 1;
00949 }
00950 
00951 /* Return TRUE if int I is a valid immediate ARM constant.  */
00952 
00953 int
00954 const_ok_for_arm (i)
00955      HOST_WIDE_INT i;
00956 {
00957   unsigned HOST_WIDE_INT mask = ~(unsigned HOST_WIDE_INT)0xFF;
00958 
00959   /* For machines with >32 bit HOST_WIDE_INT, the bits above bit 31 must 
00960      be all zero, or all one.  */
00961   if ((i & ~(unsigned HOST_WIDE_INT) 0xffffffff) != 0
00962       && ((i & ~(unsigned HOST_WIDE_INT) 0xffffffff)
00963     != ((~(unsigned HOST_WIDE_INT) 0)
00964         & ~(unsigned HOST_WIDE_INT) 0xffffffff)))
00965     return FALSE;
00966   
00967   /* Fast return for 0 and powers of 2 */
00968   if ((i & (i - 1)) == 0)
00969     return TRUE;
00970 
00971   do
00972     {
00973       if ((i & mask & (unsigned HOST_WIDE_INT) 0xffffffff) == 0)
00974         return TRUE;
00975       mask =
00976     (mask << 2) | ((mask & (unsigned HOST_WIDE_INT) 0xffffffff)
00977         >> (32 - 2)) | ~(unsigned HOST_WIDE_INT) 0xffffffff;
00978     }
00979   while (mask != ~(unsigned HOST_WIDE_INT) 0xFF);
00980 
00981   return FALSE;
00982 }
00983 
00984 /* Return true if I is a valid constant for the operation CODE.  */
00985 static int
00986 const_ok_for_op (i, code)
00987      HOST_WIDE_INT i;
00988      enum rtx_code code;
00989 {
00990   if (const_ok_for_arm (i))
00991     return 1;
00992 
00993   switch (code)
00994     {
00995     case PLUS:
00996       return const_ok_for_arm (ARM_SIGN_EXTEND (-i));
00997 
00998     case MINUS:   /* Should only occur with (MINUS I reg) => rsb */
00999     case XOR:
01000     case IOR:
01001       return 0;
01002 
01003     case AND:
01004       return const_ok_for_arm (ARM_SIGN_EXTEND (~i));
01005 
01006     default:
01007       abort ();
01008     }
01009 }
01010 
01011 /* Emit a sequence of insns to handle a large constant.
01012    CODE is the code of the operation required, it can be any of SET, PLUS,
01013    IOR, AND, XOR, MINUS;
01014    MODE is the mode in which the operation is being performed;
01015    VAL is the integer to operate on;
01016    SOURCE is the other operand (a register, or a null-pointer for SET);
01017    SUBTARGETS means it is safe to create scratch registers if that will
01018    either produce a simpler sequence, or we will want to cse the values.
01019    Return value is the number of insns emitted.  */
01020 
01021 int
01022 arm_split_constant (code, mode, val, target, source, subtargets)
01023      enum rtx_code code;
01024      enum machine_mode mode;
01025      HOST_WIDE_INT val;
01026      rtx target;
01027      rtx source;
01028      int subtargets;
01029 {
01030   if (subtargets || code == SET
01031       || (GET_CODE (target) == REG && GET_CODE (source) == REG
01032     && REGNO (target) != REGNO (source)))
01033     {
01034       /* After arm_reorg has been called, we can't fix up expensive
01035    constants by pushing them into memory so we must synthesise
01036    them in-line, regardless of the cost.  This is only likely to
01037    be more costly on chips that have load delay slots and we are
01038    compiling without running the scheduler (so no splitting
01039    occurred before the final instruction emission).
01040 
01041    Ref: gcc -O1 -mcpu=strongarm gcc.c-torture/compile/980506-2.c
01042       */
01043       if (!after_arm_reorg
01044     && (arm_gen_constant (code, mode, val, target, source, 1, 0)
01045         > arm_constant_limit + (code != SET)))
01046   {
01047     if (code == SET)
01048       {
01049         /* Currently SET is the only monadic value for CODE, all
01050      the rest are diadic.  */
01051         emit_insn (gen_rtx_SET (VOIDmode, target, GEN_INT (val)));
01052         return 1;
01053       }
01054     else
01055       {
01056         rtx temp = subtargets ? gen_reg_rtx (mode) : target;
01057 
01058         emit_insn (gen_rtx_SET (VOIDmode, temp, GEN_INT (val)));
01059         /* For MINUS, the value is subtracted from, since we never
01060      have subtraction of a constant.  */
01061         if (code == MINUS)
01062     emit_insn (gen_rtx_SET (VOIDmode, target,
01063           gen_rtx_MINUS (mode, temp, source)));
01064         else
01065     emit_insn (gen_rtx_SET (VOIDmode, target,
01066           gen_rtx (code, mode, source, temp)));
01067         return 2;
01068       }
01069   }
01070     }
01071 
01072   return arm_gen_constant (code, mode, val, target, source, subtargets, 1);
01073 }
01074 
01075 static int
01076 count_insns_for_constant (HOST_WIDE_INT remainder, int i)
01077 {
01078   HOST_WIDE_INT temp1;
01079   int num_insns = 0;
01080   do
01081     {
01082       int end;
01083     
01084       if (i <= 0)
01085   i += 32;
01086       if (remainder & (3 << (i - 2)))
01087   {
01088     end = i - 8;
01089     if (end < 0)
01090       end += 32;
01091     temp1 = remainder & ((0x0ff << end)
01092             | ((i < end) ? (0xff >> (32 - end)) : 0));
01093     remainder &= ~temp1;
01094     num_insns++;
01095     i -= 6;
01096   }
01097       i -= 2;
01098     } while (remainder);
01099   return num_insns;
01100 }
01101 
01102 /* As above, but extra parameter GENERATE which, if clear, suppresses
01103    RTL generation.  */
01104 
01105 static int
01106 arm_gen_constant (code, mode, val, target, source, subtargets, generate)
01107      enum rtx_code code;
01108      enum machine_mode mode;
01109      HOST_WIDE_INT val;
01110      rtx target;
01111      rtx source;
01112      int subtargets;
01113      int generate;
01114 {
01115   int can_invert = 0;
01116   int can_negate = 0;
01117   int can_negate_initial = 0;
01118   int can_shift = 0;
01119   int i;
01120   int num_bits_set = 0;
01121   int set_sign_bit_copies = 0;
01122   int clear_sign_bit_copies = 0;
01123   int clear_zero_bit_copies = 0;
01124   int set_zero_bit_copies = 0;
01125   int insns = 0;
01126   unsigned HOST_WIDE_INT temp1, temp2;
01127   unsigned HOST_WIDE_INT remainder = val & 0xffffffff;
01128 
01129   /* Find out which operations are safe for a given CODE.  Also do a quick
01130      check for degenerate cases; these can occur when DImode operations
01131      are split.  */
01132   switch (code)
01133     {
01134     case SET:
01135       can_invert = 1;
01136       can_shift = 1;
01137       can_negate = 1;
01138       break;
01139 
01140     case PLUS:
01141       can_negate = 1;
01142       can_negate_initial = 1;
01143       break;
01144 
01145     case IOR:
01146       if (remainder == 0xffffffff)
01147   {
01148     if (generate)
01149       emit_insn (gen_rtx_SET (VOIDmode, target,
01150             GEN_INT (ARM_SIGN_EXTEND (val))));
01151     return 1;
01152   }
01153       if (remainder == 0)
01154   {
01155     if (reload_completed && rtx_equal_p (target, source))
01156       return 0;
01157     if (generate)
01158       emit_insn (gen_rtx_SET (VOIDmode, target, source));
01159     return 1;
01160   }
01161       break;
01162 
01163     case AND:
01164       if (remainder == 0)
01165   {
01166     if (generate)
01167       emit_insn (gen_rtx_SET (VOIDmode, target, const0_rtx));
01168     return 1;
01169   }
01170       if (remainder == 0xffffffff)
01171   {
01172     if (reload_completed && rtx_equal_p (target, source))
01173       return 0;
01174     if (generate)
01175       emit_insn (gen_rtx_SET (VOIDmode, target, source));
01176     return 1;
01177   }
01178       can_invert = 1;
01179       break;
01180 
01181     case XOR:
01182       if (remainder == 0)
01183   {
01184     if (reload_completed && rtx_equal_p (target, source))
01185       return 0;
01186     if (generate)
01187       emit_insn (gen_rtx_SET (VOIDmode, target, source));
01188     return 1;
01189   }
01190       if (remainder == 0xffffffff)
01191   {
01192     if (generate)
01193       emit_insn (gen_rtx_SET (VOIDmode, target,
01194             gen_rtx_NOT (mode, source)));
01195     return 1;
01196   }
01197 
01198       /* We don't know how to handle this yet below.  */
01199       abort ();
01200 
01201     case MINUS:
01202       /* We treat MINUS as (val - source), since (source - val) is always
01203    passed as (source + (-val)).  */
01204       if (remainder == 0)
01205   {
01206     if (generate)
01207       emit_insn (gen_rtx_SET (VOIDmode, target,
01208             gen_rtx_NEG (mode, source)));
01209     return 1;
01210   }
01211       if (const_ok_for_arm (val))
01212   {
01213     if (generate)
01214       emit_insn (gen_rtx_SET (VOIDmode, target, 
01215             gen_rtx_MINUS (mode, GEN_INT (val),
01216                source)));
01217     return 1;
01218   }
01219       can_negate = 1;
01220 
01221       break;
01222 
01223     default:
01224       abort ();
01225     }
01226 
01227   /* If we can do it in one insn get out quickly.  */
01228   if (const_ok_for_arm (val)
01229       || (can_negate_initial && const_ok_for_arm (-val))
01230       || (can_invert && const_ok_for_arm (~val)))
01231     {
01232       if (generate)
01233   emit_insn (gen_rtx_SET (VOIDmode, target,
01234         (source ? gen_rtx (code, mode, source,
01235                GEN_INT (val))
01236          : GEN_INT (val))));
01237       return 1;
01238     }
01239 
01240   /* Calculate a few attributes that may be useful for specific
01241      optimizations.  */
01242   for (i = 31; i >= 0; i--)
01243     {
01244       if ((remainder & (1 << i)) == 0)
01245   clear_sign_bit_copies++;
01246       else
01247   break;
01248     }
01249 
01250   for (i = 31; i >= 0; i--)
01251     {
01252       if ((remainder & (1 << i)) != 0)
01253   set_sign_bit_copies++;
01254       else
01255   break;
01256     }
01257 
01258   for (i = 0; i <= 31; i++)
01259     {
01260       if ((remainder & (1 << i)) == 0)
01261   clear_zero_bit_copies++;
01262       else
01263   break;
01264     }
01265 
01266   for (i = 0; i <= 31; i++)
01267     {
01268       if ((remainder & (1 << i)) != 0)
01269   set_zero_bit_copies++;
01270       else
01271   break;
01272     }
01273 
01274   switch (code)
01275     {
01276     case SET:
01277       /* See if we can do this by sign_extending a constant that is known
01278    to be negative.  This is a good, way of doing it, since the shift
01279    may well merge into a subsequent insn.  */
01280       if (set_sign_bit_copies > 1)
01281   {
01282     if (const_ok_for_arm
01283         (temp1 = ARM_SIGN_EXTEND (remainder 
01284           << (set_sign_bit_copies - 1))))
01285       {
01286         if (generate)
01287     {
01288       rtx new_src = subtargets ? gen_reg_rtx (mode) : target;
01289       emit_insn (gen_rtx_SET (VOIDmode, new_src, 
01290             GEN_INT (temp1)));
01291       emit_insn (gen_ashrsi3 (target, new_src, 
01292             GEN_INT (set_sign_bit_copies - 1)));
01293     }
01294         return 2;
01295       }
01296     /* For an inverted constant, we will need to set the low bits,
01297        these will be shifted out of harm's way.  */
01298     temp1 |= (1 << (set_sign_bit_copies - 1)) - 1;
01299     if (const_ok_for_arm (~temp1))
01300       {
01301         if (generate)
01302     {
01303       rtx new_src = subtargets ? gen_reg_rtx (mode) : target;
01304       emit_insn (gen_rtx_SET (VOIDmode, new_src,
01305             GEN_INT (temp1)));
01306       emit_insn (gen_ashrsi3 (target, new_src, 
01307             GEN_INT (set_sign_bit_copies - 1)));
01308     }
01309         return 2;
01310       }
01311   }
01312 
01313       /* See if we can generate this by setting the bottom (or the top)
01314    16 bits, and then shifting these into the other half of the
01315    word.  We only look for the simplest cases, to do more would cost
01316    too much.  Be careful, however, not to generate this when the
01317    alternative would take fewer insns.  */
01318       if (val & 0xffff0000)
01319   {
01320     temp1 = remainder & 0xffff0000;
01321     temp2 = remainder & 0x0000ffff;
01322 
01323     /* Overlaps outside this range are best done using other methods.  */
01324     for (i = 9; i < 24; i++)
01325       {
01326         if ((((temp2 | (temp2 << i)) & 0xffffffff) == remainder)
01327       && !const_ok_for_arm (temp2))
01328     {
01329       rtx new_src = (subtargets
01330          ? (generate ? gen_reg_rtx (mode) : NULL_RTX)
01331          : target);
01332       insns = arm_gen_constant (code, mode, temp2, new_src,
01333               source, subtargets, generate);
01334       source = new_src;
01335       if (generate)
01336         emit_insn (gen_rtx_SET
01337              (VOIDmode, target,
01338         gen_rtx_IOR (mode,
01339                gen_rtx_ASHIFT (mode, source,
01340                    GEN_INT (i)),
01341                source)));
01342       return insns + 1;
01343     }
01344       }
01345 
01346     /* Don't duplicate cases already considered.  */
01347     for (i = 17; i < 24; i++)
01348       {
01349         if (((temp1 | (temp1 >> i)) == remainder)
01350       && !const_ok_for_arm (temp1))
01351     {
01352       rtx new_src = (subtargets
01353          ? (generate ? gen_reg_rtx (mode) : NULL_RTX)
01354          : target);
01355       insns = arm_gen_constant (code, mode, temp1, new_src,
01356               source, subtargets, generate);
01357       source = new_src;
01358       if (generate)
01359         emit_insn
01360           (gen_rtx_SET (VOIDmode, target,
01361             gen_rtx_IOR
01362             (mode,
01363              gen_rtx_LSHIFTRT (mode, source,
01364                    GEN_INT (i)),
01365              source)));
01366       return insns + 1;
01367     }
01368       }
01369   }
01370       break;
01371 
01372     case IOR:
01373     case XOR:
01374       /* If we have IOR or XOR, and the constant can be loaded in a
01375    single instruction, and we can find a temporary to put it in,
01376    then this can be done in two instructions instead of 3-4.  */
01377       if (subtargets
01378     /* TARGET can't be NULL if SUBTARGETS is 0 */
01379     || (reload_completed && !reg_mentioned_p (target, source)))
01380   {
01381     if (const_ok_for_arm (ARM_SIGN_EXTEND (~val)))
01382       {
01383         if (generate)
01384     {
01385       rtx sub = subtargets ? gen_reg_rtx (mode) : target;
01386 
01387       emit_insn (gen_rtx_SET (VOIDmode, sub, GEN_INT (val)));
01388       emit_insn (gen_rtx_SET (VOIDmode, target, 
01389             gen_rtx (code, mode, source, sub)));
01390     }
01391         return 2;
01392       }
01393   }
01394 
01395       if (code == XOR)
01396   break;
01397 
01398       if (set_sign_bit_copies > 8
01399     && (val & (-1 << (32 - set_sign_bit_copies))) == val)
01400   {
01401     if (generate)
01402       {
01403         rtx sub = subtargets ? gen_reg_rtx (mode) : target;
01404         rtx shift = GEN_INT (set_sign_bit_copies);
01405 
01406         emit_insn (gen_rtx_SET (VOIDmode, sub,
01407               gen_rtx_NOT (mode, 
01408                gen_rtx_ASHIFT (mode,
01409                    source, 
01410                    shift))));
01411         emit_insn (gen_rtx_SET (VOIDmode, target,
01412               gen_rtx_NOT (mode,
01413                gen_rtx_LSHIFTRT (mode, sub,
01414                      shift))));
01415       }
01416     return 2;
01417   }
01418 
01419       if (set_zero_bit_copies > 8
01420     && (remainder & ((1 << set_zero_bit_copies) - 1)) == remainder)
01421   {
01422     if (generate)
01423       {
01424         rtx sub = subtargets ? gen_reg_rtx (mode) : target;
01425         rtx shift = GEN_INT (set_zero_bit_copies);
01426 
01427         emit_insn (gen_rtx_SET (VOIDmode, sub,
01428               gen_rtx_NOT (mode,
01429                gen_rtx_LSHIFTRT (mode,
01430                      source,
01431                      shift))));
01432         emit_insn (gen_rtx_SET (VOIDmode, target,
01433               gen_rtx_NOT (mode,
01434                gen_rtx_ASHIFT (mode, sub,
01435                    shift))));
01436       }
01437     return 2;
01438   }
01439 
01440       if (const_ok_for_arm (temp1 = ARM_SIGN_EXTEND (~val)))
01441   {
01442     if (generate)
01443       {
01444         rtx sub = subtargets ? gen_reg_rtx (mode) : target;
01445         emit_insn (gen_rtx_SET (VOIDmode, sub,
01446               gen_rtx_NOT (mode, source)));
01447         source = sub;
01448         if (subtargets)
01449     sub = gen_reg_rtx (mode);
01450         emit_insn (gen_rtx_SET (VOIDmode, sub,
01451               gen_rtx_AND (mode, source, 
01452                GEN_INT (temp1))));
01453         emit_insn (gen_rtx_SET (VOIDmode, target,
01454               gen_rtx_NOT (mode, sub)));
01455       }
01456     return 3;
01457   }
01458       break;
01459 
01460     case AND:
01461       /* See if two shifts will do 2 or more insn's worth of work.  */
01462       if (clear_sign_bit_copies >= 16 && clear_sign_bit_copies < 24)
01463   {
01464     HOST_WIDE_INT shift_mask = ((0xffffffff
01465                << (32 - clear_sign_bit_copies))
01466               & 0xffffffff);
01467 
01468     if ((remainder | shift_mask) != 0xffffffff)
01469       {
01470         if (generate)
01471     {
01472       rtx new_src = subtargets ? gen_reg_rtx (mode) : target;
01473       insns = arm_gen_constant (AND, mode, remainder | shift_mask,
01474               new_src, source, subtargets, 1);
01475       source = new_src;
01476     }
01477         else
01478     {
01479       rtx targ = subtargets ? NULL_RTX : target;
01480       insns = arm_gen_constant (AND, mode, remainder | shift_mask,
01481               targ, source, subtargets, 0);
01482     }
01483       }
01484 
01485     if (generate)
01486       {
01487         rtx new_src = subtargets ? gen_reg_rtx (mode) : target;
01488         rtx shift = GEN_INT (clear_sign_bit_copies);
01489 
01490         emit_insn (gen_ashlsi3 (new_src, source, shift));
01491         emit_insn (gen_lshrsi3 (target, new_src, shift));
01492       }
01493 
01494     return insns + 2;
01495   }
01496 
01497       if (clear_zero_bit_copies >= 16 && clear_zero_bit_copies < 24)
01498   {
01499     HOST_WIDE_INT shift_mask = (1 << clear_zero_bit_copies) - 1;
01500     
01501     if ((remainder | shift_mask) != 0xffffffff)
01502       {
01503         if (generate)
01504     {
01505       rtx new_src = subtargets ? gen_reg_rtx (mode) : target;
01506 
01507       insns = arm_gen_constant (AND, mode, remainder | shift_mask,
01508               new_src, source, subtargets, 1);
01509       source = new_src;
01510     }
01511         else
01512     {
01513       rtx targ = subtargets ? NULL_RTX : target;
01514 
01515       insns = arm_gen_constant (AND, mode, remainder | shift_mask,
01516               targ, source, subtargets, 0);
01517     }
01518       }
01519 
01520     if (generate)
01521       {
01522         rtx new_src = subtargets ? gen_reg_rtx (mode) : target;
01523         rtx shift = GEN_INT (clear_zero_bit_copies);
01524 
01525         emit_insn (gen_lshrsi3 (new_src, source, shift));
01526         emit_insn (gen_ashlsi3 (target, new_src, shift));
01527       }
01528 
01529     return insns + 2;
01530   }
01531 
01532       break;
01533 
01534     default:
01535       break;
01536     }
01537 
01538   for (i = 0; i < 32; i++)
01539     if (remainder & (1 << i))
01540       num_bits_set++;
01541 
01542   if (code == AND || (can_invert && num_bits_set > 16))
01543     remainder = (~remainder) & 0xffffffff;
01544   else if (code == PLUS && num_bits_set > 16)
01545     remainder = (-remainder) & 0xffffffff;
01546   else
01547     {
01548       can_invert = 0;
01549       can_negate = 0;
01550     }
01551 
01552   /* Now try and find a way of doing the job in either two or three
01553      instructions.
01554      We start by looking for the largest block of zeros that are aligned on
01555      a 2-bit boundary, we then fill up the temps, wrapping around to the
01556      top of the word when we drop off the bottom.
01557      In the worst case this code should produce no more than four insns.  */
01558   {
01559     int best_start = 0;
01560     int best_consecutive_zeros = 0;
01561 
01562     for (i = 0; i < 32; i += 2)
01563       {
01564   int consecutive_zeros = 0;
01565 
01566   if (!(remainder & (3 << i)))
01567     {
01568       while ((i < 32) && !(remainder & (3 << i)))
01569         {
01570     consecutive_zeros += 2;
01571     i += 2;
01572         }
01573       if (consecutive_zeros > best_consecutive_zeros)
01574         {
01575     best_consecutive_zeros = consecutive_zeros;
01576     best_start = i - consecutive_zeros;
01577         }
01578       i -= 2;
01579     }
01580       }
01581 
01582     /* So long as it won't require any more insns to do so, it's
01583        desirable to emit a small constant (in bits 0...9) in the last
01584        insn.  This way there is more chance that it can be combined with
01585        a later addressing insn to form a pre-indexed load or store
01586        operation.  Consider:
01587 
01588          *((volatile int *)0xe0000100) = 1;
01589          *((volatile int *)0xe0000110) = 2;
01590 
01591        We want this to wind up as:
01592 
01593     mov rA, #0xe0000000
01594     mov rB, #1
01595     str rB, [rA, #0x100]
01596     mov rB, #2
01597     str rB, [rA, #0x110]
01598 
01599        rather than having to synthesize both large constants from scratch.
01600 
01601        Therefore, we calculate how many insns would be required to emit
01602        the constant starting from `best_start', and also starting from 
01603        zero (ie with bit 31 first to be output).  If `best_start' doesn't 
01604        yield a shorter sequence, we may as well use zero.  */
01605     if (best_start != 0
01606   && ((((unsigned HOST_WIDE_INT) 1) << best_start) < remainder)
01607   && (count_insns_for_constant (remainder, 0) <= 
01608       count_insns_for_constant (remainder, best_start)))
01609       best_start = 0;
01610 
01611     /* Now start emitting the insns.  */
01612     i = best_start;
01613     do
01614       {
01615   int end;
01616 
01617   if (i <= 0)
01618     i += 32;
01619   if (remainder & (3 << (i - 2)))
01620     {
01621       end = i - 8;
01622       if (end < 0)
01623         end += 32;
01624       temp1 = remainder & ((0x0ff << end)
01625          | ((i < end) ? (0xff >> (32 - end)) : 0));
01626       remainder &= ~temp1;
01627 
01628       if (generate)
01629         {
01630     rtx new_src, temp1_rtx;
01631 
01632     if (code == SET || code == MINUS)
01633       {
01634         new_src = (subtargets ? gen_reg_rtx (mode) : target);
01635         if (can_invert && code != MINUS)
01636           temp1 = ~temp1;
01637       }
01638     else
01639       {
01640         if (remainder && subtargets)
01641           new_src = gen_reg_rtx (mode);
01642         else
01643           new_src = target;
01644         if (can_invert)
01645           temp1 = ~temp1;
01646         else if (can_negate)
01647           temp1 = -temp1;
01648       }
01649 
01650     temp1 = trunc_int_for_mode (temp1, mode);
01651     temp1_rtx = GEN_INT (temp1);
01652 
01653     if (code == SET)
01654       ;
01655     else if (code == MINUS)
01656       temp1_rtx = gen_rtx_MINUS (mode, temp1_rtx, source);
01657     else
01658       temp1_rtx = gen_rtx_fmt_ee (code, mode, source, temp1_rtx);
01659 
01660     emit_insn (gen_rtx_SET (VOIDmode, new_src, temp1_rtx));
01661     source = new_src;
01662         }
01663 
01664       if (code == SET)
01665         {
01666     can_invert = 0;
01667     code = PLUS;
01668         }
01669       else if (code == MINUS)
01670         code = PLUS;
01671 
01672       insns++;
01673       i -= 6;
01674     }
01675   i -= 2;
01676       }
01677     while (remainder);
01678   }
01679 
01680   return insns;
01681 }
01682 
01683 /* Canonicalize a comparison so that we are more likely to recognize it.
01684    This can be done for a few constant compares, where we can make the
01685    immediate value easier to load.  */
01686 
01687 enum rtx_code
01688 arm_canonicalize_comparison (code, op1)
01689      enum rtx_code code;
01690      rtx * op1;
01691 {
01692   unsigned HOST_WIDE_INT i = INTVAL (*op1);
01693 
01694   switch (code)
01695     {
01696     case EQ:
01697     case NE:
01698       return code;
01699 
01700     case GT:
01701     case LE:
01702       if (i != ((((unsigned HOST_WIDE_INT) 1) << (HOST_BITS_PER_WIDE_INT - 1)) - 1)
01703     && (const_ok_for_arm (i + 1) || const_ok_for_arm (-(i + 1))))
01704   {
01705     *op1 = GEN_INT (i + 1);
01706     return code == GT ? GE : LT;
01707   }
01708       break;
01709 
01710     case GE:
01711     case LT:
01712       if (i != (((unsigned HOST_WIDE_INT) 1) << (HOST_BITS_PER_WIDE_INT - 1))
01713     && (const_ok_for_arm (i - 1) || const_ok_for_arm (-(i - 1))))
01714   {
01715     *op1 = GEN_INT (i - 1);
01716     return code == GE ? GT : LE;
01717   }
01718       break;
01719 
01720     case GTU:
01721     case LEU:
01722       if (i != ~((unsigned HOST_WIDE_INT) 0)
01723     && (const_ok_for_arm (i + 1) || const_ok_for_arm (-(i + 1))))
01724   {
01725     *op1 = GEN_INT (i + 1);
01726     return code == GTU ? GEU : LTU;
01727   }
01728       break;
01729 
01730     case GEU:
01731     case LTU:
01732       if (i != 0
01733     && (const_ok_for_arm (i - 1) || const_ok_for_arm (-(i - 1))))
01734   {
01735     *op1 = GEN_INT (i - 1);
01736     return code == GEU ? GTU : LEU;
01737   }
01738       break;
01739 
01740     default:
01741       abort ();
01742     }
01743 
01744   return code;
01745 }
01746 
01747 /* Decide whether a type should be returned in memory (true)
01748    or in a register (false).  This is called by the macro
01749    RETURN_IN_MEMORY.  */
01750 
01751 int
01752 arm_return_in_memory (type)
01753      tree type;
01754 {
01755   if (!AGGREGATE_TYPE_P (type))
01756     /* All simple types are returned in registers.  */
01757     return 0;
01758   
01759   /* For the arm-wince targets we choose to be compitable with Microsoft's
01760      ARM and Thumb compilers, which always return aggregates in memory.  */
01761 #ifndef ARM_WINCE
01762   /* All structures/unions bigger than one word are returned in memory.
01763      Also catch the case where int_size_in_bytes returns -1.  In this case
01764      the aggregate is either huge or of varaible size, and in either case
01765      we will want to return it via memory and not in a register.  */
01766   if (((unsigned int) int_size_in_bytes (type)) > UNITS_PER_WORD)
01767     return 1;
01768   
01769   if (TREE_CODE (type) == RECORD_TYPE)
01770     {
01771       tree field;
01772 
01773       /* For a struct the APCS says that we only return in a register
01774    if the type is 'integer like' and every addressable element
01775    has an offset of zero.  For practical purposes this means
01776    that the structure can have at most one non bit-field element
01777    and that this element must be the first one in the structure.  */
01778       
01779       /* Find the first field, ignoring non FIELD_DECL things which will
01780    have been created by C++.  */
01781       for (field = TYPE_FIELDS (type);
01782      field && TREE_CODE (field) != FIELD_DECL;
01783      field = TREE_CHAIN (field))
01784   continue;
01785       
01786       if (field == NULL)
01787   return 0; /* An empty structure.  Allowed by an extension to ANSI C.  */
01788 
01789       /* Check that the first field is valid for returning in a register.  */
01790 
01791       /* ... Floats are not allowed */
01792       if (FLOAT_TYPE_P (TREE_TYPE (field)))
01793   return 1;
01794 
01795       /* ... Aggregates that are not themselves valid for returning in
01796    a register are not allowed.  */
01797       if (RETURN_IN_MEMORY (TREE_TYPE (field)))
01798   return 1;
01799 
01800       /* Now check the remaining fields, if any.  Only bitfields are allowed,
01801    since they are not addressable.  */
01802       for (field = TREE_CHAIN (field);
01803      field;
01804      field = TREE_CHAIN (field))
01805   {
01806     if (TREE_CODE (field) != FIELD_DECL)
01807       continue;
01808     
01809     if (!DECL_BIT_FIELD_TYPE (field))
01810       return 1;
01811   }
01812 
01813       return 0;
01814     }
01815   
01816   if (TREE_CODE (type) == UNION_TYPE)
01817     {
01818       tree field;
01819 
01820       /* Unions can be returned in registers if every element is
01821    integral, or can be returned in an integer register.  */
01822       for (field = TYPE_FIELDS (type);
01823      field;
01824      field = TREE_CHAIN (field))
01825   {
01826     if (TREE_CODE (field) != FIELD_DECL)
01827       continue;
01828 
01829     if (FLOAT_TYPE_P (TREE_TYPE (field)))
01830       return 1;
01831     
01832     if (RETURN_IN_MEMORY (TREE_TYPE (field)))
01833       return 1;
01834   }
01835       
01836       return 0;
01837     }
01838 #endif /* not ARM_WINCE */  
01839   
01840   /* Return all other types in memory.  */
01841   return 1;
01842 }
01843 
01844 /* Initialize a variable CUM of type CUMULATIVE_ARGS
01845    for a call to a function whose data type is FNTYPE.
01846    For a library call, FNTYPE is NULL.  */
01847 void
01848 arm_init_cumulative_args (pcum, fntype, libname, indirect)
01849      CUMULATIVE_ARGS * pcum;
01850      tree fntype;
01851      rtx libname  ATTRIBUTE_UNUSED;
01852      int indirect ATTRIBUTE_UNUSED;
01853 {
01854   /* On the ARM, the offset starts at 0.  */
01855   pcum->nregs = ((fntype && aggregate_value_p (TREE_TYPE (fntype))) ? 1 : 0);
01856   
01857   pcum->call_cookie = CALL_NORMAL;
01858 
01859   if (TARGET_LONG_CALLS)
01860     pcum->call_cookie = CALL_LONG;
01861     
01862   /* Check for long call/short call attributes.  The attributes
01863      override any command line option.  */
01864   if (fntype)
01865     {
01866       if (lookup_attribute ("short_call", TYPE_ATTRIBUTES (fntype)))
01867   pcum->call_cookie = CALL_SHORT;
01868       else if (lookup_attribute ("long_call", TYPE_ATTRIBUTES (fntype)))
01869   pcum->call_cookie = CALL_LONG;
01870     }
01871 }
01872 
01873 /* Determine where to put an argument to a function.
01874    Value is zero to push the argument on the stack,
01875    or a hard register in which to store the argument.
01876 
01877    MODE is the argument's machine mode.
01878    TYPE is the data type of the argument (as a tree).
01879     This is null for libcalls where that information may
01880     not be available.
01881    CUM is a variable of type CUMULATIVE_ARGS which gives info about
01882     the preceding args and about the function being called.
01883    NAMED is nonzero if this argument is a named parameter
01884     (otherwise it is an extra parameter matching an ellipsis).  */
01885 
01886 rtx
01887 arm_function_arg (pcum, mode, type, named)
01888      CUMULATIVE_ARGS * pcum;
01889      enum machine_mode mode;
01890      tree type ATTRIBUTE_UNUSED;
01891      int named;
01892 {
01893   if (mode == VOIDmode)
01894     /* Compute operand 2 of the call insn.  */
01895     return GEN_INT (pcum->call_cookie);
01896   
01897   if (!named || pcum->nregs >= NUM_ARG_REGS)
01898     return NULL_RTX;
01899   
01900   return gen_rtx_REG (mode, pcum->nregs);
01901 }
01902 
01903 /* Encode the current state of the #pragma [no_]long_calls.  */
01904 typedef enum
01905 {
01906   OFF,    /* No #pramgma [no_]long_calls is in effect.  */
01907   LONG,   /* #pragma long_calls is in effect.  */
01908   SHORT   /* #pragma no_long_calls is in effect.  */
01909 } arm_pragma_enum;
01910 
01911 static arm_pragma_enum arm_pragma_long_calls = OFF;
01912 
01913 void
01914 arm_pr_long_calls (pfile)
01915      cpp_reader * pfile ATTRIBUTE_UNUSED;
01916 {
01917   arm_pragma_long_calls = LONG;
01918 }
01919 
01920 void
01921 arm_pr_no_long_calls (pfile)
01922      cpp_reader * pfile ATTRIBUTE_UNUSED;
01923 {
01924   arm_pragma_long_calls = SHORT;
01925 }
01926 
01927 void
01928 arm_pr_long_calls_off (pfile)
01929      cpp_reader * pfile ATTRIBUTE_UNUSED;
01930 {
01931   arm_pragma_long_calls = OFF;
01932 }
01933 
01934 /* Table of machine attributes.  */
01935 const struct attribute_spec arm_attribute_table[] =
01936 {
01937   /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
01938   /* Function calls made to this symbol must be done indirectly, because
01939      it may lie outside of the 26 bit addressing range of a normal function
01940      call.  */
01941   { "long_call",    0, 0, false, true,  true,  NULL },
01942   /* Whereas these functions are always known to reside within the 26 bit
01943      addressing range.  */
01944   { "short_call",   0, 0, false, true,  true,  NULL },
01945   /* Interrupt Service Routines have special prologue and epilogue requirements.  */ 
01946   { "isr",          0, 1, false, false, false, arm_handle_isr_attribute },
01947   { "interrupt",    0, 1, false, false, false, arm_handle_isr_attribute },
01948   { "naked",        0, 0, true,  false, false, arm_handle_fndecl_attribute },
01949 #ifdef ARM_PE
01950   /* ARM/PE has three new attributes:
01951      interfacearm - ?
01952      dllexport - for exporting a function/variable that will live in a dll
01953      dllimport - for importing a function/variable from a dll
01954 
01955      Microsoft allows multiple declspecs in one __declspec, separating
01956      them with spaces.  We do NOT support this.  Instead, use __declspec
01957      multiple times.
01958   */
01959   { "dllimport",    0, 0, true,  false, false, NULL },
01960   { "dllexport",    0, 0, true,  false, false, NULL },
01961   { "interfacearm", 0, 0, true,  false, false, arm_handle_fndecl_attribute },
01962 #endif
01963   { NULL,           0, 0, false, false, false, NULL }
01964 };
01965 
01966 /* Handle an attribute requiring a FUNCTION_DECL;
01967    arguments as in struct attribute_spec.handler.  */
01968 
01969 static tree
01970 arm_handle_fndecl_attribute (node, name, args, flags, no_add_attrs)
01971      tree * node;
01972      tree   name;
01973      tree   args ATTRIBUTE_UNUSED;
01974      int    flags ATTRIBUTE_UNUSED;
01975      bool * no_add_attrs;
01976 {
01977   if (TREE_CODE (*node) != FUNCTION_DECL)
01978     {
01979       warning ("`%s' attribute only applies to functions",
01980          IDENTIFIER_POINTER (name));
01981       *no_add_attrs = true;
01982     }
01983 
01984   return NULL_TREE;
01985 }
01986 
01987 /* Handle an "interrupt" or "isr" attribute;
01988    arguments as in struct attribute_spec.handler.  */
01989 
01990 static tree
01991 arm_handle_isr_attribute (node, name, args, flags, no_add_attrs)
01992      tree * node;
01993      tree   name;
01994      tree   args;
01995      int    flags;
01996      bool * no_add_attrs;
01997 {
01998   if (DECL_P (*node))
01999     {
02000       if (TREE_CODE (*node) != FUNCTION_DECL)
02001   {
02002     warning ("`%s' attribute only applies to functions",
02003        IDENTIFIER_POINTER (name));
02004     *no_add_attrs = true;
02005   }
02006       /* FIXME: the argument if any is checked for type attributes;
02007    should it be checked for decl ones?  */
02008     }
02009   else
02010     {
02011       if (TREE_CODE (*node) == FUNCTION_TYPE
02012     || TREE_CODE (*node) == METHOD_TYPE)
02013   {
02014     if (arm_isr_value (args) == ARM_FT_UNKNOWN)
02015       {
02016         warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
02017         *no_add_attrs = true;
02018       }
02019   }
02020       else if (TREE_CODE (*node) == POINTER_TYPE
02021          && (TREE_CODE (TREE_TYPE (*node)) == FUNCTION_TYPE
02022        || TREE_CODE (TREE_TYPE (*node)) == METHOD_TYPE)
02023          && arm_isr_value (args) != ARM_FT_UNKNOWN)
02024   {
02025     *node = build_type_copy (*node);
02026     TREE_TYPE (*node) = build_type_attribute_variant
02027       (TREE_TYPE (*node),
02028        tree_cons (name, args, TYPE_ATTRIBUTES (TREE_TYPE (*node))));
02029     *no_add_attrs = true;
02030   }
02031       else
02032   {
02033     /* Possibly pass this attribute on from the type to a decl.  */
02034     if (flags & ((int) ATTR_FLAG_DECL_NEXT
02035            | (int) ATTR_FLAG_FUNCTION_NEXT
02036            | (int) ATTR_FLAG_ARRAY_NEXT))
02037       {
02038         *no_add_attrs = true;
02039         return tree_cons (name, args, NULL_TREE);
02040       }
02041     else
02042       {
02043         warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
02044       }
02045   }
02046     }
02047 
02048   return NULL_TREE;
02049 }
02050 
02051 /* Return 0 if the attributes for two types are incompatible, 1 if they
02052    are compatible, and 2 if they are nearly compatible (which causes a
02053    warning to be generated).  */
02054 
02055 static int
02056 arm_comp_type_attributes (type1, type2)
02057      tree type1;
02058      tree type2;
02059 {
02060   int l1, l2, s1, s2;
02061   
02062   /* Check for mismatch of non-default calling convention.  */
02063   if (TREE_CODE (type1) != FUNCTION_TYPE)
02064     return 1;
02065 
02066   /* Check for mismatched call attributes.  */
02067   l1 = lookup_attribute ("long_call", TYPE_ATTRIBUTES (type1)) != NULL;
02068   l2 = lookup_attribute ("long_call", TYPE_ATTRIBUTES (type2)) != NULL;
02069   s1 = lookup_attribute ("short_call", TYPE_ATTRIBUTES (type1)) != NULL;
02070   s2 = lookup_attribute ("short_call", TYPE_ATTRIBUTES (type2)) != NULL;
02071 
02072   /* Only bother to check if an attribute is defined.  */
02073   if (l1 | l2 | s1 | s2)
02074     {
02075       /* If one type has an attribute, the other must have the same attribute.  */
02076       if ((l1 != l2) || (s1 != s2))
02077   return 0;
02078 
02079       /* Disallow mixed attributes.  */
02080       if ((l1 & s2) || (l2 & s1))
02081   return 0;
02082     }
02083   
02084   /* Check for mismatched ISR attribute.  */
02085   l1 = lookup_attribute ("isr", TYPE_ATTRIBUTES (type1)) != NULL;
02086   if (! l1)
02087     l1 = lookup_attribute ("interrupt", TYPE_ATTRIBUTES (type1)) != NULL;
02088   l2 = lookup_attribute ("isr", TYPE_ATTRIBUTES (type2)) != NULL;
02089   if (! l2)
02090     l1 = lookup_attribute ("interrupt", TYPE_ATTRIBUTES (type2)) != NULL;
02091   if (l1 != l2)
02092     return 0;
02093 
02094   return 1;
02095 }
02096 
02097 /*  Encode long_call or short_call attribute by prefixing
02098     symbol name in DECL with a special character FLAG.  */
02099 
02100 void
02101 arm_encode_call_attribute (decl, flag)
02102   tree decl;
02103   int flag;
02104 {
02105   const char * str = XSTR (XEXP (DECL_RTL (decl), 0), 0);
02106   int          len = strlen (str);
02107   char *       newstr;
02108 
02109   /* Do not allow weak functions to be treated as short call.  */
02110   if (DECL_WEAK (decl) && flag == SHORT_CALL_FLAG_CHAR)
02111     return;
02112 
02113   newstr = alloca (len + 2);
02114   newstr[0] = flag;
02115   strcpy (newstr + 1, str);
02116 
02117   newstr = (char *) ggc_alloc_string (newstr, len + 1);
02118   XSTR (XEXP (DECL_RTL (decl), 0), 0) = newstr;
02119 }
02120 
02121 /*  Assigns default attributes to newly defined type.  This is used to
02122     set short_call/long_call attributes for function types of
02123     functions defined inside corresponding #pragma scopes.  */
02124 
02125 static void
02126 arm_set_default_type_attributes (type)
02127   tree type;
02128 {
02129   /* Add __attribute__ ((long_call)) to all functions, when
02130      inside #pragma long_calls or __attribute__ ((short_call)),
02131      when inside #pragma no_long_calls.  */
02132   if (TREE_CODE (type) == FUNCTION_TYPE || TREE_CODE (type) == METHOD_TYPE)
02133     {
02134       tree type_attr_list, attr_name;
02135       type_attr_list = TYPE_ATTRIBUTES (type);
02136 
02137       if (arm_pragma_long_calls == LONG)
02138   attr_name = get_identifier ("long_call");
02139       else if (arm_pragma_long_calls == SHORT)
02140   attr_name = get_identifier ("short_call");
02141       else
02142   return;
02143 
02144       type_attr_list = tree_cons (attr_name, NULL_TREE, type_attr_list);
02145       TYPE_ATTRIBUTES (type) = type_attr_list;
02146     }
02147 }
02148 
02149 /* Return 1 if the operand is a SYMBOL_REF for a function known to be
02150    defined within the current compilation unit.  If this caanot be
02151    determined, then 0 is returned.  */
02152 
02153 static int
02154 current_file_function_operand (sym_ref)
02155   rtx sym_ref;
02156 {
02157   /* This is a bit of a fib.  A function will have a short call flag
02158      applied to its name if it has the short call attribute, or it has
02159      already been defined within the current compilation unit.  */
02160   if (ENCODED_SHORT_CALL_ATTR_P (XSTR (sym_ref, 0)))
02161     return 1;
02162 
02163   /* The current function is always defined within the current compilation
02164      unit.  if it s a weak definition however, then this may not be the real
02165      definition of the function, and so we have to say no.  */
02166   if (sym_ref == XEXP (DECL_RTL (current_function_decl), 0)
02167       && !DECL_WEAK (current_function_decl))
02168     return 1;
02169 
02170   /* We cannot make the determination - default to returning 0.  */
02171   return 0;
02172 }
02173 
02174 /* Return non-zero if a 32 bit "long_call" should be generated for
02175    this call.  We generate a long_call if the function:
02176 
02177         a.  has an __attribute__((long call))
02178      or b.  is within the scope of a #pragma long_calls
02179      or c.  the -mlong-calls command line switch has been specified
02180 
02181    However we do not generate a long call if the function:
02182    
02183         d.  has an __attribute__ ((short_call))
02184      or e.  is inside the scope of a #pragma no_long_calls
02185      or f.  has an __attribute__ ((section))
02186      or g.  is defined within the current compilation unit.
02187    
02188    This function will be called by C fragments contained in the machine
02189    description file.  CALL_REF and CALL_COOKIE correspond to the matched
02190    rtl operands.  CALL_SYMBOL is used to distinguish between
02191    two different callers of the function.  It is set to 1 in the
02192    "call_symbol" and "call_symbol_value" patterns and to 0 in the "call"
02193    and "call_value" patterns.  This is because of the difference in the
02194    SYM_REFs passed by these patterns.  */
02195 
02196 int
02197 arm_is_longcall_p (sym_ref, call_cookie, call_symbol)
02198   rtx sym_ref;
02199   int call_cookie;
02200   int call_symbol;
02201 {
02202   if (!call_symbol)
02203     {
02204       if (GET_CODE (sym_ref) != MEM)
02205   return 0;
02206 
02207       sym_ref = XEXP (sym_ref, 0);
02208     }
02209 
02210   if (GET_CODE (sym_ref) != SYMBOL_REF)
02211     return 0;
02212 
02213   if (call_cookie & CALL_SHORT)
02214     return 0;
02215 
02216   if (TARGET_LONG_CALLS && flag_function_sections)
02217     return 1;
02218   
02219   if (current_file_function_operand (sym_ref))
02220     return 0;
02221   
02222   return (call_cookie & CALL_LONG)
02223     || ENCODED_LONG_CALL_ATTR_P (XSTR (sym_ref, 0))
02224     || TARGET_LONG_CALLS;
02225 }
02226 
02227 /* Return non-zero if it is ok to make a tail-call to DECL.  */
02228 
02229 int
02230 arm_function_ok_for_sibcall (decl)
02231      tree decl;
02232 {
02233   int call_type = TARGET_LONG_CALLS ? CALL_LONG : CALL_NORMAL;
02234 
02235   /* Never tailcall something for which we have no decl, or if we
02236      are in Thumb mode.  */
02237   if (decl == NULL || TARGET_THUMB)
02238     return 0;
02239 
02240   /* Get the calling method.  */
02241   if (lookup_attribute ("short_call", TYPE_ATTRIBUTES (TREE_TYPE (decl))))
02242     call_type = CALL_SHORT;
02243   else if (lookup_attribute ("long_call", TYPE_ATTRIBUTES (TREE_TYPE (decl))))
02244     call_type = CALL_LONG;
02245 
02246   /* Cannot tail-call to long calls, since these are out of range of
02247      a branch instruction.  However, if not compiling PIC, we know
02248      we can reach the symbol if it is in this compilation unit.  */
02249   if (call_type == CALL_LONG && (flag_pic || !TREE_ASM_WRITTEN (decl)))
02250     return 0;
02251 
02252   /* If we are interworking and the function is not declared static
02253      then we can't tail-call it unless we know that it exists in this 
02254      compilation unit (since it might be a Thumb routine).  */
02255   if (TARGET_INTERWORK && TREE_PUBLIC (decl) && !TREE_ASM_WRITTEN (decl))
02256     return 0;
02257 
02258   /* Never tailcall from an ISR routine - it needs a special exit sequence.  */
02259   if (IS_INTERRUPT (arm_current_func_type ()))
02260     return 0;
02261 
02262   /* Everything else is ok.  */
02263   return 1;
02264 }
02265 
02266 
02267 int
02268 legitimate_pic_operand_p (x)
02269      rtx x;
02270 {
02271   if (CONSTANT_P (x)
02272       && flag_pic
02273       && (GET_CODE (x) == SYMBOL_REF
02274     || (GET_CODE (x) == CONST
02275         && GET_CODE (XEXP (x, 0)) == PLUS
02276         && GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF)))
02277     return 0;
02278 
02279   return 1;
02280 }
02281 
02282 rtx
02283 legitimize_pic_address (orig, mode, reg)
02284      rtx orig;
02285      enum machine_mode mode;
02286      rtx reg;
02287 {
02288   if (GET_CODE (orig) == SYMBOL_REF
02289       || GET_CODE (orig) == LABEL_REF)
02290     {
02291 #ifndef AOF_ASSEMBLER
02292       rtx pic_ref, address;
02293 #endif
02294       rtx insn;
02295       int subregs = 0;
02296 
02297       if (reg == 0)
02298   {
02299     if (no_new_pseudos)
02300       abort ();
02301     else
02302       reg = gen_reg_rtx (Pmode);
02303 
02304     subregs = 1;
02305   }
02306 
02307 #ifdef AOF_ASSEMBLER
02308       /* The AOF assembler can generate relocations for these directly, and
02309    understands that the PIC register has to be added into the offset.  */
02310       insn = emit_insn (gen_pic_load_addr_based (reg, orig));
02311 #else
02312       if (subregs)
02313   address = gen_reg_rtx (Pmode);
02314       else
02315   address = reg;
02316 
02317       if (TARGET_ARM)
02318   emit_insn (gen_pic_load_addr_arm (address, orig));
02319       else
02320   emit_insn (gen_pic_load_addr_thumb (address, orig));
02321 
02322       if ((GET_CODE (orig) == LABEL_REF
02323      || (GET_CODE (orig) == SYMBOL_REF && 
02324          ENCODED_SHORT_CALL_ATTR_P (XSTR (orig, 0))))
02325     && NEED_GOT_RELOC)
02326   pic_ref = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, address);
02327       else
02328   {
02329     pic_ref = gen_rtx_MEM (Pmode,
02330          gen_rtx_PLUS (Pmode, pic_offset_table_rtx,
02331                  address));
02332     RTX_UNCHANGING_P (pic_ref) = 1;
02333   }
02334 
02335       insn = emit_move_insn (reg, pic_ref);
02336 #endif
02337       current_function_uses_pic_offset_table = 1;
02338       /* Put a REG_EQUAL note on this insn, so that it can be optimized
02339    by loop.  */
02340       REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, orig,
02341               REG_NOTES (insn));
02342       return reg;
02343     }
02344   else if (GET_CODE (orig) == CONST)
02345     {
02346       rtx base, offset;
02347 
02348       if (GET_CODE (XEXP (orig, 0)) == PLUS
02349     && XEXP (XEXP (orig, 0), 0) == pic_offset_table_rtx)
02350   return orig;
02351 
02352       if (reg == 0)
02353   {
02354     if (no_new_pseudos)
02355       abort ();
02356     else
02357       reg = gen_reg_rtx (Pmode);
02358   }
02359 
02360       if (GET_CODE (XEXP (orig, 0)) == PLUS)
02361   {
02362     base = legitimize_pic_address (XEXP (XEXP (orig, 0), 0), Pmode, reg);
02363     offset = legitimize_pic_address (XEXP (XEXP (orig, 0), 1), Pmode,
02364              base == reg ? 0 : reg);
02365   }
02366       else
02367   abort ();
02368 
02369       if (GET_CODE (offset) == CONST_INT)
02370   {
02371     /* The base register doesn't really matter, we only want to
02372        test the index for the appropriate mode.  */
02373     ARM_GO_IF_LEGITIMATE_INDEX (mode, 0, offset, win);
02374 
02375     if (!no_new_pseudos)
02376       offset = force_reg (Pmode, offset);
02377     else
02378       abort ();
02379 
02380   win:
02381     if (GET_CODE (offset) == CONST_INT)
02382       return plus_constant (base, INTVAL (offset));
02383   }
02384 
02385       if (GET_MODE_SIZE (mode) > 4
02386     && (GET_MODE_CLASS (mode) == MODE_INT
02387         || TARGET_SOFT_FLOAT))
02388   {
02389     emit_insn (gen_addsi3 (reg, base, offset));
02390     return reg;
02391   }
02392 
02393       return gen_rtx_PLUS (Pmode, base, offset);
02394     }
02395 
02396   return orig;
02397 }
02398 
02399 /* Generate code to load the PIC register.  PROLOGUE is true if
02400    called from arm_expand_prologue (in which case we want the 
02401    generated insns at the start of the function);  false if called
02402    by an exception receiver that needs the PIC register reloaded
02403    (in which case the insns are just dumped at the current location).  */
02404 
02405 void
02406 arm_finalize_pic (prologue)
02407      int prologue ATTRIBUTE_UNUSED;
02408 {
02409 #ifndef AOF_ASSEMBLER
02410   rtx l1, pic_tmp, pic_tmp2, seq, pic_rtx;
02411   rtx global_offset_table;
02412 
02413   if (current_function_uses_pic_offset_table == 0 || TARGET_SINGLE_PIC_BASE)
02414     return;
02415 
02416   if (!flag_pic)
02417     abort ();
02418 
02419   start_sequence ();
02420   l1 = gen_label_rtx ();
02421 
02422   global_offset_table = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");
02423   /* On the ARM the PC register contains 'dot + 8' at the time of the
02424      addition, on the Thumb it is 'dot + 4'.  */
02425   pic_tmp = plus_constant (gen_rtx_LABEL_REF (Pmode, l1), TARGET_ARM ? 8 : 4);
02426   if (GOT_PCREL)
02427     pic_tmp2 = gen_rtx_CONST (VOIDmode,
02428           gen_rtx_PLUS (Pmode, global_offset_table, pc_rtx));
02429   else
02430     pic_tmp2 = gen_rtx_CONST (VOIDmode, global_offset_table);
02431 
02432   pic_rtx = gen_rtx_CONST (Pmode, gen_rtx_MINUS (Pmode, pic_tmp2, pic_tmp));
02433   
02434   if (TARGET_ARM)
02435     {
02436       emit_insn (gen_pic_load_addr_arm (pic_offset_table_rtx, pic_rtx));
02437       emit_insn (gen_pic_add_dot_plus_eight (pic_offset_table_rtx, l1));
02438     }
02439   else
02440     {
02441       emit_insn (gen_pic_load_addr_thumb (pic_offset_table_rtx, pic_rtx));
02442       emit_insn (gen_pic_add_dot_plus_four (pic_offset_table_rtx, l1));
02443     }
02444 
02445   seq = gen_sequence ();
02446   end_sequence ();
02447   if (prologue)
02448     emit_insn_after (seq, get_insns ());
02449   else
02450     emit_insn (seq);
02451 
02452   /* Need to emit this whether or not we obey regdecls,
02453      since setjmp/longjmp can cause life info to screw up.  */
02454   emit_insn (gen_rtx_USE (VOIDmode, pic_offset_table_rtx));
02455 #endif /* AOF_ASSEMBLER */
02456 }
02457 
02458 #define REG_OR_SUBREG_REG(X)            \
02459   (GET_CODE (X) == REG              \
02460    || (GET_CODE (X) == SUBREG && GET_CODE (SUBREG_REG (X)) == REG))
02461 
02462 #define REG_OR_SUBREG_RTX(X)      \
02463    (GET_CODE (X) == REG ? (X) : SUBREG_REG (X))
02464 
02465 #ifndef COSTS_N_INSNS
02466 #define COSTS_N_INSNS(N) ((N) * 4 - 2)
02467 #endif
02468 
02469 int
02470 arm_rtx_costs (x, code, outer)
02471      rtx x;
02472      enum rtx_code code;
02473      enum rtx_code outer;
02474 {
02475   enum machine_mode mode = GET_MODE (x);
02476   enum rtx_code subcode;
02477   int extra_cost;
02478 
02479   if (TARGET_THUMB)
02480     {
02481       switch (code)
02482   {
02483   case ASHIFT:
02484   case ASHIFTRT:
02485   case LSHIFTRT:
02486   case ROTATERT:  
02487   case PLUS:
02488   case MINUS:
02489   case COMPARE:
02490   case NEG:
02491   case NOT: 
02492     return COSTS_N_INSNS (1);
02493     
02494   case MULT:              
02495     if (GET_CODE (XEXP (x, 1)) == CONST_INT)      
02496       {               
02497         int cycles = 0;           
02498         unsigned HOST_WIDE_INT i = INTVAL (XEXP (x, 1));
02499         
02500         while (i)           
02501     {             
02502       i >>= 2;            
02503       cycles++;           
02504     }             
02505         return COSTS_N_INSNS (2) + cycles;      
02506       }
02507     return COSTS_N_INSNS (1) + 16;
02508     
02509   case SET:             
02510     return (COSTS_N_INSNS (1)         
02511       + 4 * ((GET_CODE (SET_SRC (x)) == MEM)    
02512        + GET_CODE (SET_DEST (x)) == MEM));
02513     
02514   case CONST_INT:           
02515     if (outer == SET)           
02516       {             
02517         if ((unsigned HOST_WIDE_INT) INTVAL (x) < 256)    
02518     return 0;           
02519         if (thumb_shiftable_const (INTVAL (x)))     
02520     return COSTS_N_INSNS (2);       
02521         return COSTS_N_INSNS (3);       
02522       }               
02523     else if (outer == PLUS          
02524        && INTVAL (x) < 256 && INTVAL (x) > -256)    
02525       return 0;             
02526     else if (outer == COMPARE         
02527        && (unsigned HOST_WIDE_INT) INTVAL (x) < 256)  
02528       return 0;             
02529     else if (outer == ASHIFT || outer == ASHIFTRT   
02530        || outer == LSHIFTRT)        
02531       return 0;             
02532     return COSTS_N_INSNS (2);
02533     
02534   case CONST:             
02535   case CONST_DOUBLE:            
02536   case LABEL_REF:           
02537   case SYMBOL_REF:            
02538     return COSTS_N_INSNS (3);
02539     
02540   case UDIV:
02541   case UMOD:
02542   case DIV:
02543   case MOD:
02544     return 100;
02545 
02546   case TRUNCATE:
02547     return 99;
02548 
02549   case AND:
02550   case XOR:
02551   case IOR: 
02552     /* XXX guess. */
02553     return 8;
02554 
02555   case ADDRESSOF:
02556   case MEM:
02557     /* XXX another guess.  */
02558     /* Memory costs quite a lot for the first word, but subsequent words
02559        load at the equivalent of a single insn each.  */
02560     return (10 + 4 * ((GET_MODE_SIZE (mode) - 1) / UNITS_PER_WORD)
02561       + (CONSTANT_POOL_ADDRESS_P (x) ? 4 : 0));
02562 
02563   case IF_THEN_ELSE:
02564     /* XXX a guess. */
02565     if (GET_CODE (XEXP (x, 1)) == PC || GET_CODE (XEXP (x, 2)) == PC)
02566       return 14;
02567     return 2;
02568 
02569   case ZERO_EXTEND:
02570     /* XXX still guessing.  */
02571     switch (GET_MODE (XEXP (x, 0)))
02572       {
02573       case QImode:
02574         return (1 + (mode == DImode ? 4 : 0)
02575           + (GET_CODE (XEXP (x, 0)) == MEM ? 10 : 0));
02576         
02577       case HImode:
02578         return (4 + (mode == DImode ? 4 : 0)
02579           + (GET_CODE (XEXP (x, 0)) == MEM ? 10 : 0));
02580         
02581       case SImode:
02582         return (1 + (GET_CODE (XEXP (x, 0)) == MEM ? 10 : 0));
02583     
02584       default:
02585         return 99;
02586       }
02587     
02588   default:
02589     return 99;
02590 #if 0   
02591   case FFS:
02592   case FLOAT:
02593   case FIX:
02594   case UNSIGNED_FIX:
02595     /* XXX guess */
02596     fprintf (stderr, "unexpected code for thumb in rtx_costs: %s\n",
02597        rtx_name[code]);
02598     abort ();
02599 #endif
02600   }
02601     }
02602   
02603   switch (code)
02604     {
02605     case MEM:
02606       /* Memory costs quite a lot for the first word, but subsequent words
02607    load at the equivalent of a single insn each.  */
02608       return (10 + 4 * ((GET_MODE_SIZE (mode) - 1) / UNITS_PER_WORD)
02609         + (CONSTANT_POOL_ADDRESS_P (x) ? 4 : 0));
02610 
02611     case DIV:
02612     case MOD:
02613       return 100;
02614 
02615     case ROTATE:
02616       if (mode == SImode && GET_CODE (XEXP (x, 1)) == REG)
02617   return 4;
02618       /* Fall through */
02619     case ROTATERT:
02620       if (mode != SImode)
02621   return 8;
02622       /* Fall through */
02623     case ASHIFT: case LSHIFTRT: case ASHIFTRT:
02624       if (mode == DImode)
02625   return (8 + (GET_CODE (XEXP (x, 1)) == CONST_INT ? 0 : 8)
02626     + ((GET_CODE (XEXP (x, 0)) == REG 
02627         || (GET_CODE (XEXP (x, 0)) == SUBREG
02628       && GET_CODE (SUBREG_REG (XEXP (x, 0))) == REG))
02629        ? 0 : 8));
02630       return (1 + ((GET_CODE (XEXP (x, 0)) == REG
02631         || (GET_CODE (XEXP (x, 0)) == SUBREG
02632       && GET_CODE (SUBREG_REG (XEXP (x, 0))) == REG))
02633        ? 0 : 4)
02634         + ((GET_CODE (XEXP (x, 1)) == REG
02635       || (GET_CODE (XEXP (x, 1)) == SUBREG
02636           && GET_CODE (SUBREG_REG (XEXP (x, 1))) == REG)
02637       || (GET_CODE (XEXP (x, 1)) == CONST_INT))
02638      ? 0 : 4));
02639 
02640     case MINUS:
02641       if (mode == DImode)
02642   return (4 + (REG_OR_SUBREG_REG (XEXP (x, 1)) ? 0 : 8)
02643     + ((REG_OR_SUBREG_REG (XEXP (x, 0))
02644         || (GET_CODE (XEXP (x, 0)) == CONST_INT
02645            && const_ok_for_arm (INTVAL (XEXP (x, 0)))))
02646        ? 0 : 8));
02647 
02648       if (GET_MODE_CLASS (mode) == MODE_FLOAT)
02649   return (2 + ((REG_OR_SUBREG_REG (XEXP (x, 1))
02650           || (GET_CODE (XEXP (x, 1)) == CONST_DOUBLE
02651         && const_double_rtx_ok_for_fpu (XEXP (x, 1))))
02652          ? 0 : 8)
02653     + ((REG_OR_SUBREG_REG (XEXP (x, 0))
02654         || (GET_CODE (XEXP (x, 0)) == CONST_DOUBLE
02655       && const_double_rtx_ok_for_fpu (XEXP (x, 0))))
02656        ? 0 : 8));
02657 
02658       if (((GET_CODE (XEXP (x, 0)) == CONST_INT
02659       && const_ok_for_arm (INTVAL (XEXP (x, 0)))
02660       && REG_OR_SUBREG_REG (XEXP (x, 1))))
02661     || (((subcode = GET_CODE (XEXP (x, 1))) == ASHIFT
02662          || subcode == ASHIFTRT || subcode == LSHIFTRT
02663          || subcode == ROTATE || subcode == ROTATERT
02664          || (subcode == MULT
02665        && GET_CODE (XEXP (XEXP (x, 1), 1)) == CONST_INT
02666        && ((INTVAL (XEXP (XEXP (x, 1), 1)) &
02667       (INTVAL (XEXP (XEXP (x, 1), 1)) - 1)) == 0)))
02668         && REG_OR_SUBREG_REG (XEXP (XEXP (x, 1), 0))
02669         && (REG_OR_SUBREG_REG (XEXP (XEXP (x, 1), 1))
02670       || GET_CODE (XEXP (XEXP (x, 1), 1)) == CONST_INT)
02671         && REG_OR_SUBREG_REG (XEXP (x, 0))))
02672   return 1;
02673       /* Fall through */
02674 
02675     case PLUS: 
02676       if (GET_MODE_CLASS (mode) == MODE_FLOAT)
02677   return (2 + (REG_OR_SUBREG_REG (XEXP (x, 0)) ? 0 : 8)
02678     + ((REG_OR_SUBREG_REG (XEXP (x, 1))
02679         || (GET_CODE (XEXP (x, 1)) == CONST_DOUBLE
02680       && const_double_rtx_ok_for_fpu (XEXP (x, 1))))
02681        ? 0 : 8));
02682 
02683       /* Fall through */
02684     case AND: case XOR: case IOR: 
02685       extra_cost = 0;
02686 
02687       /* Normally the frame registers will be spilt into reg+const during
02688    reload, so it is a bad idea to combine them with other instructions,
02689    since then they might not be moved outside of loops.  As a compromise
02690    we allow integration with ops that have a constant as their second
02691    operand.  */
02692       if ((REG_OR_SUBREG_REG (XEXP (x, 0))
02693      && ARM_FRAME_RTX (REG_OR_SUBREG_RTX (XEXP (x, 0)))
02694      && GET_CODE (XEXP (x, 1)) != CONST_INT)
02695     || (REG_OR_SUBREG_REG (XEXP (x, 0))
02696         && ARM_FRAME_RTX (REG_OR_SUBREG_RTX (XEXP (x, 0)))))
02697   extra_cost = 4;
02698 
02699       if (mode == DImode)
02700   return (4 + extra_cost + (REG_OR_SUBREG_REG (XEXP (x, 0)) ? 0 : 8)
02701     + ((REG_OR_SUBREG_REG (XEXP (x, 1))
02702         || (GET_CODE (XEXP (x, 1)) == CONST_INT
02703       && const_ok_for_op (INTVAL (XEXP (x, 1)), code)))
02704        ? 0 : 8));
02705 
02706       if (REG_OR_SUBREG_REG (XEXP (x, 0)))
02707   return (1 + (GET_CODE (XEXP (x, 1)) == CONST_INT ? 0 : extra_cost)
02708     + ((REG_OR_SUBREG_REG (XEXP (x, 1))
02709         || (GET_CODE (XEXP (x, 1)) == CONST_INT
02710       && const_ok_for_op (INTVAL (XEXP (x, 1)), code)))
02711        ? 0 : 4));
02712 
02713       else if (REG_OR_SUBREG_REG (XEXP (x, 1)))
02714   return (1 + extra_cost
02715     + ((((subcode = GET_CODE (XEXP (x, 0))) == ASHIFT
02716          || subcode == LSHIFTRT || subcode == ASHIFTRT
02717          || subcode == ROTATE || subcode == ROTATERT
02718          || (subcode == MULT
02719        && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
02720        && ((INTVAL (XEXP (XEXP (x, 0), 1)) &
02721             (INTVAL (XEXP (XEXP (x, 0), 1)) - 1)) == 0)))
02722         && (REG_OR_SUBREG_REG (XEXP (XEXP (x, 0), 0)))
02723         && ((REG_OR_SUBREG_REG (XEXP (XEXP (x, 0), 1)))
02724       || GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT))
02725        ? 0 : 4));
02726 
02727       return 8;
02728 
02729     case MULT:
02730       /* There is no point basing this on the tuning, since it is always the
02731    fast variant if it exists at all.  */
02732       if (arm_fast_multiply && mode == DImode
02733     && (GET_CODE (XEXP (x, 0)) == GET_CODE (XEXP (x, 1)))
02734     && (GET_CODE (XEXP (x, 0)) == ZERO_EXTEND
02735         || GET_CODE (XEXP (x, 0)) == SIGN_EXTEND))
02736   return 8;
02737 
02738       if (GET_MODE_CLASS (mode) == MODE_FLOAT
02739     || mode == DImode)
02740   return 30;
02741 
02742       if (GET_CODE (XEXP (x, 1)) == CONST_INT)
02743   {
02744     unsigned HOST_WIDE_INT i = (INTVAL (XEXP (x, 1))
02745               & (unsigned HOST_WIDE_INT) 0xffffffff);
02746     int add_cost = const_ok_for_arm (i) ? 4 : 8;
02747     int j;
02748     
02749     /* Tune as appropriate.  */ 
02750     int booth_unit_size = ((tune_flags & FL_FAST_MULT) ? 8 : 2);
02751     
02752     for (j = 0; i && j < 32; j += booth_unit_size)
02753       {
02754         i >>= booth_unit_size;
02755         add_cost += 2;
02756       }
02757 
02758     return add_cost;
02759   }
02760 
02761       return (((tune_flags & FL_FAST_MULT) ? 8 : 30)
02762         + (REG_OR_SUBREG_REG (XEXP (x, 0)) ? 0 : 4)
02763         + (REG_OR_SUBREG_REG (XEXP (x, 1)) ? 0 : 4));
02764 
02765     case TRUNCATE:
02766       if (arm_fast_multiply && mode == SImode
02767     && GET_CODE (XEXP (x, 0)) == LSHIFTRT
02768     && GET_CODE (XEXP (XEXP (x, 0), 0)) == MULT
02769     && (GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 0))
02770         == GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 1)))
02771     && (GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 0)) == ZERO_EXTEND
02772         || GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 0)) == SIGN_EXTEND))
02773   return 8;
02774       return 99;
02775 
02776     case NEG:
02777       if (GET_MODE_CLASS (mode) == MODE_FLOAT)
02778   return 4 + (REG_OR_SUBREG_REG (XEXP (x, 0)) ? 0 : 6);
02779       /* Fall through */
02780     case NOT:
02781       if (mode == DImode)
02782   return 4 + (REG_OR_SUBREG_REG (XEXP (x, 0)) ? 0 : 4);
02783 
02784       return 1 + (REG_OR_SUBREG_REG (XEXP (x, 0)) ? 0 : 4);
02785 
02786     case IF_THEN_ELSE:
02787       if (GET_CODE (XEXP (x, 1)) == PC || GET_CODE (XEXP (x, 2)) == PC)
02788   return 14;
02789       return 2;
02790 
02791     case COMPARE:
02792       return 1;
02793 
02794     case ABS:
02795       return 4 + (mode == DImode ? 4 : 0);
02796 
02797     case SIGN_EXTEND:
02798       if (GET_MODE (XEXP (x, 0)) == QImode)
02799   return (4 + (mode == DImode ? 4 : 0)
02800     + (GET_CODE (XEXP (x, 0)) == MEM ? 10 : 0));
02801       /* Fall through */
02802     case ZERO_EXTEND:
02803       switch (GET_MODE (XEXP (x, 0)))
02804   {
02805   case QImode:
02806     return (1 + (mode == DImode ? 4 : 0)
02807       + (GET_CODE (XEXP (x, 0)) == MEM ? 10 : 0));
02808 
02809   case HImode:
02810     return (4 + (mode == DImode ? 4 : 0)
02811       + (GET_CODE (XEXP (x, 0)) == MEM ? 10 : 0));
02812 
02813   case SImode:
02814     return (1 + (GET_CODE (XEXP (x, 0)) == MEM ? 10 : 0));
02815 
02816   default:
02817     break;
02818   }
02819       abort ();
02820 
02821     case CONST_INT:           
02822       if (const_ok_for_arm (INTVAL (x)))      
02823   return outer == SET ? 2 : -1;         
02824       else if (outer == AND                     
02825          && const_ok_for_arm (~INTVAL (x)))   
02826   return -1;                                    
02827       else if ((outer == COMPARE                
02828     || outer == PLUS || outer == MINUS)     
02829          && const_ok_for_arm (-INTVAL (x)))   
02830   return -1;                                    
02831       else                                            
02832   return 5;
02833       
02834     case CONST:               
02835     case LABEL_REF:           
02836     case SYMBOL_REF:            
02837       return 6;
02838       
02839     case CONST_DOUBLE:            
02840       if (const_double_rtx_ok_for_fpu (x))      
02841   return outer == SET ? 2 : -1;     
02842       else if ((outer == COMPARE || outer == PLUS)  
02843          && neg_const_double_rtx_ok_for_fpu (x))    
02844   return -1;            
02845       return 7;
02846       
02847     default:
02848       return 99;
02849     }
02850 }
02851 
02852 static int
02853 arm_adjust_cost (insn, link, dep, cost)
02854      rtx insn;
02855      rtx link;
02856      rtx dep;
02857      int cost;
02858 {
02859   rtx i_pat, d_pat;
02860 
02861   /* Some true dependencies can have a higher cost depending
02862      on precisely how certain input operands are used.  */
02863   if (arm_is_xscale
02864       && REG_NOTE_KIND (link) == 0
02865       && recog_memoized (insn) < 0
02866       && recog_memoized (dep) < 0)
02867     {
02868       int shift_opnum = get_attr_shift (insn);
02869       enum attr_type attr_type = get_attr_type (dep);
02870 
02871       /* If nonzero, SHIFT_OPNUM contains the operand number of a shifted
02872    operand for INSN.  If we have a shifted input operand and the
02873    instruction we depend on is another ALU instruction, then we may
02874    have to account for an additional stall.  */
02875       if (shift_opnum != 0 && attr_type == TYPE_NORMAL)
02876   {
02877     rtx shifted_operand;
02878     int opno;
02879     
02880     /* Get the shifted operand.  */
02881     extract_insn (insn);
02882     shifted_operand = recog_data.operand[shift_opnum];
02883 
02884     /* Iterate over all the operands in DEP.  If we write an operand
02885        that overlaps with SHIFTED_OPERAND, then we have increase the
02886        cost of this dependency.  */
02887     extract_insn (dep);
02888     preprocess_constraints ();
02889     for (opno = 0; opno < recog_data.n_operands; opno++)
02890       {
02891         /* We can ignore strict inputs.  */
02892         if (recog_data.operand_type[opno] == OP_IN)
02893     continue;
02894 
02895         if (reg_overlap_mentioned_p (recog_data.operand[opno],
02896              shifted_operand))
02897     return 2;
02898       }
02899   }
02900     }
02901 
02902   /* XXX This is not strictly true for the FPA.  */
02903   if (REG_NOTE_KIND (link) == REG_DEP_ANTI
02904       || REG_NOTE_KIND (link) == REG_DEP_OUTPUT)
02905     return 0;
02906 
02907   /* Call insns don't incur a stall, even if they follow a load.  */
02908   if (REG_NOTE_KIND (link) == 0
02909       && GET_CODE (insn) == CALL_INSN)
02910     return 1;
02911 
02912   if ((i_pat = single_set (insn)) != NULL
02913       && GET_CODE (SET_SRC (i_pat)) == MEM
02914       && (d_pat = single_set (dep)) != NULL
02915       && GET_CODE (SET_DEST (d_pat)) == MEM)
02916     {
02917       /* This is a load after a store, there is no conflict if the load reads
02918    from a cached area.  Assume that loads from the stack, and from the
02919    constant pool are cached, and that others will miss.  This is a 
02920    hack.  */
02921       
02922       if (CONSTANT_POOL_ADDRESS_P (XEXP (SET_SRC (i_pat), 0))
02923     || reg_mentioned_p (stack_pointer_rtx, XEXP (SET_SRC (i_pat), 0))
02924     || reg_mentioned_p (frame_pointer_rtx, XEXP (SET_SRC (i_pat), 0))
02925     || reg_mentioned_p (hard_frame_pointer_rtx, 
02926             XEXP (SET_SRC (i_pat), 0)))
02927   return 1;
02928     }
02929 
02930   return cost;
02931 }
02932 
02933 /* This code has been fixed for cross compilation.  */
02934 
02935 static int fpa_consts_inited = 0;
02936 
02937 static const char * const strings_fpa[8] =
02938 {
02939   "0",   "1",   "2",   "3",
02940   "4",   "5",   "0.5", "10"
02941 };
02942 
02943 static REAL_VALUE_TYPE values_fpa[8];
02944 
02945 static void
02946 init_fpa_table ()
02947 {
02948   int i;
02949   REAL_VALUE_TYPE r;
02950 
02951   for (i = 0; i < 8; i++)
02952     {
02953       r = REAL_VALUE_ATOF (strings_fpa[i], DFmode);
02954       values_fpa[i] = r;
02955     }
02956 
02957   fpa_consts_inited = 1;
02958 }
02959 
02960 /* Return TRUE if rtx X is a valid immediate FPU constant.  */
02961 
02962 int
02963 const_double_rtx_ok_for_fpu (x)
02964      rtx x;
02965 {
02966   REAL_VALUE_TYPE r;
02967   int i;
02968   
02969   if (!fpa_consts_inited)
02970     init_fpa_table ();
02971   
02972   REAL_VALUE_FROM_CONST_DOUBLE (r, x);
02973   if (REAL_VALUE_MINUS_ZERO (r))
02974     return 0;
02975 
02976   for (i = 0; i < 8; i++)
02977     if (REAL_VALUES_EQUAL (r, values_fpa[i]))
02978       return 1;
02979 
02980   return 0;
02981 }
02982 
02983 /* Return TRUE if rtx X is a valid immediate FPU constant.  */
02984 
02985 int
02986 neg_const_double_rtx_ok_for_fpu (x)
02987      rtx x;
02988 {
02989   REAL_VALUE_TYPE r;
02990   int i;
02991   
02992   if (!fpa_consts_inited)
02993     init_fpa_table ();
02994   
02995   REAL_VALUE_FROM_CONST_DOUBLE (r, x);
02996   r = REAL_VALUE_NEGATE (r);
02997   if (REAL_VALUE_MINUS_ZERO (r))
02998     return 0;
02999 
03000   for (i = 0; i < 8; i++)
03001     if (REAL_VALUES_EQUAL (r, values_fpa[i]))
03002       return 1;
03003 
03004   return 0;
03005 }
03006 
03007 /* Predicates for `match_operand' and `match_operator'.  */
03008 
03009 /* s_register_operand is the same as register_operand, but it doesn't accept
03010    (SUBREG (MEM)...).
03011 
03012    This function exists because at the time it was put in it led to better
03013    code.  SUBREG(MEM) always needs a reload in the places where
03014    s_register_operand is used, and this seemed to lead to excessive
03015    reloading.  */
03016 
03017 int
03018 s_register_operand (op, mode)
03019      rtx op;
03020      enum machine_mode mode;
03021 {
03022   if (GET_MODE (op) != mode && mode != VOIDmode)
03023     return 0;
03024 
03025   if (GET_CODE (op) == SUBREG)
03026     op = SUBREG_REG (op);
03027 
03028   /* We don't consider registers whose class is NO_REGS
03029      to be a register operand.  */
03030   /* XXX might have to check for lo regs only for thumb ??? */
03031   return (GET_CODE (op) == REG
03032     && (REGNO (op) >= FIRST_PSEUDO_REGISTER
03033         || REGNO_REG_CLASS (REGNO (op)) != NO_REGS));
03034 }
03035 
03036 /* A hard register operand (even before reload.  */
03037 
03038 int
03039 arm_hard_register_operand (op, mode)
03040      rtx op;
03041      enum machine_mode mode;
03042 {
03043   if (GET_MODE (op) != mode && mode != VOIDmode)
03044     return 0;
03045 
03046   return (GET_CODE (op) == REG
03047     && REGNO (op) < FIRST_PSEUDO_REGISTER);
03048 }
03049     
03050 /* Only accept reg, subreg(reg), const_int.  */
03051 
03052 int
03053 reg_or_int_operand (op, mode)
03054      rtx op;
03055      enum machine_mode mode;
03056 {
03057   if (GET_CODE (op) == CONST_INT)
03058     return 1;
03059 
03060   if (GET_MODE (op) != mode && mode != VOIDmode)
03061     return 0;
03062 
03063   if (GET_CODE (op) == SUBREG)
03064     op = SUBREG_REG (op);
03065 
03066   /* We don't consider registers whose class is NO_REGS
03067      to be a register operand.  */
03068   return (GET_CODE (op) == REG
03069     && (REGNO (op) >= FIRST_PSEUDO_REGISTER
03070         || REGNO_REG_CLASS (REGNO (op)) != NO_REGS));
03071 }
03072 
03073 /* Return 1 if OP is an item in memory, given that we are in reload.  */
03074 
03075 int
03076 arm_reload_memory_operand (op, mode)
03077      rtx op;
03078      enum machine_mode mode ATTRIBUTE_UNUSED;
03079 {
03080   int regno = true_regnum (op);
03081 
03082   return (!CONSTANT_P (op)
03083     && (regno == -1
03084         || (GET_CODE (op) == REG
03085       && REGNO (op) >= FIRST_PSEUDO_REGISTER)));
03086 }
03087 
03088 /* Return 1 if OP is a valid memory address, but not valid for a signed byte
03089    memory access (architecture V4).
03090    MODE is QImode if called when computing constraints, or VOIDmode when
03091    emitting patterns.  In this latter case we cannot use memory_operand()
03092    because it will fail on badly formed MEMs, which is precisly what we are
03093    trying to catch.  */
03094 
03095 int
03096 bad_signed_byte_operand (op, mode)
03097      rtx op;
03098      enum machine_mode mode ATTRIBUTE_UNUSED;
03099 {
03100 #if 0
03101   if ((mode == QImode && !memory_operand (op, mode)) || GET_CODE (op) != MEM)
03102     return 0;
03103 #endif
03104   if (GET_CODE (op) != MEM)
03105     return 0;
03106 
03107   op = XEXP (op, 0);
03108 
03109   /* A sum of anything more complex than reg + reg or reg + const is bad.  */
03110   if ((GET_CODE (op) == PLUS || GET_CODE (op) == MINUS)
03111       && (!s_register_operand (XEXP (op, 0), VOIDmode)
03112     || (!s_register_operand (XEXP (op, 1), VOIDmode)
03113         && GET_CODE (XEXP (op, 1)) != CONST_INT)))
03114     return 1;
03115 
03116   /* Big constants are also bad.  */
03117   if (GET_CODE (op) == PLUS && GET_CODE (XEXP (op, 1)) == CONST_INT
03118       && (INTVAL (XEXP (op, 1)) > 0xff
03119     || -INTVAL (XEXP (op, 1)) > 0xff))
03120     return 1;
03121 
03122   /* Everything else is good, or can will automatically be made so.  */
03123   return 0;
03124 }
03125 
03126 /* Return TRUE for valid operands for the rhs of an ARM instruction.  */
03127 
03128 int
03129 arm_rhs_operand (op, mode)
03130      rtx op;
03131      enum machine_mode mode;
03132 {
03133   return (s_register_operand (op, mode)
03134     || (GET_CODE (op) == CONST_INT && const_ok_for_arm (INTVAL (op))));
03135 }
03136 
03137 /* Return TRUE for valid operands for the
03138    rhs of an ARM instruction, or a load.  */
03139 
03140 int
03141 arm_rhsm_operand (op, mode)
03142      rtx op;
03143      enum machine_mode mode;
03144 {
03145   return (s_register_operand (op, mode)
03146     || (GET_CODE (op) == CONST_INT && const_ok_for_arm (INTVAL (op)))
03147     || memory_operand (op, mode));
03148 }
03149 
03150 /* Return TRUE for valid operands for the rhs of an ARM instruction, or if a
03151    constant that is valid when negated.  */
03152 
03153 int
03154 arm_add_operand (op, mode)
03155      rtx op;
03156      enum machine_mode mode;
03157 {
03158   if (TARGET_THUMB)
03159     return thumb_cmp_operand (op, mode);
03160   
03161   return (s_register_operand (op, mode)
03162     || (GET_CODE (op) == CONST_INT
03163         && (const_ok_for_arm (INTVAL (op))
03164       || const_ok_for_arm (-INTVAL (op)))));
03165 }
03166 
03167 int
03168 arm_not_operand (op, mode)
03169      rtx op;
03170      enum machine_mode mode;
03171 {
03172   return (s_register_operand (op, mode)
03173     || (GET_CODE (op) == CONST_INT
03174         && (const_ok_for_arm (INTVAL (op))
03175       || const_ok_for_arm (~INTVAL (op)))));
03176 }
03177 
03178 /* Return TRUE if the operand is a memory reference which contains an
03179    offsettable address.  */
03180 
03181 int
03182 offsettable_memory_operand (op, mode)
03183      rtx op;
03184      enum machine_mode mode;
03185 {
03186   if (mode == VOIDmode)
03187     mode = GET_MODE (op);
03188 
03189   return (mode == GET_MODE (op)
03190     && GET_CODE (op) == MEM
03191     && offsettable_address_p (reload_completed | reload_in_progress,
03192             mode, XEXP (op, 0)));
03193 }
03194 
03195 /* Return TRUE if the operand is a memory reference which is, or can be
03196    made word aligned by adjusting the offset.  */
03197 
03198 int
03199 alignable_memory_operand (op, mode)
03200      rtx op;
03201      enum machine_mode mode;
03202 {
03203   rtx reg;
03204 
03205   if (mode == VOIDmode)
03206     mode = GET_MODE (op);
03207 
03208   if (mode != GET_MODE (op) || GET_CODE (op) != MEM)
03209     return 0;
03210 
03211   op = XEXP (op, 0);
03212 
03213   return ((GET_CODE (reg = op) == REG
03214      || (GET_CODE (op) == SUBREG
03215          && GET_CODE (reg = SUBREG_REG (op)) == REG)
03216      || (GET_CODE (op) == PLUS
03217          && GET_CODE (XEXP (op, 1)) == CONST_INT
03218          && (GET_CODE (reg = XEXP (op, 0)) == REG
03219        || (GET_CODE (XEXP (op, 0)) == SUBREG
03220            && GET_CODE (reg = SUBREG_REG (XEXP (op, 0))) == REG))))
03221     && REGNO_POINTER_ALIGN (REGNO (reg)) >= 32);
03222 }
03223 
03224 /* Similar to s_register_operand, but does not allow hard integer 
03225    registers.  */
03226 
03227 int
03228 f_register_operand (op, mode)
03229      rtx op;
03230      enum machine_mode mode;
03231 {
03232   if (GET_MODE (op) != mode && mode != VOIDmode)
03233     return 0;
03234 
03235   if (GET_CODE (op) == SUBREG)
03236     op = SUBREG_REG (op);
03237 
03238   /* We don't consider registers whose class is NO_REGS
03239      to be a register operand.  */
03240   return (GET_CODE (op) == REG
03241     && (REGNO (op) >= FIRST_PSEUDO_REGISTER
03242         || REGNO_REG_CLASS (REGNO (op)) == FPU_REGS));
03243 }
03244 
03245 /* Return TRUE for valid operands for the rhs of an FPU instruction.  */
03246 
03247 int
03248 fpu_rhs_operand (op, mode)
03249      rtx op;
03250      enum machine_mode mode;
03251 {
03252   if (s_register_operand (op, mode))
03253     return TRUE;
03254 
03255   if (GET_MODE (op) != mode && mode != VOIDmode)
03256     return FALSE;
03257 
03258   if (GET_CODE (op) == CONST_DOUBLE)
03259     return const_double_rtx_ok_for_fpu (op);
03260 
03261   return FALSE;
03262 }
03263 
03264 int
03265 fpu_add_operand (op, mode)
03266      rtx op;
03267      enum machine_mode mode;
03268 {
03269   if (s_register_operand (op, mode))
03270     return TRUE;
03271 
03272   if (GET_MODE (op) != mode && mode != VOIDmode)
03273     return FALSE;
03274 
03275   if (GET_CODE (op) == CONST_DOUBLE)
03276     return (const_double_rtx_ok_for_fpu (op) 
03277       || neg_const_double_rtx_ok_for_fpu (op));
03278 
03279   return FALSE;
03280 }
03281 
03282 /* Return nonzero if OP is a constant power of two.  */
03283 
03284 int
03285 power_of_two_operand (op, mode)
03286      rtx op;
03287      enum machine_mode mode ATTRIBUTE_UNUSED;
03288 {
03289   if (GET_CODE (op) == CONST_INT)
03290     {
03291       HOST_WIDE_INT value = INTVAL (op);
03292 
03293       return value != 0  &&  (value & (value - 1)) == 0;
03294     }
03295 
03296   return FALSE;
03297 }
03298 
03299 /* Return TRUE for a valid operand of a DImode operation.
03300    Either: REG, SUBREG, CONST_DOUBLE or MEM(DImode_address).
03301    Note that this disallows MEM(REG+REG), but allows
03302    MEM(PRE/POST_INC/DEC(REG)).  */
03303 
03304 int
03305 di_operand (op, mode)
03306      rtx op;
03307      enum machine_mode mode;
03308 {
03309   if (s_register_operand (op, mode))
03310     return TRUE;
03311 
03312   if (mode != VOIDmode && GET_MODE (op) != VOIDmode && GET_MODE (op) != DImode)
03313     return FALSE;
03314 
03315   if (GET_CODE (op) == SUBREG)
03316     op = SUBREG_REG (op);
03317 
03318   switch (GET_CODE (op))
03319     {
03320     case CONST_DOUBLE:
03321     case CONST_INT:
03322       return TRUE;
03323 
03324     case MEM:
03325       return memory_address_p (DImode, XEXP (op, 0));
03326 
03327     default:
03328       return FALSE;
03329     }
03330 }
03331 
03332 /* Like di_operand, but don't accept constants.  */
03333 
03334 int
03335 nonimmediate_di_operand (op, mode)
03336      rtx op;
03337      enum machine_mode mode;
03338 {
03339   if (s_register_operand (op, mode))
03340     return TRUE;
03341 
03342   if (mode != VOIDmode && GET_MODE (op) != VOIDmode && GET_MODE (op) != DImode)
03343     return FALSE;
03344 
03345   if (GET_CODE (op) == SUBREG)
03346     op = SUBREG_REG (op);
03347 
03348   if (GET_CODE (op) == MEM)
03349     return memory_address_p (DImode, XEXP (op, 0));
03350 
03351   return FALSE;
03352 }
03353 
03354 /* Return TRUE for a valid operand of a DFmode operation when -msoft-float.
03355    Either: REG, SUBREG, CONST_DOUBLE or MEM(DImode_address).
03356    Note that this disallows MEM(REG+REG), but allows
03357    MEM(PRE/POST_INC/DEC(REG)).  */
03358 
03359 int
03360 soft_df_operand (op, mode)
03361      rtx op;
03362      enum machine_mode mode;
03363 {
03364   if (s_register_operand (op, mode))
03365     return TRUE;
03366 
03367   if (mode != VOIDmode && GET_MODE (op) != mode)
03368     return FALSE;
03369 
03370   if (GET_CODE (op) == SUBREG && CONSTANT_P (SUBREG_REG (op)))
03371     return FALSE;
03372   
03373   if (GET_CODE (op) == SUBREG)
03374     op = SUBREG_REG (op);
03375   
03376   switch (GET_CODE (op))
03377     {
03378     case CONST_DOUBLE:
03379       return TRUE;
03380 
03381     case MEM:
03382       return memory_address_p (DFmode, XEXP (op, 0));
03383 
03384     default:
03385       return FALSE;
03386     }
03387 }
03388 
03389 /* Like soft_df_operand, but don't accept constants.  */
03390 
03391 int
03392 nonimmediate_soft_df_operand (op, mode)
03393      rtx op;
03394      enum machine_mode mode;
03395 {
03396   if (s_register_operand (op, mode))
03397     return TRUE;
03398 
03399   if (mode != VOIDmode && GET_MODE (op) != mode)
03400     return FALSE;
03401 
03402   if (GET_CODE (op) == SUBREG)
03403     op = SUBREG_REG (op);
03404 
03405   if (GET_CODE (op) == MEM)
03406     return memory_address_p (DFmode, XEXP (op, 0));
03407   return FALSE;
03408 }
03409 
03410 /* Return TRUE for valid index operands.  */
03411 
03412 int
03413 index_operand (op, mode)
03414      rtx op;
03415      enum machine_mode mode;
03416 {
03417   return (s_register_operand (op, mode)
03418     || (immediate_operand (op, mode)
03419         && (GET_CODE (op) != CONST_INT
03420       || (INTVAL (op) < 4096 && INTVAL (op) > -4096))));
03421 }
03422 
03423 /* Return TRUE for valid shifts by a constant. This also accepts any
03424    power of two on the (somewhat overly relaxed) assumption that the
03425    shift operator in this case was a mult.  */
03426 
03427 int
03428 const_shift_operand (op, mode)
03429      rtx op;
03430      enum machine_mode mode;
03431 {
03432   return (power_of_two_operand (op, mode)
03433     || (immediate_operand (op, mode)
03434         && (GET_CODE (op) != CONST_INT
03435       || (INTVAL (op) < 32 && INTVAL (op) > 0))));
03436 }
03437 
03438 /* Return TRUE for arithmetic operators which can be combined with a multiply
03439    (shift).  */
03440 
03441 int
03442 shiftable_operator (x, mode)
03443      rtx x;
03444      enum machine_mode mode;
03445 {
03446   enum rtx_code code;
03447 
03448   if (GET_MODE (x) != mode)
03449     return FALSE;
03450 
03451   code = GET_CODE (x);
03452 
03453   return (code == PLUS || code == MINUS
03454     || code == IOR || code == XOR || code == AND);
03455 }
03456 
03457 /* Return TRUE for binary logical operators.  */
03458 
03459 int
03460 logical_binary_operator (x, mode)
03461      rtx x;
03462      enum machine_mode mode;
03463 {
03464   enum rtx_code code;
03465 
03466   if (GET_MODE (x) != mode)
03467     return FALSE;
03468 
03469   code = GET_CODE (x);
03470 
03471   return (code == IOR || code == XOR || code == AND);
03472 }
03473 
03474 /* Return TRUE for shift operators.  */
03475 
03476 int
03477 shift_operator (x, mode)
03478      rtx x;
03479      enum machine_mode mode;
03480 {
03481   enum rtx_code code;
03482 
03483   if (GET_MODE (x) != mode)
03484     return FALSE;
03485 
03486   code = GET_CODE (x);
03487 
03488   if (code == MULT)
03489     return power_of_two_operand (XEXP (x, 1), mode);
03490 
03491   return (code == ASHIFT || code == ASHIFTRT || code == LSHIFTRT
03492     || code == ROTATERT);
03493 }
03494 
03495 /* Return TRUE if x is EQ or NE.  */
03496 
03497 int
03498 equality_operator (x, mode)
03499      rtx x;
03500      enum machine_mode mode ATTRIBUTE_UNUSED;
03501 {
03502   return GET_CODE (x) == EQ || GET_CODE (x) == NE;
03503 }
03504 
03505 /* Return TRUE if x is a comparison operator other than LTGT or UNEQ.  */
03506 
03507 int
03508 arm_comparison_operator (x, mode)
03509      rtx x;
03510      enum machine_mode mode;
03511 {
03512   return (comparison_operator (x, mode)
03513     && GET_CODE (x) != LTGT
03514     && GET_CODE (x) != UNEQ);
03515 }
03516 
03517 /* Return TRUE for SMIN SMAX UMIN UMAX operators.  */
03518 
03519 int
03520 minmax_operator (x, mode)
03521      rtx x;
03522      enum machine_mode mode;
03523 {
03524   enum rtx_code code = GET_CODE (x);
03525 
03526   if (GET_MODE (x) != mode)
03527     return FALSE;
03528 
03529   return code == SMIN || code == SMAX || code == UMIN || code == UMAX;
03530 }
03531 
03532 /* Return TRUE if this is the condition code register, if we aren't given
03533    a mode, accept any class CCmode register.  */
03534 
03535 int
03536 cc_register (x, mode)
03537      rtx x;
03538      enum machine_mode mode;
03539 {
03540   if (mode == VOIDmode)
03541     {
03542       mode = GET_MODE (x);
03543       
03544       if (GET_MODE_CLASS (mode) != MODE_CC)
03545   return FALSE;
03546     }
03547 
03548   if (   GET_MODE (x) == mode
03549       && GET_CODE (x) == REG
03550       && REGNO    (x) == CC_REGNUM)
03551     return TRUE;
03552 
03553   return FALSE;
03554 }
03555 
03556 /* Return TRUE if this is the condition code register, if we aren't given
03557    a mode, accept any class CCmode register which indicates a dominance
03558    expression.  */
03559 
03560 int
03561 dominant_cc_register (x, mode)
03562      rtx x;
03563      enum machine_mode mode;
03564 {
03565   if (mode == VOIDmode)
03566     {
03567       mode = GET_MODE (x);
03568       
03569       if (GET_MODE_CLASS (mode) != MODE_CC)
03570   return FALSE;
03571     }
03572 
03573   if (   mode != CC_DNEmode && mode != CC_DEQmode
03574       && mode != CC_DLEmode && mode != CC_DLTmode
03575       && mode != CC_DGEmode && mode != CC_DGTmode
03576       && mode != CC_DLEUmode && mode != CC_DLTUmode
03577       && mode != CC_DGEUmode && mode != CC_DGTUmode)
03578     return FALSE;
03579 
03580   return cc_register (x, mode);
03581 }
03582 
03583 /* Return TRUE if X references a SYMBOL_REF.  */
03584 
03585 int
03586 symbol_mentioned_p (x)
03587      rtx x;
03588 {
03589   const char * fmt;
03590   int i;
03591 
03592   if (GET_CODE (x) == SYMBOL_REF)
03593     return 1;
03594 
03595   fmt = GET_RTX_FORMAT (GET_CODE (x));
03596   
03597   for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
03598     {
03599       if (fmt[i] == 'E')
03600   {
03601     int j;
03602 
03603     for (j = XVECLEN (x, i) - 1; j >= 0; j--)
03604       if (symbol_mentioned_p (XVECEXP (x, i, j)))
03605         return 1;
03606   }
03607       else if (fmt[i] == 'e' && symbol_mentioned_p (XEXP (x, i)))
03608   return 1;
03609     }
03610 
03611   return 0;
03612 }
03613 
03614 /* Return TRUE if X references a LABEL_REF.  */
03615 
03616 int
03617 label_mentioned_p (x)
03618      rtx x;
03619 {
03620   const char * fmt;
03621   int i;
03622 
03623   if (GET_CODE (x) == LABEL_REF)
03624     return 1;
03625 
03626   fmt = GET_RTX_FORMAT (GET_CODE (x));
03627   for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
03628     {
03629       if (fmt[i] == 'E')
03630   {
03631     int j;
03632 
03633     for (j = XVECLEN (x, i) - 1; j >= 0; j--)
03634       if (label_mentioned_p (XVECEXP (x, i, j)))
03635         return 1;
03636   }
03637       else if (fmt[i] == 'e' && label_mentioned_p (XEXP (x, i)))
03638   return 1;
03639     }
03640 
03641   return 0;
03642 }
03643 
03644 enum rtx_code
03645 minmax_code (x)
03646      rtx x;
03647 {
03648   enum rtx_code code = GET_CODE (x);
03649 
03650   if (code == SMAX)
03651     return GE;
03652   else if (code == SMIN)
03653     return LE;
03654   else if (code == UMIN)
03655     return LEU;
03656   else if (code == UMAX)
03657     return GEU;
03658 
03659   abort ();
03660 }
03661 
03662 /* Return 1 if memory locations are adjacent.  */
03663 
03664 int
03665 adjacent_mem_locations (a, b)
03666      rtx a, b;
03667 {
03668   if ((GET_CODE (XEXP (a, 0)) == REG
03669        || (GET_CODE (XEXP (a, 0)) == PLUS
03670      && GET_CODE (XEXP (XEXP (a, 0), 1)) == CONST_INT))
03671       && (GET_CODE (XEXP (b, 0)) == REG
03672     || (GET_CODE (XEXP (b, 0)) == PLUS
03673         && GET_CODE (XEXP (XEXP (b, 0), 1)) == CONST_INT)))
03674     {
03675       int val0 = 0, val1 = 0;
03676       int reg0, reg1;
03677   
03678       if (GET_CODE (XEXP (a, 0)) == PLUS)
03679         {
03680     reg0 = REGNO  (XEXP (XEXP (a, 0), 0));
03681     val0 = INTVAL (XEXP (XEXP (a, 0), 1));
03682         }
03683       else
03684   reg0 = REGNO (XEXP (a, 0));
03685 
03686       if (GET_CODE (XEXP (b, 0)) == PLUS)
03687         {
03688     reg1 = REGNO  (XEXP (XEXP (b, 0), 0));
03689     val1 = INTVAL (XEXP (XEXP (b, 0), 1));
03690         }
03691       else
03692   reg1 = REGNO (XEXP (b, 0));
03693 
03694       return (reg0 == reg1) && ((val1 - val0) == 4 || (val0 - val1) == 4);
03695     }
03696   return 0;
03697 }
03698 
03699 /* Return 1 if OP is a load multiple operation.  It is known to be
03700    parallel and the first section will be tested.  */
03701 
03702 int
03703 load_multiple_operation (op, mode)
03704      rtx op;
03705      enum machine_mode mode ATTRIBUTE_UNUSED;
03706 {
03707   HOST_WIDE_INT count = XVECLEN (op, 0);
03708   int dest_regno;
03709   rtx src_addr;
03710   HOST_WIDE_INT i = 1, base = 0;
03711   rtx elt;
03712 
03713   if (count <= 1
03714       || GET_CODE (XVECEXP (op, 0, 0)) != SET)
03715     return 0;
03716 
03717   /* Check to see if this might be a write-back.  */
03718   if (GET_CODE (SET_SRC (elt = XVECEXP (op, 0, 0))) == PLUS)
03719     {
03720       i++;
03721       base = 1;
03722 
03723       /* Now check it more carefully.  */
03724       if (GET_CODE (SET_DEST (elt)) != REG
03725           || GET_CODE (XEXP (SET_SRC (elt), 0)) != REG
03726           || REGNO (XEXP (SET_SRC (elt), 0)) != REGNO (SET_DEST (elt))
03727           || GET_CODE (XEXP (SET_SRC (elt), 1)) != CONST_INT
03728           || INTVAL (XEXP (SET_SRC (elt), 1)) != (count - 1) * 4)
03729         return 0;
03730     }
03731 
03732   /* Perform a quick check so we don't blow up below.  */
03733   if (count <= i
03734       || GET_CODE (XVECEXP (op, 0, i - 1)) != SET
03735       || GET_CODE (SET_DEST (XVECEXP (op, 0, i - 1))) != REG
03736       || GET_CODE (SET_SRC (XVECEXP (op, 0, i - 1))) != MEM)
03737     return 0;
03738 
03739   dest_regno = REGNO (SET_DEST (XVECEXP (op, 0, i - 1)));
03740   src_addr = XEXP (SET_SRC (XVECEXP (op, 0, i - 1)), 0);
03741 
03742   for (; i < count; i++)
03743     {
03744       elt = XVECEXP (op, 0, i);
03745 
03746       if (GET_CODE (elt) != SET
03747           || GET_CODE (SET_DEST (elt)) != REG
03748           || GET_MODE (SET_DEST (elt)) != SImode
03749           || REGNO (SET_DEST (elt)) != (unsigned int)(dest_regno + i - base)
03750           || GET_CODE (SET_SRC (elt)) != MEM
03751           || GET_MODE (SET_SRC (elt)) != SImode
03752           || GET_CODE (XEXP (SET_SRC (elt), 0)) != PLUS
03753           || !rtx_equal_p (XEXP (XEXP (SET_SRC (elt), 0), 0), src_addr)
03754           || GET_CODE (XEXP (XEXP (SET_SRC (elt), 0), 1)) != CONST_INT
03755           || INTVAL (XEXP (XEXP (SET_SRC (elt), 0), 1)) != (i - base) * 4)
03756         return 0;
03757     }
03758 
03759   return 1;
03760 }
03761 
03762 /* Return 1 if OP is a store multiple operation.  It is known to be
03763    parallel and the first section will be tested.  */
03764 
03765 int
03766 store_multiple_operation (op, mode)
03767      rtx op;
03768      enum machine_mode mode ATTRIBUTE_UNUSED;
03769 {
03770   HOST_WIDE_INT count = XVECLEN (op, 0);
03771   int src_regno;
03772   rtx dest_addr;
03773   HOST_WIDE_INT i = 1, base = 0;
03774   rtx elt;
03775 
03776   if (count <= 1
03777       || GET_CODE (XVECEXP (op, 0, 0)) != SET)
03778     return 0;
03779 
03780   /* Check to see if this might be a write-back.  */
03781   if (GET_CODE (SET_SRC (elt = XVECEXP (op, 0, 0))) == PLUS)
03782     {
03783       i++;
03784       base = 1;
03785 
03786       /* Now check it more carefully.  */
03787       if (GET_CODE (SET_DEST (elt)) != REG
03788           || GET_CODE (XEXP (SET_SRC (elt), 0)) != REG
03789           || REGNO (XEXP (SET_SRC (elt), 0)) != REGNO (SET_DEST (elt))
03790           || GET_CODE (XEXP (SET_SRC (elt), 1)) != CONST_INT
03791           || INTVAL (XEXP (SET_SRC (elt), 1)) != (count - 1) * 4)
03792         return 0;
03793     }
03794 
03795   /* Perform a quick check so we don't blow up below.  */
03796   if (count <= i
03797       || GET_CODE (XVECEXP (op, 0, i - 1)) != SET
03798       || GET_CODE (SET_DEST (XVECEXP (op, 0, i - 1))) != MEM
03799       || GET_CODE (SET_SRC (XVECEXP (op, 0, i - 1))) != REG)
03800     return 0;
03801 
03802   src_regno = REGNO (SET_SRC (XVECEXP (op, 0, i - 1)));
03803   dest_addr = XEXP (SET_DEST (XVECEXP (op, 0, i - 1)), 0);
03804 
03805   for (; i < count; i++)
03806     {
03807       elt = XVECEXP (op, 0, i);
03808 
03809       if (GET_CODE (elt) != SET
03810           || GET_CODE (SET_SRC (elt)) != REG
03811           || GET_MODE (SET_SRC (elt)) != SImode
03812           || REGNO (SET_SRC (elt)) != (unsigned int)(src_regno + i - base)
03813           || GET_CODE (SET_DEST (elt)) != MEM
03814           || GET_MODE (SET_DEST (elt)) != SImode
03815           || GET_CODE (XEXP (SET_DEST (elt), 0)) != PLUS
03816           || !rtx_equal_p (XEXP (XEXP (SET_DEST (elt), 0), 0), dest_addr)
03817           || GET_CODE (XEXP (XEXP (SET_DEST (elt), 0), 1)) != CONST_INT
03818           || INTVAL (XEXP (XEXP (SET_DEST (elt), 0), 1)) != (i - base) * 4)
03819         return 0;
03820     }
03821 
03822   return 1;
03823 }
03824 
03825 int
03826 load_multiple_sequence (operands, nops, regs, base, load_offset)
03827      rtx * operands;
03828      int nops;
03829      int * regs;
03830      int * base;
03831      HOST_WIDE_INT * load_offset;
03832 {
03833   int unsorted_regs[4];
03834   HOST_WIDE_INT unsorted_offsets[4];
03835   int order[4];
03836   int base_reg = -1;
03837   int i;
03838 
03839   /* Can only handle 2, 3, or 4 insns at present,
03840      though could be easily extended if required.  */
03841   if (nops < 2 || nops > 4)
03842     abort ();
03843 
03844   /* Loop over the operands and check that the memory references are
03845      suitable (ie immediate offsets from the same base register).  At
03846      the same time, extract the target register, and the memory
03847      offsets.  */
03848   for (i = 0; i < nops; i++)
03849     {
03850       rtx reg;
03851       rtx offset;
03852 
03853       /* Convert a subreg of a mem into the mem itself.  */
03854       if (GET_CODE (operands[nops + i]) == SUBREG)
03855   operands[nops + i] = alter_subreg (operands + (nops + i));
03856 
03857       if (GET_CODE (operands[nops + i]) != MEM)
03858   abort ();
03859 
03860       /* Don't reorder volatile memory references; it doesn't seem worth
03861    looking for the case where the order is ok anyway.  */
03862       if (MEM_VOLATILE_P (operands[nops + i]))
03863   return 0;
03864 
03865       offset = const0_rtx;
03866 
03867       if ((GET_CODE (reg = XEXP (operands[nops + i], 0)) == REG
03868      || (GET_CODE (reg) == SUBREG
03869          && GET_CODE (reg = SUBREG_REG (reg)) == REG))
03870     || (GET_CODE (XEXP (operands[nops + i], 0)) == PLUS
03871         && ((GET_CODE (reg = XEXP (XEXP (operands[nops + i], 0), 0))
03872        == REG)
03873       || (GET_CODE (reg) == SUBREG
03874           && GET_CODE (reg = SUBREG_REG (reg)) == REG))
03875         && (GET_CODE (offset = XEXP (XEXP (operands[nops + i], 0), 1))
03876       == CONST_INT)))
03877   {
03878     if (i == 0)
03879       {
03880         base_reg = REGNO (reg);
03881         unsorted_regs[0] = (GET_CODE (operands[i]) == REG
03882           ? REGNO (operands[i])
03883           : REGNO (SUBREG_REG (operands[i])));
03884         order[0] = 0;
03885       }
03886     else 
03887       {
03888         if (base_reg != (int) REGNO (reg))
03889     /* Not addressed from the same base register.  */
03890     return 0;
03891 
03892         unsorted_regs[i] = (GET_CODE (operands[i]) == REG
03893           ? REGNO (operands[i])
03894           : REGNO (SUBREG_REG (operands[i])));
03895         if (unsorted_regs[i] < unsorted_regs[order[0]])
03896     order[0] = i;
03897       }
03898 
03899     /* If it isn't an integer register, or if it overwrites the
03900        base register but isn't the last insn in the list, then
03901        we can't do this.  */
03902     if (unsorted_regs[i] < 0 || unsorted_regs[i] > 14
03903         || (i != nops - 1 && unsorted_regs[i] == base_reg))
03904       return 0;
03905 
03906     unsorted_offsets[i] = INTVAL (offset);
03907   }
03908       else
03909   /* Not a suitable memory address.  */
03910   return 0;
03911     }
03912 
03913   /* All the useful information has now been extracted from the
03914      operands into unsorted_regs and unsorted_offsets; additionally,
03915      order[0] has been set to the lowest numbered register in the
03916      list.  Sort the registers into order, and check that the memory
03917      offsets are ascending and adjacent.  */
03918 
03919   for (i = 1; i < nops; i++)
03920     {
03921       int j;
03922 
03923       order[i] = order[i - 1];
03924       for (j = 0; j < nops; j++)
03925   if (unsorted_regs[j] > unsorted_regs[order[i - 1]]
03926       && (order[i] == order[i - 1]
03927     || unsorted_regs[j] < unsorted_regs[order[i]]))
03928     order[i] = j;
03929 
03930       /* Have we found a suitable register? if not, one must be used more
03931    than once.  */
03932       if (order[i] == order[i - 1])
03933   return 0;
03934 
03935       /* Is the memory address adjacent and ascending? */
03936       if (unsorted_offsets[order[i]] != unsorted_offsets[order[i - 1]] + 4)
03937   return 0;
03938     }
03939 
03940   if (base)
03941     {
03942       *base = base_reg;
03943 
03944       for (i = 0; i < nops; i++)
03945   regs[i] = unsorted_regs[order[i]];
03946 
03947       *load_offset = unsorted_offsets[order[0]];
03948     }
03949 
03950   if (unsorted_offsets[order[0]] == 0)
03951     return 1; /* ldmia */
03952 
03953   if (unsorted_offsets[order[0]] == 4)
03954     return 2; /* ldmib */
03955 
03956   if (unsorted_offsets[order[nops - 1]] == 0)
03957     return 3; /* ldmda */
03958 
03959   if (unsorted_offsets[order[nops - 1]] == -4)
03960     return 4; /* ldmdb */
03961 
03962   /* For ARM8,9 & StrongARM, 2 ldr instructions are faster than an ldm
03963      if the offset isn't small enough.  The reason 2 ldrs are faster
03964      is because these ARMs are able to do more than one cache access
03965      in a single cycle.  The ARM9 and StrongARM have Harvard caches,
03966      whilst the ARM8 has a double bandwidth cache.  This means that
03967      these cores can do both an instruction fetch and a data fetch in
03968      a single cycle, so the trick of calculating the address into a
03969      scratch register (one of the result regs) and then doing a load
03970      multiple actually becomes slower (and no smaller in code size).
03971      That is the transformation
03972  
03973   ldr rd1, [rbase + offset]
03974   ldr rd2, [rbase + offset + 4]
03975  
03976      to
03977  
03978   add rd1, rbase, offset
03979   ldmia rd1, {rd1, rd2}
03980  
03981      produces worse code -- '3 cycles + any stalls on rd2' instead of
03982      '2 cycles + any stalls on rd2'.  On ARMs with only one cache
03983      access per cycle, the first sequence could never complete in less
03984      than 6 cycles, whereas the ldm sequence would only take 5 and
03985      would make better use of sequential accesses if not hitting the
03986      cache.
03987 
03988      We cheat here and test 'arm_ld_sched' which we currently know to
03989      only be true for the ARM8, ARM9 and StrongARM.  If this ever
03990      changes, then the test below needs to be reworked.  */
03991   if (nops == 2 && arm_ld_sched)
03992     return 0;
03993 
03994   /* Can't do it without setting up the offset, only do this if it takes
03995      no more than one insn.  */
03996   return (const_ok_for_arm (unsorted_offsets[order[0]]) 
03997     || const_ok_for_arm (-unsorted_offsets[order[0]])) ? 5 : 0;
03998 }
03999 
04000 const char *
04001 emit_ldm_seq (operands, nops)
04002      rtx * operands;
04003      int nops;
04004 {
04005   int regs[4];
04006   int base_reg;
04007   HOST_WIDE_INT offset;
04008   char buf[100];
04009   int i;
04010 
04011   switch (load_multiple_sequence (operands, nops, regs, &base_reg, &offset))
04012     {
04013     case 1:
04014       strcpy (buf, "ldm%?ia\t");
04015       break;
04016 
04017     case 2:
04018       strcpy (buf, "ldm%?ib\t");
04019       break;
04020 
04021     case 3:
04022       strcpy (buf, "ldm%?da\t");
04023       break;
04024 
04025     case 4:
04026       strcpy (buf, "ldm%?db\t");
04027       break;
04028 
04029     case 5:
04030       if (offset >= 0)
04031   sprintf (buf, "add%%?\t%s%s, %s%s, #%ld", REGISTER_PREFIX,
04032      reg_names[regs[0]], REGISTER_PREFIX, reg_names[base_reg],
04033      (long) offset);
04034       else
04035   sprintf (buf, "sub%%?\t%s%s, %s%s, #%ld", REGISTER_PREFIX,
04036      reg_names[regs[0]], REGISTER_PREFIX, reg_names[base_reg],
04037      (long) -offset);
04038       output_asm_insn (buf, operands);
04039       base_reg = regs[0];
04040       strcpy (buf, "ldm%?ia\t");
04041       break;
04042 
04043     default:
04044       abort ();
04045     }
04046 
04047   sprintf (buf + strlen (buf), "%s%s, {%s%s", REGISTER_PREFIX, 
04048      reg_names[base_reg], REGISTER_PREFIX, reg_names[regs[0]]);
04049 
04050   for (i = 1; i < nops; i++)
04051     sprintf (buf + strlen (buf), ", %s%s", REGISTER_PREFIX,
04052        reg_names[regs[i]]);
04053 
04054   strcat (buf, "}\t%@ phole ldm");
04055 
04056   output_asm_insn (buf, operands);
04057   return "";
04058 }
04059 
04060 int
04061 store_multiple_sequence (operands, nops, regs, base, load_offset)
04062      rtx * operands;
04063      int nops;
04064      int * regs;
04065      int * base;
04066      HOST_WIDE_INT * load_offset;
04067 {
04068   int unsorted_regs[4];
04069   HOST_WIDE_INT unsorted_offsets[4];
04070   int order[4];
04071   int base_reg = -1;
04072   int i;
04073 
04074   /* Can only handle 2, 3, or 4 insns at present, though could be easily
04075      extended if required.  */
04076   if (nops < 2 || nops > 4)
04077     abort ();
04078 
04079   /* Loop over the operands and check that the memory references are
04080      suitable (ie immediate offsets from the same base register).  At
04081      the same time, extract the target register, and the memory
04082      offsets.  */
04083   for (i = 0; i < nops; i++)
04084     {
04085       rtx reg;
04086       rtx offset;
04087 
04088       /* Convert a subreg of a mem into the mem itself.  */
04089       if (GET_CODE (operands[nops + i]) == SUBREG)
04090   operands[nops + i] = alter_subreg (operands + (nops + i));
04091 
04092       if (GET_CODE (operands[nops + i]) != MEM)
04093   abort ();
04094 
04095       /* Don't reorder volatile memory references; it doesn't seem worth
04096    looking for the case where the order is ok anyway.  */
04097       if (MEM_VOLATILE_P (operands[nops + i]))
04098   return 0;
04099 
04100       offset = const0_rtx;
04101 
04102       if ((GET_CODE (reg = XEXP (operands[nops + i], 0)) == REG
04103      || (GET_CODE (reg) == SUBREG
04104          && GET_CODE (reg = SUBREG_REG (reg)) == REG))
04105     || (GET_CODE (XEXP (operands[nops + i], 0)) == PLUS
04106         && ((GET_CODE (reg = XEXP (XEXP (operands[nops + i], 0), 0))
04107        == REG)
04108       || (GET_CODE (reg) == SUBREG
04109           && GET_CODE (reg = SUBREG_REG (reg)) == REG))
04110         && (GET_CODE (offset = XEXP (XEXP (operands[nops + i], 0), 1))
04111       == CONST_INT)))
04112   {
04113     if (i == 0)
04114       {
04115         base_reg = REGNO (reg);
04116         unsorted_regs[0] = (GET_CODE (operands[i]) == REG
04117           ? REGNO (operands[i])
04118           : REGNO (SUBREG_REG (operands[i])));
04119         order[0] = 0;
04120       }
04121     else 
04122       {
04123         if (base_reg != (int) REGNO (reg))
04124     /* Not addressed from the same base register.  */
04125     return 0;
04126 
04127         unsorted_regs[i] = (GET_CODE (operands[i]) == REG
04128           ? REGNO (operands[i])
04129           : REGNO (SUBREG_REG (operands[i])));
04130         if (unsorted_regs[i] < unsorted_regs[order[0]])
04131     order[0] = i;
04132       }
04133 
04134     /* If it isn't an integer register, then we can't do this.  */
04135     if (unsorted_regs[i] < 0 || unsorted_regs[i] > 14)
04136       return 0;
04137 
04138     unsorted_offsets[i] = INTVAL (offset);
04139   }
04140       else
04141   /* Not a suitable memory address.  */
04142   return 0;
04143     }
04144 
04145   /* All the useful information has now been extracted from the
04146      operands into unsorted_regs and unsorted_offsets; additionally,
04147      order[0] has been set to the lowest numbered register in the
04148      list.  Sort the registers into order, and check that the memory
04149      offsets are ascending and adjacent.  */
04150 
04151   for (i = 1; i < nops; i++)
04152     {
04153       int j;
04154 
04155       order[i] = order[i - 1];
04156       for (j = 0; j < nops; j++)
04157   if (unsorted_regs[j] > unsorted_regs[order[i - 1]]
04158       && (order[i] == order[i - 1]
04159     || unsorted_regs[j] < unsorted_regs[order[i]]))
04160     order[i] = j;
04161 
04162       /* Have we found a suitable register? if not, one must be used more
04163    than once.  */
04164       if (order[i] == order[i - 1])
04165   return 0;
04166 
04167       /* Is the memory address adjacent and ascending? */
04168       if (unsorted_offsets[order[i]] != unsorted_offsets[order[i - 1]] + 4)
04169   return 0;
04170     }
04171 
04172   if (base)
04173     {
04174       *base = base_reg;
04175 
04176       for (i = 0; i < nops; i++)
04177   regs[i] = unsorted_regs[order[i]];
04178 
04179       *load_offset = unsorted_offsets[order[0]];
04180     }
04181 
04182   if (unsorted_offsets[order[0]] == 0)
04183     return 1; /* stmia */
04184 
04185   if (unsorted_offsets[order[0]] == 4)
04186     return 2; /* stmib */
04187 
04188   if (unsorted_offsets[order[nops - 1]] == 0)
04189     return 3; /* stmda */
04190 
04191   if (unsorted_offsets[order[nops - 1]] == -4)
04192     return 4; /* stmdb */
04193 
04194   return 0;
04195 }
04196 
04197 const char *
04198 emit_stm_seq (operands, nops)
04199      rtx * operands;
04200      int nops;
04201 {
04202   int regs[4];
04203   int base_reg;
04204   HOST_WIDE_INT offset;
04205   char buf[100];
04206   int i;
04207 
04208   switch (store_multiple_sequence (operands, nops, regs, &base_reg, &offset))
04209     {
04210     case 1:
04211       strcpy (buf, "stm%?ia\t");
04212       break;
04213 
04214     case 2:
04215       strcpy (buf, "stm%?ib\t");
04216       break;
04217 
04218     case 3:
04219       strcpy (buf, "stm%?da\t");
04220       break;
04221 
04222     case 4:
04223       strcpy (buf, "stm%?db\t");
04224       break;
04225 
04226     default:
04227       abort ();
04228     }
04229 
04230   sprintf (buf + strlen (buf), "%s%s, {%s%s", REGISTER_PREFIX, 
04231      reg_names[base_reg], REGISTER_PREFIX, reg_names[regs[0]]);
04232 
04233   for (i = 1; i < nops; i++)
04234     sprintf (buf + strlen (buf), ", %s%s", REGISTER_PREFIX,
04235        reg_names[regs[i]]);
04236 
04237   strcat (buf, "}\t%@ phole stm");
04238 
04239   output_asm_insn (buf, operands);
04240   return "";
04241 }
04242 
04243 int
04244 multi_register_push (op, mode)
04245      rtx op;
04246      enum machine_mode mode ATTRIBUTE_UNUSED;
04247 {
04248   if (GET_CODE (op) != PARALLEL
04249       || (GET_CODE (XVECEXP (op, 0, 0)) != SET)
04250       || (GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != UNSPEC)
04251       || (XINT (SET_SRC (XVECEXP (op, 0, 0)), 1) != UNSPEC_PUSH_MULT))
04252     return 0;
04253 
04254   return 1;
04255 }
04256 
04257 /* Routines for use in generating RTL.  */
04258 
04259 rtx
04260 arm_gen_load_multiple (base_regno, count, from, up, write_back, unchanging_p,
04261            in_struct_p, scalar_p)
04262      int base_regno;
04263      int count;
04264      rtx from;
04265      int up;
04266      int write_back;
04267      int unchanging_p;
04268      int in_struct_p;
04269      int scalar_p;
04270 {
04271   int i = 0, j;
04272   rtx result;
04273   int sign = up ? 1 : -1;
04274   rtx mem;
04275 
04276   /* XScale has load-store double instructions, but they have stricter
04277      alignment requirements than load-store multiple, so we can not
04278      use them.
04279 
04280      For XScale ldm requires 2 + NREGS cycles to complete and blocks
04281      the pipeline until completion.
04282 
04283   NREGS   CYCLES
04284     1     3
04285     2     4
04286     3     5
04287     4     6
04288 
04289      An ldr instruction takes 1-3 cycles, but does not block the
04290      pipeline.
04291 
04292   NREGS   CYCLES
04293     1    1-3
04294     2    2-6
04295     3    3-9
04296     4    4-12
04297 
04298      Best case ldr will always win.  However, the more ldr instructions
04299      we issue, the less likely we are to be able to schedule them well.
04300      Using ldr instructions also increases code size.
04301 
04302      As a compromise, we use ldr for counts of 1 or 2 regs, and ldm
04303      for counts of 3 or 4 regs.  */
04304   if (arm_is_xscale && count <= 2 && ! optimize_size)
04305     {
04306       rtx seq;
04307       
04308       start_sequence ();
04309       
04310       for (i = 0; i < count; i++)
04311   {
04312     mem = gen_rtx_MEM (SImode, plus_constant (from, i * 4 * sign));
04313     RTX_UNCHANGING_P (mem) = unchanging_p;
04314     MEM_IN_STRUCT_P (mem) = in_struct_p;
04315     MEM_SCALAR_P (mem) = scalar_p;
04316     emit_move_insn (gen_rtx_REG (SImode, base_regno + i), mem);
04317   }
04318 
04319       if (write_back)
04320   emit_move_insn (from, plus_constant (from, count * 4 * sign));
04321 
04322       seq = gen_sequence ();
04323       end_sequence ();
04324       
04325       return seq;
04326     }
04327 
04328   result = gen_rtx_PARALLEL (VOIDmode,
04329            rtvec_alloc (count + (write_back ? 1 : 0)));
04330   if (write_back)
04331     {
04332       XVECEXP (result, 0, 0)
04333   = gen_rtx_SET (GET_MODE (from), from,
04334            plus_constant (from, count * 4 * sign));
04335       i = 1;
04336       count++;
04337     }
04338 
04339   for (j = 0; i < count; i++, j++)
04340     {
04341       mem = gen_rtx_MEM (SImode, plus_constant (from, j * 4 * sign));
04342       RTX_UNCHANGING_P (mem) = unchanging_p;
04343       MEM_IN_STRUCT_P (mem) = in_struct_p;
04344       MEM_SCALAR_P (mem) = scalar_p;
04345       XVECEXP (result, 0, i)
04346   = gen_rtx_SET (VOIDmode, gen_rtx_REG (SImode, base_regno + j), mem);
04347     }
04348 
04349   return result;
04350 }
04351 
04352 rtx
04353 arm_gen_store_multiple (base_regno, count, to, up, write_back, unchanging_p,
04354       in_struct_p, scalar_p)
04355      int base_regno;
04356      int count;
04357      rtx to;
04358      int up;
04359      int write_back;
04360      int unchanging_p;
04361      int in_struct_p;
04362      int scalar_p;
04363 {
04364   int i = 0, j;
04365   rtx result;
04366   int sign = up ? 1 : -1;
04367   rtx mem;
04368 
04369   /* See arm_gen_load_multiple for discussion of
04370      the pros/cons of ldm/stm usage for XScale.  */
04371   if (arm_is_xscale && count <= 2 && ! optimize_size)
04372     {
04373       rtx seq;
04374       
04375       start_sequence ();
04376       
04377       for (i = 0; i < count; i++)
04378   {
04379     mem = gen_rtx_MEM (SImode, plus_constant (to, i * 4 * sign));
04380     RTX_UNCHANGING_P (mem) = unchanging_p;
04381     MEM_IN_STRUCT_P (mem) = in_struct_p;
04382     MEM_SCALAR_P (mem) = scalar_p;
04383     emit_move_insn (mem, gen_rtx_REG (SImode, base_regno + i));
04384   }
04385 
04386       if (write_back)
04387   emit_move_insn (to, plus_constant (to, count * 4 * sign));
04388 
04389       seq = gen_sequence ();
04390       end_sequence ();
04391       
04392       return seq;
04393     }
04394 
04395   result = gen_rtx_PARALLEL (VOIDmode,
04396            rtvec_alloc (count + (write_back ? 1 : 0)));
04397   if (write_back)
04398     {
04399       XVECEXP (result, 0, 0)
04400   = gen_rtx_SET (GET_MODE (to), to,
04401            plus_constant (to, count * 4 * sign));
04402       i = 1;
04403       count++;
04404     }
04405 
04406   for (j = 0; i < count; i++, j++)
04407     {
04408       mem = gen_rtx_MEM (SImode, plus_constant (to, j * 4 * sign));
04409       RTX_UNCHANGING_P (mem) = unchanging_p;
04410       MEM_IN_STRUCT_P (mem) = in_struct_p;
04411       MEM_SCALAR_P (mem) = scalar_p;
04412 
04413       XVECEXP (result, 0, i)
04414   = gen_rtx_SET (VOIDmode, mem, gen_rtx_REG (SImode, base_regno + j));
04415     }
04416 
04417   return result;
04418 }
04419 
04420 int
04421 arm_gen_movstrqi (operands)
04422      rtx * operands;
04423 {
04424   HOST_WIDE_INT in_words_to_go, out_words_to_go, last_bytes;
04425   int i;
04426   rtx src, dst;
04427   rtx st_src, st_dst, fin_src, fin_dst;
04428   rtx part_bytes_reg = NULL;
04429   rtx mem;
04430   int dst_unchanging_p, dst_in_struct_p, src_unchanging_p, src_in_struct_p;
04431   int dst_scalar_p, src_scalar_p;
04432 
04433   if (GET_CODE (operands[2]) != CONST_INT
04434       || GET_CODE (operands[3]) != CONST_INT
04435       || INTVAL (operands[2]) > 64
04436       || INTVAL (operands[3]) & 3)
04437     return 0;
04438 
04439   st_dst = XEXP (operands[0], 0);
04440   st_src = XEXP (operands[1], 0);
04441 
04442   dst_unchanging_p = RTX_UNCHANGING_P (operands[0]);
04443   dst_in_struct_p = MEM_IN_STRUCT_P (operands[0]);
04444   dst_scalar_p = MEM_SCALAR_P (operands[0]);
04445   src_unchanging_p = RTX_UNCHANGING_P (operands[1]);
04446   src_in_struct_p = MEM_IN_STRUCT_P (operands[1]);
04447   src_scalar_p = MEM_SCALAR_P (operands[1]);
04448 
04449   fin_dst = dst = copy_to_mode_reg (SImode, st_dst);
04450   fin_src = src = copy_to_mode_reg (SImode, st_src);
04451 
04452   in_words_to_go = NUM_INTS (INTVAL (operands[2]));
04453   out_words_to_go = INTVAL (operands[2]) / 4;
04454   last_bytes = INTVAL (operands[2]) & 3;
04455 
04456   if (out_words_to_go != in_words_to_go && ((in_words_to_go - 1) & 3) != 0)
04457     part_bytes_reg = gen_rtx_REG (SImode, (in_words_to_go - 1) & 3);
04458 
04459   for (i = 0; in_words_to_go >= 2; i+=4)
04460     {
04461       if (in_words_to_go > 4)
04462   emit_insn (arm_gen_load_multiple (0, 4, src, TRUE, TRUE,
04463             src_unchanging_p,
04464             src_in_struct_p,
04465             src_scalar_p));
04466       else
04467   emit_insn (arm_gen_load_multiple (0, in_words_to_go, src, TRUE, 
04468             FALSE, src_unchanging_p,
04469             src_in_struct_p, src_scalar_p));
04470 
04471       if (out_words_to_go)
04472   {
04473     if (out_words_to_go > 4)
04474       emit_insn (arm_gen_store_multiple (0, 4, dst, TRUE, TRUE,
04475                  dst_unchanging_p,
04476                  dst_in_struct_p,
04477                  dst_scalar_p));
04478     else if (out_words_to_go != 1)
04479       emit_insn (arm_gen_store_multiple (0, out_words_to_go,
04480                  dst, TRUE, 
04481                  (last_bytes == 0
04482             ? FALSE : TRUE),
04483                  dst_unchanging_p,
04484                  dst_in_struct_p,
04485                  dst_scalar_p));
04486     else
04487       {
04488         mem = gen_rtx_MEM (SImode, dst);
04489         RTX_UNCHANGING_P (mem) = dst_unchanging_p;
04490         MEM_IN_STRUCT_P (mem) = dst_in_struct_p;
04491         MEM_SCALAR_P (mem) = dst_scalar_p;
04492         emit_move_insn (mem, gen_rtx_REG (SImode, 0));
04493         if (last_bytes != 0)
04494     emit_insn (gen_addsi3 (dst, dst, GEN_INT (4)));
04495       }
04496   }
04497 
04498       in_words_to_go -= in_words_to_go < 4 ? in_words_to_go : 4;
04499       out_words_to_go -= out_words_to_go < 4 ? out_words_to_go : 4;
04500     }
04501 
04502   /* OUT_WORDS_TO_GO will be zero here if there are byte stores to do.  */
04503   if (out_words_to_go)
04504     {
04505       rtx sreg;
04506       
04507       mem = gen_rtx_MEM (SImode, src);
04508       RTX_UNCHANGING_P (mem) = src_unchanging_p;
04509       MEM_IN_STRUCT_P (mem) = src_in_struct_p;
04510       MEM_SCALAR_P (mem) = src_scalar_p;
04511       emit_move_insn (sreg = gen_reg_rtx (SImode), mem);
04512       emit_move_insn (fin_src = gen_reg_rtx (SImode), plus_constant (src, 4));
04513       
04514       mem = gen_rtx_MEM (SImode, dst);
04515       RTX_UNCHANGING_P (mem) = dst_unchanging_p;
04516       MEM_IN_STRUCT_P (mem) = dst_in_struct_p;
04517       MEM_SCALAR_P (mem) = dst_scalar_p;
04518       emit_move_insn (mem, sreg);
04519       emit_move_insn (fin_dst = gen_reg_rtx (SImode), plus_constant (dst, 4));
04520       in_words_to_go--;
04521       
04522       if (in_words_to_go) /* Sanity check */
04523   abort ();
04524     }
04525 
04526   if (in_words_to_go)
04527     {
04528       if (in_words_to_go < 0)
04529   abort ();
04530 
04531       mem = gen_rtx_MEM (SImode, src);
04532       RTX_UNCHANGING_P (mem) = src_unchanging_p;
04533       MEM_IN_STRUCT_P (mem) = src_in_struct_p;
04534       MEM_SCALAR_P (mem) = src_scalar_p;
04535       part_bytes_reg = copy_to_mode_reg (SImode, mem);
04536     }
04537 
04538   if (last_bytes && part_bytes_reg == NULL)
04539     abort ();
04540 
04541   if (BYTES_BIG_ENDIAN && last_bytes)
04542     {
04543       rtx tmp = gen_reg_rtx (SImode);
04544 
04545       /* The bytes we want are in the top end of the word.  */
04546       emit_insn (gen_lshrsi3 (tmp, part_bytes_reg,
04547             GEN_INT (8 * (4 - last_bytes))));
04548       part_bytes_reg = tmp;
04549       
04550       while (last_bytes)
04551   {
04552     mem = gen_rtx_MEM (QImode, plus_constant (dst, last_bytes - 1));
04553     RTX_UNCHANGING_P (mem) = dst_unchanging_p;
04554     MEM_IN_STRUCT_P (mem) = dst_in_struct_p;
04555     MEM_SCALAR_P (mem) = dst_scalar_p;
04556     emit_move_insn (mem, gen_lowpart (QImode, part_bytes_reg));
04557 
04558     if (--last_bytes)
04559       {
04560         tmp = gen_reg_rtx (SImode);
04561         emit_insn (gen_lshrsi3 (tmp, part_bytes_reg, GEN_INT (8)));
04562         part_bytes_reg = tmp;
04563       }
04564   }
04565     
04566     }
04567   else
04568     {
04569       if (last_bytes > 1)
04570   {
04571     mem = gen_rtx_MEM (HImode, dst);
04572     RTX_UNCHANGING_P (mem) = dst_unchanging_p;
04573     MEM_IN_STRUCT_P (mem) = dst_in_struct_p;
04574     MEM_SCALAR_P (mem) = dst_scalar_p;
04575     emit_move_insn (mem, gen_lowpart (HImode, part_bytes_reg));
04576     last_bytes -= 2;
04577     if (last_bytes)
04578       {
04579         rtx tmp = gen_reg_rtx (SImode);
04580 
04581         emit_insn (gen_addsi3 (dst, dst, GEN_INT (2)));
04582         emit_insn (gen_lshrsi3 (tmp, part_bytes_reg, GEN_INT (16)));
04583         part_bytes_reg = tmp;
04584       }
04585   }
04586       
04587       if (last_bytes)
04588   {
04589     mem = gen_rtx_MEM (QImode, dst);
04590     RTX_UNCHANGING_P (mem) = dst_unchanging_p;
04591     MEM_IN_STRUCT_P (mem) = dst_in_struct_p;
04592     MEM_SCALAR_P (mem) = dst_scalar_p;
04593     emit_move_insn (mem, gen_lowpart (QImode, part_bytes_reg));
04594   }
04595     }
04596 
04597   return 1;
04598 }
04599 
04600 /* Generate a memory reference for a half word, such that it will be loaded
04601    into the top 16 bits of the word.  We can assume that the address is
04602    known to be alignable and of the form reg, or plus (reg, const).  */
04603 
04604 rtx
04605 arm_gen_rotated_half_load (memref)
04606      rtx memref;
04607 {
04608   HOST_WIDE_INT offset = 0;
04609   rtx base = XEXP (memref, 0);
04610 
04611   if (GET_CODE (base) == PLUS)
04612     {
04613       offset = INTVAL (XEXP (base, 1));
04614       base = XEXP (base, 0);
04615     }
04616 
04617   /* If we aren't allowed to generate unaligned addresses, then fail.  */
04618   if (TARGET_MMU_TRAPS
04619       && ((BYTES_BIG_ENDIAN ? 1 : 0) ^ ((offset & 2) == 0)))
04620     return NULL;
04621 
04622   base = gen_rtx_MEM (SImode, plus_constant (base, offset & ~2));
04623 
04624   if ((BYTES_BIG_ENDIAN ? 1 : 0) ^ ((offset & 2) == 2))
04625     return base;
04626 
04627   return gen_rtx_ROTATE (SImode, base, GEN_INT (16));
04628 }
04629 
04630 /* Select a dominance comparison mode if possible.  We support three forms.
04631    COND_OR == 0 => (X && Y) 
04632    COND_OR == 1 => ((! X( || Y)
04633    COND_OR == 2 => (X || Y) 
04634    If we are unable to support a dominance comparsison we return CC mode.  
04635    This will then fail to match for the RTL expressions that generate this
04636    call.  */
04637 
04638 static enum machine_mode
04639 select_dominance_cc_mode (x, y, cond_or)
04640      rtx x;
04641      rtx y;
04642      HOST_WIDE_INT cond_or;
04643 {
04644   enum rtx_code cond1, cond2;
04645   int swapped = 0;
04646 
04647   /* Currently we will probably get the wrong result if the individual
04648      comparisons are not simple.  This also ensures that it is safe to
04649      reverse a comparison if necessary.  */
04650   if ((arm_select_cc_mode (cond1 = GET_CODE (x), XEXP (x, 0), XEXP (x, 1))
04651        != CCmode)
04652       || (arm_select_cc_mode (cond2 = GET_CODE (y), XEXP (y, 0), XEXP (y, 1))
04653     != CCmode))
04654     return CCmode;
04655 
04656   /* The if_then_else variant of this tests the second condition if the
04657      first passes, but is true if the first fails.  Reverse the first
04658      condition to get a true "inclusive-or" expression.  */
04659   if (cond_or == 1)
04660     cond1 = reverse_condition (cond1);
04661 
04662   /* If the comparisons are not equal, and one doesn't dominate the other,
04663      then we can't do this.  */
04664   if (cond1 != cond2 
04665       && !comparison_dominates_p (cond1, cond2)
04666       && (swapped = 1, !comparison_dominates_p (cond2, cond1)))
04667     return CCmode;
04668 
04669   if (swapped)
04670     {
04671       enum rtx_code temp = cond1;
04672       cond1 = cond2;
04673       cond2 = temp;
04674     }
04675 
04676   switch (cond1)
04677     {
04678     case EQ:
04679       if (cond2 == EQ || !cond_or)
04680   return CC_DEQmode;
04681 
04682       switch (cond2)
04683   {
04684   case LE: return CC_DLEmode;
04685   case LEU: return CC_DLEUmode;
04686   case GE: return CC_DGEmode;
04687   case GEU: return CC_DGEUmode;
04688   default: break;
04689   }
04690 
04691       break;
04692 
04693     case LT:
04694       if (cond2 == LT || !cond_or)
04695   return CC_DLTmode;
04696       if (cond2 == LE)
04697   return CC_DLEmode;
04698       if (cond2 == NE)
04699   return CC_DNEmode;
04700       break;
04701 
04702     case GT:
04703       if (cond2 == GT || !cond_or)
04704   return CC_DGTmode;
04705       if (cond2 == GE)
04706   return CC_DGEmode;
04707       if (cond2 == NE)
04708   return CC_DNEmode;
04709       break;
04710       
04711     case LTU:
04712       if (cond2 == LTU || !cond_or)
04713   return CC_DLTUmode;
04714       if (cond2 == LEU)
04715   return CC_DLEUmode;
04716       if (cond2 == NE)
04717   return CC_DNEmode;
04718       break;
04719 
04720     case GTU:
04721       if (cond2 == GTU || !cond_or)
04722   return CC_DGTUmode;
04723       if (cond2 == GEU)
04724   return CC_DGEUmode;
04725       if (cond2 == NE)
04726   return CC_DNEmode;
04727       break;
04728 
04729     /* The remaining cases only occur when both comparisons are the
04730        same.  */
04731     case NE:
04732       return CC_DNEmode;
04733 
04734     case LE:
04735       return CC_DLEmode;
04736 
04737     case GE:
04738       return CC_DGEmode;
04739 
04740     case LEU:
04741       return CC_DLEUmode;
04742 
04743     case GEU:
04744       return CC_DGEUmode;
04745 
04746     default:
04747       break;
04748     }
04749 
04750   abort ();
04751 }
04752 
04753 enum machine_mode
04754 arm_select_cc_mode (op, x, y)
04755      enum rtx_code op;
04756      rtx x;
04757      rtx y;
04758 {
04759   /* All floating point compares return CCFP if it is an equality
04760      comparison, and CCFPE otherwise.  */
04761   if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
04762     {
04763       switch (op)
04764   {
04765   case EQ:
04766   case NE:
04767   case UNORDERED:
04768   case ORDERED:
04769   case UNLT:
04770   case UNLE:
04771   case UNGT:
04772   case UNGE:
04773   case UNEQ:
04774   case LTGT:
04775     return CCFPmode;
04776 
04777   case LT:
04778   case LE:
04779   case GT:
04780   case GE:
04781     return CCFPEmode;
04782 
04783   default:
04784     abort ();
04785   }
04786     }
04787   
04788   /* A compare with a shifted operand.  Because of canonicalization, the
04789      comparison will have to be swapped when we emit the assembler.  */
04790   if (GET_MODE (y) == SImode && GET_CODE (y) == REG
04791       && (GET_CODE (x) == ASHIFT || GET_CODE (x) == ASHIFTRT
04792     || GET_CODE (x) == LSHIFTRT || GET_CODE (x) == ROTATE
04793     || GET_CODE (x) == ROTATERT))
04794     return CC_SWPmode;
04795 
04796   /* This is a special case that is used by combine to allow a 
04797      comparison of a shifted byte load to be split into a zero-extend
04798      followed by a comparison of the shifted integer (only valid for
04799      equalities and unsigned inequalities).  */
04800   if (GET_MODE (x) == SImode
04801       && GET_CODE (x) == ASHIFT
04802       && GET_CODE (XEXP (x, 1)) == CONST_INT && INTVAL (XEXP (x, 1)) == 24
04803       && GET_CODE (XEXP (x, 0)) == SUBREG
04804       && GET_CODE (SUBREG_REG (XEXP (x, 0))) == MEM
04805       && GET_MODE (SUBREG_REG (XEXP (x, 0))) == QImode
04806       && (op == EQ || op == NE
04807     || op == GEU || op == GTU || op == LTU || op == LEU)
04808       && GET_CODE (y) == CONST_INT)
04809     return CC_Zmode;
04810 
04811   /* A construct for a conditional compare, if the false arm contains
04812      0, then both conditions must be true, otherwise either condition
04813      must be true.  Not all conditions are possible, so CCmode is
04814      returned if it can't be done.  */
04815   if (GET_CODE (x) == IF_THEN_ELSE
04816       && (XEXP (x, 2) == const0_rtx
04817     || XEXP (x, 2) == const1_rtx)
04818       && GET_RTX_CLASS (GET_CODE (XEXP (x, 0))) == '<'
04819       && GET_RTX_CLASS (GET_CODE (XEXP (x, 1))) == '<')
04820     return select_dominance_cc_mode (XEXP (x, 0), XEXP (x, 1), 
04821              INTVAL (XEXP (x, 2)));
04822 
04823   /* Alternate canonicalizations of the above.  These are somewhat cleaner.  */
04824   if (GET_CODE (x) == AND
04825       && GET_RTX_CLASS (GET_CODE (XEXP (x, 0))) == '<'
04826       && GET_RTX_CLASS (GET_CODE (XEXP (x, 1))) == '<')
04827     return select_dominance_cc_mode (XEXP (x, 0), XEXP (x, 1), 0);
04828 
04829   if (GET_CODE (x) == IOR
04830       && GET_RTX_CLASS (GET_CODE (XEXP (x, 0))) == '<'
04831       && GET_RTX_CLASS (GET_CODE (XEXP (x, 1))) == '<')
04832     return select_dominance_cc_mode (XEXP (x, 0), XEXP (x, 1), 2);
04833 
04834   /* An operation that sets the condition codes as a side-effect, the
04835      V flag is not set correctly, so we can only use comparisons where
04836      this doesn't matter.  (For LT and GE we can use "mi" and "pl"
04837      instead.  */
04838   if (GET_MODE (x) == SImode
04839       && y == const0_rtx
04840       && (op == EQ || op == NE || op == LT || op == GE)
04841       && (GET_CODE (x) == PLUS || GET_CODE (x) == MINUS
04842     || GET_CODE (x) == AND || GET_CODE (x) == IOR
04843     || GET_CODE (x) == XOR || GET_CODE (x) == MULT
04844     || GET_CODE (x) == NOT || GET_CODE (x) == NEG
04845     || GET_CODE (x) == LSHIFTRT
04846     || GET_CODE (x) == ASHIFT || GET_CODE (x) == ASHIFTRT
04847     || GET_CODE (x) == ROTATERT || GET_CODE (x) == ZERO_EXTRACT))
04848     return CC_NOOVmode;
04849 
04850   if (GET_MODE (x) == QImode && (op == EQ || op == NE))
04851     return CC_Zmode;
04852 
04853   if (GET_MODE (x) == SImode && (op == LTU || op == GEU)
04854       && GET_CODE (x) == PLUS
04855       && (rtx_equal_p (XEXP (x, 0), y) || rtx_equal_p (XEXP (x, 1), y)))
04856     return CC_Cmode;
04857 
04858   return CCmode;
04859 }
04860 
04861 /* X and Y are two things to compare using CODE.  Emit the compare insn and
04862    return the rtx for register 0 in the proper mode.  FP means this is a
04863    floating point compare: I don't think that it is needed on the arm.  */
04864 
04865 rtx
04866 arm_gen_compare_reg (code, x, y)
04867      enum rtx_code code;
04868      rtx x, y;
04869 {
04870   enum machine_mode mode = SELECT_CC_MODE (code, x, y);
04871   rtx cc_reg = gen_rtx_REG (mode, CC_REGNUM);
04872 
04873   emit_insn (gen_rtx_SET (VOIDmode, cc_reg,
04874         gen_rtx_COMPARE (mode, x, y)));
04875 
04876   return cc_reg;
04877 }
04878 
04879 void
04880 arm_reload_in_hi (operands)
04881      rtx * operands;
04882 {
04883   rtx ref = operands[1];
04884   rtx base, scratch;
04885   HOST_WIDE_INT offset = 0;
04886 
04887   if (GET_CODE (ref) == SUBREG)
04888     {
04889       offset = SUBREG_BYTE (ref);
04890       ref = SUBREG_REG (ref);
04891     }
04892 
04893   if (GET_CODE (ref) == REG)
04894     {
04895       /* We have a pseudo which has been spilt onto the stack; there
04896    are two cases here: the first where there is a simple
04897    stack-slot replacement and a second where the stack-slot is
04898    out of range, or is used as a subreg.  */
04899       if (reg_equiv_mem[REGNO (ref)])
04900   {
04901     ref = reg_equiv_mem[REGNO (ref)];
04902     base = find_replacement (&XEXP (ref, 0));
04903   }
04904       else
04905   /* The slot is out of range, or was dressed up in a SUBREG.  */
04906   base = reg_equiv_address[REGNO (ref)];
04907     }
04908   else
04909     base = find_replacement (&XEXP (ref, 0));
04910 
04911   /* Handle the case where the address is too complex to be offset by 1.  */
04912   if (GET_CODE (base) == MINUS
04913       || (GET_CODE (base) == PLUS && GET_CODE (XEXP (base, 1)) != CONST_INT))
04914     {
04915       rtx base_plus = gen_rtx_REG (SImode, REGNO (operands[2]) + 1);
04916 
04917       emit_insn (gen_rtx_SET (VOIDmode, base_plus, base));
04918       base = base_plus;
04919     }
04920   else if (GET_CODE (base) == PLUS)
04921     {
04922       /* The addend must be CONST_INT, or we would have dealt with it above.  */
04923       HOST_WIDE_INT hi, lo;
04924 
04925       offset += INTVAL (XEXP (base, 1));
04926       base = XEXP (base, 0);
04927 
04928       /* Rework the address into a legal sequence of insns.  */
04929       /* Valid range for lo is -4095 -> 4095 */
04930       lo = (offset >= 0
04931       ? (offset & 0xfff)
04932       : -((-offset) & 0xfff));
04933 
04934       /* Corner case, if lo is the max offset then we would be out of range
04935    once we have added the additional 1 below, so bump the msb into the
04936    pre-loading insn(s).  */
04937       if (lo == 4095)
04938   lo &= 0x7ff;
04939 
04940       hi = ((((offset - lo) & (HOST_WIDE_INT) 0xffffffff)
04941        ^ (HOST_WIDE_INT) 0x80000000)
04942       - (HOST_WIDE_INT) 0x80000000);
04943 
04944       if (hi + lo != offset)
04945   abort ();
04946 
04947       if (hi != 0)
04948   {
04949     rtx base_plus = gen_rtx_REG (SImode, REGNO (operands[2]) + 1);
04950 
04951     /* Get the base address; addsi3 knows how to handle constants
04952        that require more than one insn.  */
04953     emit_insn (gen_addsi3 (base_plus, base, GEN_INT (hi)));
04954     base = base_plus;
04955     offset = lo;
04956   }
04957     }
04958 
04959   scratch = gen_rtx_REG (SImode, REGNO (operands[2]));
04960   emit_insn (gen_zero_extendqisi2 (scratch,
04961            gen_rtx_MEM (QImode,
04962             plus_constant (base,
04963                      offset))));
04964   emit_insn (gen_zero_extendqisi2 (gen_rtx_SUBREG (SImode, operands[0], 0),
04965            gen_rtx_MEM (QImode, 
04966             plus_constant (base,
04967                      offset + 1))));
04968   if (!BYTES_BIG_ENDIAN)
04969     emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_SUBREG (SImode, operands[0], 0),
04970       gen_rtx_IOR (SImode, 
04971              gen_rtx_ASHIFT
04972              (SImode,
04973               gen_rtx_SUBREG (SImode, operands[0], 0),
04974               GEN_INT (8)),
04975              scratch)));
04976   else
04977     emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_SUBREG (SImode, operands[0], 0),
04978           gen_rtx_IOR (SImode, 
04979            gen_rtx_ASHIFT (SImode, scratch,
04980                GEN_INT (8)),
04981            gen_rtx_SUBREG (SImode, operands[0],
04982                0))));
04983 }
04984 
04985 /* Handle storing a half-word to memory during reload by synthesising as two
04986    byte stores.  Take care not to clobber the input values until after we
04987    have moved them somewhere safe.  This code assumes that if the DImode
04988    scratch in operands[2] overlaps either the input value or output address
04989    in some way, then that value must die in this insn (we absolutely need
04990    two scratch registers for some corner cases).  */
04991 
04992 void
04993 arm_reload_out_hi (operands)
04994      rtx * operands;
04995 {
04996   rtx ref = operands[0];
04997   rtx outval = operands[1];
04998   rtx base, scratch;
04999   HOST_WIDE_INT offset = 0;
05000 
05001   if (GET_CODE (ref) == SUBREG)
05002     {
05003       offset = SUBREG_BYTE (ref);
05004       ref = SUBREG_REG (ref);
05005     }
05006 
05007   if (GET_CODE (ref) == REG)
05008     {
05009       /* We have a pseudo which has been spilt onto the stack; there
05010    are two cases here: the first where there is a simple
05011    stack-slot replacement and a second where the stack-slot is
05012    out of range, or is used as a subreg.  */
05013       if (reg_equiv_mem[REGNO (ref)])
05014   {
05015     ref = reg_equiv_mem[REGNO (ref)];
05016     base = find_replacement (&XEXP (ref, 0));
05017   }
05018       else
05019   /* The slot is out of range, or was dressed up in a SUBREG.  */
05020   base = reg_equiv_address[REGNO (ref)];
05021     }
05022   else
05023     base = find_replacement (&XEXP (ref, 0));
05024 
05025   scratch = gen_rtx_REG (SImode, REGNO (operands[2]));
05026 
05027   /* Handle the case where the address is too complex to be offset by 1.  */
05028   if (GET_CODE (base) == MINUS
05029       || (GET_CODE (base) == PLUS && GET_CODE (XEXP (base, 1)) != CONST_INT))
05030     {
05031       rtx base_plus = gen_rtx_REG (SImode, REGNO (operands[2]) + 1);
05032 
05033       /* Be careful not to destroy OUTVAL.  */
05034       if (reg_overlap_mentioned_p (base_plus, outval))
05035   {
05036     /* Updating base_plus might destroy outval, see if we can
05037        swap the scratch and base_plus.  */
05038     if (!reg_overlap_mentioned_p (scratch, outval))
05039       {
05040         rtx tmp = scratch;
05041         scratch = base_plus;
05042         base_plus = tmp;
05043       }
05044     else
05045       {
05046         rtx scratch_hi = gen_rtx_REG (HImode, REGNO (operands[2]));
05047 
05048         /* Be conservative and copy OUTVAL into the scratch now,
05049      this should only be necessary if outval is a subreg
05050      of something larger than a word.  */
05051         /* XXX Might this clobber base?  I can't see how it can,
05052      since scratch is known to overlap with OUTVAL, and
05053      must be wider than a word.  */
05054         emit_insn (gen_movhi (scratch_hi, outval));
05055         outval = scratch_hi;
05056       }
05057   }
05058 
05059       emit_insn (gen_rtx_SET (VOIDmode, base_plus, base));
05060       base = base_plus;
05061     }
05062   else if (GET_CODE (base) == PLUS)
05063     {
05064       /* The addend must be CONST_INT, or we would have dealt with it above.  */
05065       HOST_WIDE_INT hi, lo;
05066 
05067       offset += INTVAL (XEXP (base, 1));
05068       base = XEXP (base, 0);
05069 
05070       /* Rework the address into a legal sequence of insns.  */
05071       /* Valid range for lo is -4095 -> 4095 */
05072       lo = (offset >= 0
05073       ? (offset & 0xfff)
05074       : -((-offset) & 0xfff));
05075 
05076       /* Corner case, if lo is the max offset then we would be out of range
05077    once we have added the additional 1 below, so bump the msb into the
05078    pre-loading insn(s).  */
05079       if (lo == 4095)
05080   lo &= 0x7ff;
05081 
05082       hi = ((((offset - lo) & (HOST_WIDE_INT) 0xffffffff)
05083        ^ (HOST_WIDE_INT) 0x80000000)
05084       - (HOST_WIDE_INT) 0x80000000);
05085 
05086       if (hi + lo != offset)
05087   abort ();
05088 
05089       if (hi != 0)
05090   {
05091     rtx base_plus = gen_rtx_REG (SImode, REGNO (operands[2]) + 1);
05092 
05093     /* Be careful not to destroy OUTVAL.  */
05094     if (reg_overlap_mentioned_p (base_plus, outval))
05095       {
05096         /* Updating base_plus might destroy outval, see if we
05097      can swap the scratch and base_plus.  */
05098         if (!reg_overlap_mentioned_p (scratch, outval))
05099     {
05100       rtx tmp = scratch;
05101       scratch = base_plus;
05102       base_plus = tmp;
05103     }
05104         else
05105     {
05106       rtx scratch_hi = gen_rtx_REG (HImode, REGNO (operands[2]));
05107 
05108       /* Be conservative and copy outval into scratch now,
05109          this should only be necessary if outval is a
05110          subreg of something larger than a word.  */
05111       /* XXX Might this clobber base?  I can't see how it
05112          can, since scratch is known to overlap with
05113          outval.  */
05114       emit_insn (gen_movhi (scratch_hi, outval));
05115       outval = scratch_hi;
05116     }
05117       }
05118 
05119     /* Get the base address; addsi3 knows how to handle constants
05120        that require more than one insn.  */
05121     emit_insn (gen_addsi3 (base_plus, base, GEN_INT (hi)));
05122     base = base_plus;
05123     offset = lo;
05124   }
05125     }
05126 
05127   if (BYTES_BIG_ENDIAN)
05128     {
05129       emit_insn (gen_movqi (gen_rtx_MEM (QImode, 
05130            plus_constant (base, offset + 1)),
05131           gen_lowpart (QImode, outval)));
05132       emit_insn (gen_lshrsi3 (scratch,
05133             gen_rtx_SUBREG (SImode, outval, 0),
05134             GEN_INT (8)));
05135       emit_insn (gen_movqi (gen_rtx_MEM (QImode, plus_constant (base, offset)),
05136           gen_lowpart (QImode, scratch)));
05137     }
05138   else
05139     {
05140       emit_insn (gen_movqi (gen_rtx_MEM (QImode, plus_constant (base, offset)),
05141           gen_lowpart (QImode, outval)));
05142       emit_insn (gen_lshrsi3 (scratch,
05143             gen_rtx_SUBREG (SImode, outval, 0),
05144             GEN_INT (8)));
05145       emit_insn (gen_movqi (gen_rtx_MEM (QImode,
05146            plus_constant (base, offset + 1)),
05147           gen_lowpart (QImode, scratch)));
05148     }
05149 }
05150 
05151 /* Print a symbolic form of X to the debug file, F.  */
05152 
05153 static void
05154 arm_print_value (f, x)
05155      FILE * f;
05156      rtx x;
05157 {
05158   switch (GET_CODE (x))
05159     {
05160     case CONST_INT:
05161       fprintf (f, HOST_WIDE_INT_PRINT_HEX, INTVAL (x));
05162       return;
05163 
05164     case CONST_DOUBLE:
05165       fprintf (f, "<0x%lx,0x%lx>", (long)XWINT (x, 2), (long)XWINT (x, 3));
05166       return;
05167 
05168     case CONST_STRING:
05169       fprintf (f, "\"%s\"", XSTR (x, 0));
05170       return;
05171 
05172     case SYMBOL_REF:
05173       fprintf (f, "`%s'", XSTR (x, 0));
05174       return;
05175 
05176     case LABEL_REF:
05177       fprintf (f, "L%d", INSN_UID (XEXP (x, 0)));
05178       return;
05179 
05180     case CONST:
05181       arm_print_value (f, XEXP (x, 0));
05182       return;
05183 
05184     case PLUS:
05185       arm_print_value (f, XEXP (x, 0));
05186       fprintf (f, "+");
05187       arm_print_value (f, XEXP (x, 1));
05188       return;
05189 
05190     case PC:
05191       fprintf (f, "pc");
05192       return;
05193 
05194     default:
05195       fprintf (f, "????");
05196       return;
05197     }
05198 }
05199 
05200 /* Routines for manipulation of the constant pool.  */
05201 
05202 /* Arm instructions cannot load a large constant directly into a
05203    register; they have to come from a pc relative load.  The constant
05204    must therefore be placed in the addressable range of the pc
05205    relative load.  Depending on the precise pc relative load
05206    instruction the range is somewhere between 256 bytes and 4k.  This
05207    means that we often have to dump a constant inside a function, and
05208    generate code to branch around it.
05209 
05210    It is important to minimize this, since the branches will slow
05211    things down and make the code larger.
05212 
05213    Normally we can hide the table after an existing unconditional
05214    branch so that there is no interruption of the flow, but in the
05215    worst case the code looks like this:
05216 
05217   ldr rn, L1
05218   ...
05219   b L2
05220   align
05221   L1: .long value
05222   L2:
05223   ...
05224 
05225   ldr rn, L3
05226   ...
05227   b L4
05228   align
05229   L3: .long value
05230   L4:
05231   ...
05232 
05233    We fix this by performing a scan after scheduling, which notices
05234    which instructions need to have their operands fetched from the
05235    constant table and builds the table.
05236 
05237    The algorithm starts by building a table of all the constants that
05238    need fixing up and all the natural barriers in the function (places
05239    where a constant table can be dropped without breaking the flow).
05240    For each fixup we note how far the pc-relative replacement will be
05241    able to reach and the offset of the instruction into the function.
05242 
05243    Having built the table we then group the fixes together to form
05244    tables that are as large as possible (subject to addressing
05245    constraints) and emit each table of constants after the last
05246    barrier that is within range of all the instructions in the group.
05247    If a group does not contain a barrier, then we forcibly create one
05248    by inserting a jump instruction into the flow.  Once the table has
05249    been inserted, the insns are then modified to reference the
05250    relevant entry in the pool.
05251 
05252    Possible enhancements to the algorithm (not implemented) are:
05253 
05254    1) For some processors and object formats, there may be benefit in
05255    aligning the pools to the start of cache lines; this alignment
05256    would need to be taken into account when calculating addressability
05257    of a pool.  */
05258 
05259 /* These typedefs are located at the start of this file, so that
05260    they can be used in the prototypes there.  This comment is to
05261    remind readers of that fact so that the following structures
05262    can be understood more easily.
05263 
05264      typedef struct minipool_node    Mnode;
05265      typedef struct minipool_fixup   Mfix;  */
05266 
05267 struct minipool_node
05268 {
05269   /* Doubly linked chain of entries.  */
05270   Mnode * next;
05271   Mnode * prev;
05272   /* The maximum offset into the code that this entry can be placed.  While
05273      pushing fixes for forward references, all entries are sorted in order
05274      of increasing max_address.  */
05275   HOST_WIDE_INT max_address;
05276   /* Similarly for an entry inserted for a backwards ref.  */
05277   HOST_WIDE_INT min_address;
05278   /* The number of fixes referencing this entry.  This can become zero
05279      if we "unpush" an entry.  In this case we ignore the entry when we
05280      come to emit the code.  */
05281   int refcount;
05282   /* The offset from the start of the minipool.  */
05283   HOST_WIDE_INT offset;
05284   /* The value in table.  */
05285   rtx value;
05286   /* The mode of value.  */
05287   enum machine_mode mode;
05288   int fix_size;
05289 };
05290 
05291 struct minipool_fixup
05292 {
05293   Mfix *            next;
05294   rtx               insn;
05295   HOST_WIDE_INT     address;
05296   rtx *             loc;
05297   enum machine_mode mode;
05298   int               fix_size;
05299   rtx               value;
05300   Mnode *           minipool;
05301   HOST_WIDE_INT     forwards;
05302   HOST_WIDE_INT     backwards;
05303 };
05304 
05305 /* Fixes less than a word need padding out to a word boundary.  */
05306 #define MINIPOOL_FIX_SIZE(mode) \
05307   (GET_MODE_SIZE ((mode)) >= 4 ? GET_MODE_SIZE ((mode)) : 4)
05308 
05309 static Mnode *  minipool_vector_head;
05310 static Mnode *  minipool_vector_tail;
05311 static rtx  minipool_vector_label;
05312 
05313 /* The linked list of all minipool fixes required for this function.  */
05314 Mfix *    minipool_fix_head;
05315 Mfix *    minipool_fix_tail;
05316 /* The fix entry for the current minipool, once it has been placed.  */
05317 Mfix *    minipool_barrier;
05318 
05319 /* Determines if INSN is the start of a jump table.  Returns the end
05320    of the TABLE or NULL_RTX.  */
05321 
05322 static rtx
05323 is_jump_table (insn)
05324      rtx insn;
05325 {
05326   rtx table;
05327   
05328   if (GET_CODE (insn) == JUMP_INSN
05329       && JUMP_LABEL (insn) != NULL
05330       && ((table = next_real_insn (JUMP_LABEL (insn)))
05331     == next_real_insn (insn))
05332       && table != NULL
05333       && GET_CODE (table) == JUMP_INSN
05334       && (GET_CODE (PATTERN (table)) == ADDR_VEC
05335     || GET_CODE (PATTERN (table)) == ADDR_DIFF_VEC))
05336     return table;
05337 
05338   return NULL_RTX;
05339 }
05340 
05341 #ifndef JUMP_TABLES_IN_TEXT_SECTION
05342 #define JUMP_TABLES_IN_TEXT_SECTION 0
05343 #endif
05344 
05345 static HOST_WIDE_INT
05346 get_jump_table_size (insn)
05347      rtx insn;
05348 {
05349   /* ADDR_VECs only take room if read-only data does into the text
05350      section.  */
05351   if (JUMP_TABLES_IN_TEXT_SECTION
05352 #if !defined(READONLY_DATA_SECTION)
05353       || 1
05354 #endif
05355       )
05356     {
05357       rtx body = PATTERN (insn);
05358       int elt = GET_CODE (body) == ADDR_DIFF_VEC ? 1 : 0;
05359 
05360       return GET_MODE_SIZE (GET_MODE (body)) * XVECLEN (body, elt);
05361     }
05362 
05363   return 0;
05364 }
05365 
05366 /* Move a minipool fix MP from its current location to before MAX_MP.
05367    If MAX_MP is NULL, then MP doesn't need moving, but the addressing
05368    contrains may need updating.  */
05369 
05370 static Mnode *
05371 move_minipool_fix_forward_ref (mp, max_mp, max_address)
05372      Mnode *       mp;
05373      Mnode *       max_mp;
05374      HOST_WIDE_INT max_address;
05375 {
05376   /* This should never be true and the code below assumes these are
05377      different.  */
05378   if (mp == max_mp)
05379     abort ();
05380 
05381   if (max_mp == NULL)
05382     {
05383       if (max_address < mp->max_address)
05384   mp->max_address = max_address;
05385     }
05386   else
05387     {
05388       if (max_address > max_mp->max_address - mp->fix_size)
05389   mp->max_address = max_mp->max_address - mp->fix_size;
05390       else
05391   mp->max_address = max_address;
05392 
05393       /* Unlink MP from its current position.  Since max_mp is non-null,
05394        mp->prev must be non-null.  */
05395       mp->prev->next = mp->next;
05396       if (mp->next != NULL)
05397   mp->next->prev = mp->prev;
05398       else
05399   minipool_vector_tail = mp->prev;
05400 
05401       /* Re-insert it before MAX_MP.  */
05402       mp->next = max_mp;
05403       mp->prev = max_mp->prev;
05404       max_mp->prev = mp;
05405       
05406       if (mp->prev != NULL)
05407   mp->prev->next = mp;
05408       else
05409   minipool_vector_head = mp;
05410     }
05411 
05412   /* Save the new entry.  */
05413   max_mp = mp;
05414 
05415   /* Scan over the preceding entries and adjust their addresses as
05416      required.  */
05417   while (mp->prev != NULL
05418    && mp->prev->max_address > mp->max_address - mp->prev->fix_size)
05419     {
05420       mp->prev->max_address = mp->max_address - mp->prev->fix_size;
05421       mp = mp->prev;
05422     }
05423 
05424   return max_mp;
05425 }
05426 
05427 /* Add a constant to the minipool for a forward reference.  Returns the
05428    node added or NULL if the constant will not fit in this pool.  */
05429 
05430 static Mnode *
05431 add_minipool_forward_ref (fix)
05432      Mfix * fix;
05433 {
05434   /* If set, max_mp is the first pool_entry that has a lower
05435      constraint than the one we are trying to add.  */
05436   Mnode *       max_mp = NULL;
05437   HOST_WIDE_INT max_address = fix->address + fix->forwards;
05438   Mnode *       mp;
05439   
05440   /* If this fix's address is greater than the address of the first
05441      entry, then we can't put the fix in this pool.  We subtract the
05442      size of the current fix to ensure that if the table is fully
05443      packed we still have enough room to insert this value by suffling
05444      the other fixes forwards.  */
05445   if (minipool_vector_head &&
05446       fix->address >= minipool_vector_head->max_address - fix->fix_size)
05447     return NULL;
05448 
05449   /* Scan the pool to see if a constant with the same value has
05450      already been added.  While we are doing this, also note the
05451      location where we must insert the constant if it doesn't already
05452      exist.  */
05453   for (mp = minipool_vector_head; mp != NULL; mp = mp->next)
05454     {
05455       if (GET_CODE (fix->value) == GET_CODE (mp->value)
05456     && fix->mode == mp->mode
05457     && (GET_CODE (fix->value) != CODE_LABEL
05458         || (CODE_LABEL_NUMBER (fix->value)
05459       == CODE_LABEL_NUMBER (mp->value)))
05460     && rtx_equal_p (fix->value, mp->value))
05461   {
05462     /* More than one fix references this entry.  */
05463     mp->refcount++;
05464     return move_minipool_fix_forward_ref (mp, max_mp, max_address);
05465   }
05466 
05467       /* Note the insertion point if necessary.  */
05468       if (max_mp == NULL
05469     && mp->max_address > max_address)
05470   max_mp = mp;
05471     }
05472 
05473   /* The value is not currently in the minipool, so we need to create
05474      a new entry for it.  If MAX_MP is NULL, the entry will be put on
05475      the end of the list since the placement is less constrained than
05476      any existing entry.  Otherwise, we insert the new fix before
05477      MAX_MP and, if neceesary, adjust the constraints on the other
05478      entries.  */
05479   mp = xmalloc (sizeof (* mp));
05480   mp->fix_size = fix->fix_size;
05481   mp->mode = fix->mode;
05482   mp->value = fix->value;
05483   mp->refcount = 1;
05484   /* Not yet required for a backwards ref.  */
05485   mp->min_address = -65536;
05486 
05487   if (max_mp == NULL)
05488     {
05489       mp->max_address = max_address;
05490       mp->next = NULL;
05491       mp->prev = minipool_vector_tail;
05492 
05493       if (mp->prev == NULL)
05494   {
05495     minipool_vector_head = mp;
05496     minipool_vector_label = gen_label_rtx ();
05497   }
05498       else
05499   mp->prev->next = mp;
05500 
05501       minipool_vector_tail = mp;
05502     }
05503   else
05504     {
05505       if (max_address > max_mp->max_address - mp->fix_size)
05506   mp->max_address = max_mp->max_address - mp->fix_size;
05507       else
05508   mp->max_address = max_address;
05509 
05510       mp->next = max_mp;
05511       mp->prev = max_mp->prev;
05512       max_mp->prev = mp;
05513       if (mp->prev != NULL)
05514   mp->prev->next = mp;
05515       else
05516   minipool_vector_head = mp;
05517     }
05518 
05519   /* Save the new entry.  */
05520   max_mp = mp;
05521 
05522   /* Scan over the preceding entries and adjust their addresses as
05523      required.  */
05524   while (mp->prev != NULL
05525    && mp->prev->max_address > mp->max_address - mp->prev->fix_size)
05526     {
05527       mp->prev->max_address = mp->max_address - mp->prev->fix_size;
05528       mp = mp->prev;
05529     }
05530 
05531   return max_mp;
05532 }
05533 
05534 static Mnode *
05535 move_minipool_fix_backward_ref (mp, min_mp, min_address)
05536      Mnode *        mp;
05537      Mnode *        min_mp;
05538      HOST_WIDE_INT  min_address;
05539 {
05540   HOST_WIDE_INT offset;
05541 
05542   /* This should never be true, and the code below assumes these are
05543      different.  */
05544   if (mp == min_mp)
05545     abort ();
05546 
05547   if (min_mp == NULL)
05548     {
05549       if (min_address > mp->min_address)
05550   mp->min_address = min_address;
05551     }
05552   else
05553     {
05554       /* We will adjust this below if it is too loose.  */
05555       mp->min_address = min_address;
05556 
05557       /* Unlink MP from its current position.  Since min_mp is non-null,
05558    mp->next must be non-null.  */
05559       mp->next->prev = mp->prev;
05560       if (mp->prev != NULL)
05561   mp->prev->next = mp->next;
05562       else
05563   minipool_vector_head = mp->next;
05564 
05565       /* Reinsert it after MIN_MP.  */
05566       mp->prev = min_mp;
05567       mp->next = min_mp->next;
05568       min_mp->next = mp;
05569       if (mp->next != NULL)
05570   mp->next->prev = mp;
05571       else
05572   minipool_vector_tail = mp;
05573     }
05574 
05575   min_mp = mp;
05576 
05577   offset = 0;
05578   for (mp = minipool_vector_head; mp != NULL; mp = mp->next)
05579     {
05580       mp->offset = offset;
05581       if (mp->refcount > 0)
05582   offset += mp->fix_size;
05583 
05584       if (mp->next && mp->next->min_address < mp->min_address + mp->fix_size)
05585   mp->next->min_address = mp->min_address + mp->fix_size;
05586     }
05587 
05588   return min_mp;
05589 }      
05590 
05591 /* Add a constant to the minipool for a backward reference.  Returns the
05592    node added or NULL if the constant will not fit in this pool.  
05593 
05594    Note that the code for insertion for a backwards reference can be
05595    somewhat confusing because the calculated offsets for each fix do
05596    not take into account the size of the pool (which is still under
05597    construction.  */
05598 
05599 static Mnode *
05600 add_minipool_backward_ref (fix)
05601      Mfix * fix;
05602 {
05603   /* If set, min_mp is the last pool_entry that has a lower constraint
05604      than the one we are trying to add.  */
05605   Mnode *        min_mp = NULL;
05606   /* This can be negative, since it is only a constraint.  */
05607   HOST_WIDE_INT  min_address = fix->address - fix->backwards;
05608   Mnode *        mp;
05609 
05610   /* If we can't reach the current pool from this insn, or if we can't
05611      insert this entry at the end of the pool without pushing other
05612      fixes out of range, then we don't try.  This ensures that we
05613      can't fail later on.  */
05614   if (min_address >= minipool_barrier->address
05615       || (minipool_vector_tail->min_address + fix->fix_size
05616     >= minipool_barrier->address))
05617     return NULL;
05618 
05619   /* Scan the pool to see if a constant with the same value has
05620      already been added.  While we are doing this, also note the
05621      location where we must insert the constant if it doesn't already
05622      exist.  */
05623   for (mp = minipool_vector_tail; mp != NULL; mp = mp->prev)
05624     {
05625       if (GET_CODE (fix->value) == GET_CODE (mp->value)
05626     && fix->mode == mp->mode
05627     && (GET_CODE (fix->value) != CODE_LABEL
05628         || (CODE_LABEL_NUMBER (fix->value)
05629       == CODE_LABEL_NUMBER (mp->value)))
05630     && rtx_equal_p (fix->value, mp->value)
05631     /* Check that there is enough slack to move this entry to the
05632        end of the table (this is conservative).  */
05633     && (mp->max_address 
05634         > (minipool_barrier->address 
05635      + minipool_vector_tail->offset
05636      + minipool_vector_tail->fix_size)))
05637   {
05638     mp->refcount++;
05639     return move_minipool_fix_backward_ref (mp, min_mp, min_address);
05640   }
05641 
05642       if (min_mp != NULL)
05643   mp->min_address += fix->fix_size;
05644       else
05645   {
05646     /* Note the insertion point if necessary.  */
05647     if (mp->min_address < min_address)
05648       min_mp = mp;
05649     else if (mp->max_address
05650        < minipool_barrier->address + mp->offset + fix->fix_size)
05651       {
05652         /* Inserting before this entry would push the fix beyond
05653      its maximum address (which can happen if we have
05654      re-located a forwards fix); force the new fix to come
05655      after it.  */
05656         min_mp = mp;
05657         min_address = mp->min_address + fix->fix_size;
05658       }
05659   }
05660     }
05661 
05662   /* We need to create a new entry.  */
05663   mp = xmalloc (sizeof (* mp));
05664   mp->fix_size = fix->fix_size;
05665   mp->mode = fix->mode;
05666   mp->value = fix->value;
05667   mp->refcount = 1;
05668   mp->max_address = minipool_barrier->address + 65536;
05669 
05670   mp->min_address = min_address;
05671 
05672   if (min_mp == NULL)
05673     {
05674       mp->prev = NULL;
05675       mp->next = minipool_vector_head;
05676 
05677       if (mp->next == NULL)
05678   {
05679     minipool_vector_tail = mp;
05680     minipool_vector_label = gen_label_rtx ();
05681   }
05682       else
05683   mp->next->prev = mp;
05684 
05685       minipool_vector_head = mp;
05686     }
05687   else
05688     {
05689       mp->next = min_mp->next;
05690       mp->prev = min_mp;
05691       min_mp->next = mp;
05692       
05693       if (mp->next != NULL)
05694   mp->next->prev = mp;
05695       else
05696   minipool_vector_tail = mp;
05697     }
05698 
05699   /* Save the new entry.  */
05700   min_mp = mp;
05701 
05702   if (mp->prev)
05703     mp = mp->prev;
05704   else
05705     mp->offset = 0;
05706 
05707   /* Scan over the following entries and adjust their offsets.  */
05708   while (mp->next != NULL)
05709     {
05710       if (mp->next->min_address < mp->min_address + mp->fix_size)
05711   mp->next->min_address = mp->min_address + mp->fix_size;
05712 
05713       if (mp->refcount)
05714   mp->next->offset = mp->offset + mp->fix_size;
05715       else
05716   mp->next->offset = mp->offset;
05717 
05718       mp = mp->next;
05719     }
05720 
05721   return min_mp;
05722 }
05723 
05724 static void
05725 assign_minipool_offsets (barrier)
05726      Mfix * barrier;
05727 {
05728   HOST_WIDE_INT offset = 0;
05729   Mnode * mp;
05730 
05731   minipool_barrier = barrier;
05732 
05733   for (mp = minipool_vector_head; mp != NULL; mp = mp->next)
05734     {
05735       mp->offset = offset;
05736       
05737       if (mp->refcount > 0)
05738   offset += mp->fix_size;
05739     }
05740 }
05741 
05742 /* Output the literal table */
05743 static void
05744 dump_minipool (scan)
05745      rtx scan;
05746 {
05747   Mnode * mp;
05748   Mnode * nmp;
05749 
05750   if (rtl_dump_file)
05751     fprintf (rtl_dump_file,
05752        ";; Emitting minipool after insn %u; address %ld\n",
05753        INSN_UID (scan), (unsigned long) minipool_barrier->address);
05754 
05755   scan = emit_label_after (gen_label_rtx (), scan);
05756   scan = emit_insn_after (gen_align_4 (), scan);
05757   scan = emit_label_after (minipool_vector_label, scan);
05758 
05759   for (mp = minipool_vector_head; mp != NULL; mp = nmp)
05760     {
05761       if (mp->refcount > 0)
05762   {
05763     if (rtl_dump_file)
05764       {
05765         fprintf (rtl_dump_file, 
05766            ";;  Offset %u, min %ld, max %ld ",
05767            (unsigned) mp->offset, (unsigned long) mp->min_address,
05768            (unsigned long) mp->max_address);
05769         arm_print_value (rtl_dump_file, mp->value);
05770         fputc ('\n', rtl_dump_file);
05771       }
05772 
05773     switch (mp->fix_size)
05774       {
05775 #ifdef HAVE_consttable_1
05776       case 1:
05777         scan = emit_insn_after (gen_consttable_1 (mp->value), scan);
05778         break;
05779 
05780 #endif
05781 #ifdef HAVE_consttable_2
05782       case 2:
05783         scan = emit_insn_after (gen_consttable_2 (mp->value), scan);
05784         break;
05785 
05786 #endif
05787 #ifdef HAVE_consttable_4
05788       case 4:
05789         scan = emit_insn_after (gen_consttable_4 (mp->value), scan);
05790         break;
05791 
05792 #endif
05793 #ifdef HAVE_consttable_8
05794       case 8:
05795         scan = emit_insn_after (gen_consttable_8 (mp->value), scan);
05796         break;
05797 
05798 #endif
05799       default:
05800         abort ();
05801         break;
05802       }
05803   }
05804 
05805       nmp = mp->next;
05806       free (mp);
05807     }
05808 
05809   minipool_vector_head = minipool_vector_tail = NULL;
05810   scan = emit_insn_after (gen_consttable_end (), scan);
05811   scan = emit_barrier_after (scan);
05812 }
05813 
05814 /* Return the cost of forcibly inserting a barrier after INSN.  */
05815 
05816 static int
05817 arm_barrier_cost (insn)
05818      rtx insn;
05819 {
05820   /* Basing the location of the pool on the loop depth is preferable,
05821      but at the moment, the basic block information seems to be
05822      corrupt by this stage of the compilation.  */
05823   int base_cost = 50;
05824   rtx next = next_nonnote_insn (insn);
05825 
05826   if (next != NULL && GET_CODE (next) == CODE_LABEL)
05827     base_cost -= 20;
05828 
05829   switch (GET_CODE (insn))
05830     {
05831     case CODE_LABEL:
05832       /* It will always be better to place the table before the label, rather
05833    than after it.  */
05834       return 50;  
05835 
05836     case INSN:
05837     case CALL_INSN:
05838       return base_cost;
05839 
05840     case JUMP_INSN:
05841       return base_cost - 10;
05842 
05843     default:
05844       return base_cost + 10;
05845     }
05846 }
05847 
05848 /* Find the best place in the insn stream in the range
05849    (FIX->address,MAX_ADDRESS) to forcibly insert a minipool barrier.
05850    Create the barrier by inserting a jump and add a new fix entry for
05851    it.  */
05852 
05853 static Mfix *
05854 create_fix_barrier (fix, max_address)
05855      Mfix * fix;
05856      HOST_WIDE_INT max_address;
05857 {
05858   HOST_WIDE_INT count = 0;
05859   rtx barrier;
05860   rtx from = fix->insn;
05861   rtx selected = from;
05862   int selected_cost;
05863   HOST_WIDE_INT selected_address;
05864   Mfix * new_fix;
05865   HOST_WIDE_INT max_count = max_address - fix->address;
05866   rtx label = gen_label_rtx ();
05867 
05868   selected_cost = arm_barrier_cost (from);
05869   selected_address = fix->address;
05870 
05871   while (from && count < max_count)
05872     {
05873       rtx tmp;
05874       int new_cost;
05875 
05876       /* This code shouldn't have been called if there was a natural barrier
05877    within range.  */
05878       if (GET_CODE (from) == BARRIER)
05879   abort ();
05880 
05881       /* Count the length of this insn.  */
05882       count += get_attr_length (from);
05883 
05884       /* If there is a jump table, add its length.  */
05885       tmp = is_jump_table (from);
05886       if (tmp != NULL)
05887   {
05888     count += get_jump_table_size (tmp);
05889 
05890     /* Jump tables aren't in a basic block, so base the cost on
05891        the dispatch insn.  If we select this location, we will
05892        still put the pool after the table.  */
05893     new_cost = arm_barrier_cost (from);
05894 
05895     if (count < max_count && new_cost <= selected_cost)
05896       {
05897         selected = tmp;
05898         selected_cost = new_cost;
05899         selected_address = fix->address + count;
05900       }
05901 
05902     /* Continue after the dispatch table.  */
05903     from = NEXT_INSN (tmp);
05904     continue;
05905   }
05906 
05907       new_cost = arm_barrier_cost (from);
05908       
05909       if (count < max_count && new_cost <= selected_cost)
05910   {
05911     selected = from;
05912     selected_cost = new_cost;
05913     selected_address = fix->address + count;
05914   }
05915 
05916       from = NEXT_INSN (from);
05917     }
05918 
05919   /* Create a new JUMP_INSN that branches around a barrier.  */
05920   from = emit_jump_insn_after (gen_jump (label), selected);
05921   JUMP_LABEL (from) = label;
05922   barrier = emit_barrier_after (from);
05923   emit_label_after (label, barrier);
05924 
05925   /* Create a minipool barrier entry for the new barrier.  */
05926   new_fix = (Mfix *) obstack_alloc (&minipool_obstack, sizeof (* new_fix));
05927   new_fix->insn = barrier;
05928   new_fix->address = selected_address;
05929   new_fix->next = fix->next;
05930   fix->next = new_fix;
05931 
05932   return new_fix;
05933 }
05934 
05935 /* Record that there is a natural barrier in the insn stream at
05936    ADDRESS.  */
05937 static void
05938 push_minipool_barrier (insn, address)
05939      rtx insn;
05940      HOST_WIDE_INT address;
05941 {
05942   Mfix * fix = (Mfix *) obstack_alloc (&minipool_obstack, sizeof (* fix));
05943 
05944   fix->insn = insn;
05945   fix->address = address;
05946 
05947   fix->next = NULL;
05948   if (minipool_fix_head != NULL)
05949     minipool_fix_tail->next = fix;
05950   else
05951     minipool_fix_head = fix;
05952 
05953   minipool_fix_tail = fix;
05954 }
05955 
05956 /* Record INSN, which will need fixing up to load a value from the
05957    minipool.  ADDRESS is the offset of the insn since the start of the
05958    function; LOC is a pointer to the part of the insn which requires
05959    fixing; VALUE is the constant that must be loaded, which is of type
05960    MODE.  */
05961 static void
05962 push_minipool_fix (insn, address, loc, mode, value)
05963      rtx insn;
05964      HOST_WIDE_INT address;
05965      rtx * loc;
05966      enum machine_mode mode;
05967      rtx value;
05968 {
05969   Mfix * fix = (Mfix *) obstack_alloc (&minipool_obstack, sizeof (* fix));
05970 
05971 #ifdef AOF_ASSEMBLER
05972   /* PIC symbol refereneces need to be converted into offsets into the
05973      based area.  */
05974   /* XXX This shouldn't be done here.  */
05975   if (flag_pic && GET_CODE (value) == SYMBOL_REF)
05976     value = aof_pic_entry (value);
05977 #endif /* AOF_ASSEMBLER */
05978 
05979   fix->insn = insn;
05980   fix->address = address;
05981   fix->loc = loc;
05982   fix->mode = mode;
05983   fix->fix_size = MINIPOOL_FIX_SIZE (mode);
05984   fix->value = value;
05985   fix->forwards = get_attr_pool_range (insn);
05986   fix->backwards = get_attr_neg_pool_range (insn);
05987   fix->minipool = NULL;
05988 
05989   /* If an insn doesn't have a range defined for it, then it isn't
05990      expecting to be reworked by this code.  Better to abort now than
05991      to generate duff assembly code.  */
05992   if (fix->forwards == 0 && fix->backwards == 0)
05993     abort ();
05994 
05995   if (rtl_dump_file)
05996     {
05997       fprintf (rtl_dump_file,
05998          ";; %smode fixup for i%d; addr %lu, range (%ld,%ld): ",
05999          GET_MODE_NAME (mode),
06000          INSN_UID (insn), (unsigned long) address, 
06001          -1 * (long)fix->backwards, (long)fix->forwards);
06002       arm_print_value (rtl_dump_file, fix->value);
06003       fprintf (rtl_dump_file, "\n");
06004     }
06005 
06006   /* Add it to the chain of fixes.  */
06007   fix->next = NULL;
06008   
06009   if (minipool_fix_head != NULL)
06010     minipool_fix_tail->next = fix;
06011   else
06012     minipool_fix_head = fix;
06013 
06014   minipool_fix_tail = fix;
06015 }
06016 
06017 /* Scan INSN and note any of its operands that need fixing.  */
06018 
06019 static void
06020 note_invalid_constants (insn, address)
06021      rtx insn;
06022      HOST_WIDE_INT address;
06023 {
06024   int opno;
06025 
06026   extract_insn (insn);
06027 
06028   if (!constrain_operands (1))
06029     fatal_insn_not_found (insn);
06030 
06031   /* Fill in recog_op_alt with information about the constraints of this
06032      insn.  */
06033   preprocess_constraints ();
06034 
06035   for (opno = 0; opno < recog_data.n_operands; opno++)
06036     {
06037       /* Things we need to fix can only occur in inputs.  */
06038       if (recog_data.operand_type[opno] != OP_IN)
06039   continue;
06040 
06041       /* If this alternative is a memory reference, then any mention
06042    of constants in this alternative is really to fool reload
06043    into allowing us to accept one there.  We need to fix them up
06044    now so that we output the right code.  */
06045       if (recog_op_alt[opno][which_alternative].memory_ok)
06046   {
06047     rtx op = recog_data.operand[opno];
06048 
06049     if (CONSTANT_P (op))
06050       push_minipool_fix (insn, address, recog_data.operand_loc[opno],
06051              recog_data.operand_mode[opno], op);
06052 #if 0
06053     /* RWE: Now we look correctly at the operands for the insn,
06054        this shouldn't be needed any more.  */
06055 #ifndef AOF_ASSEMBLER
06056     /* XXX Is this still needed?  */
06057     else if (GET_CODE (op) == UNSPEC && XINT (op, 1) == UNSPEC_PIC_SYM)
06058       push_minipool_fix (insn, address, recog_data.operand_loc[opno],
06059              recog_data.operand_mode[opno],
06060              XVECEXP (op, 0, 0));
06061 #endif
06062 #endif
06063     else if (GET_CODE (op) == MEM
06064        && GET_CODE (XEXP (op, 0)) == SYMBOL_REF
06065        && CONSTANT_POOL_ADDRESS_P (XEXP (op, 0)))
06066       push_minipool_fix (insn, address, recog_data.operand_loc[opno],
06067              recog_data.operand_mode[opno],
06068              get_pool_constant (XEXP (op, 0)));
06069   }
06070     }
06071 }
06072 
06073 void
06074 arm_reorg (first)
06075      rtx first;
06076 {
06077   rtx insn;
06078   HOST_WIDE_INT address = 0;
06079   Mfix * fix;
06080 
06081   minipool_fix_head = minipool_fix_tail = NULL;
06082 
06083   /* The first insn must always be a note, or the code below won't
06084      scan it properly.  */
06085   if (GET_CODE (first) != NOTE)
06086     abort ();
06087 
06088   /* Scan all the insns and record the operands that will need fixing.  */
06089   for (insn = next_nonnote_insn (first); insn; insn = next_nonnote_insn (insn))
06090     {
06091       if (GET_CODE (insn) == BARRIER)
06092   push_minipool_barrier (insn, address);
06093       else if (GET_CODE (insn) == INSN || GET_CODE (insn) == CALL_INSN
06094          || GET_CODE (insn) == JUMP_INSN)
06095   {
06096     rtx table;
06097 
06098     note_invalid_constants (insn, address);
06099     address += get_attr_length (insn);
06100 
06101     /* If the insn is a vector jump, add the size of the table
06102        and skip the table.  */
06103     if ((table = is_jump_table (insn)) != NULL)
06104       {
06105         address += get_jump_table_size (table);
06106         insn = table;
06107       }
06108   }
06109     }
06110 
06111   fix = minipool_fix_head;
06112   
06113   /* Now scan the fixups and perform the required changes.  */
06114   while (fix)
06115     {
06116       Mfix * ftmp;
06117       Mfix * fdel;
06118       Mfix *  last_added_fix;
06119       Mfix * last_barrier = NULL;
06120       Mfix * this_fix;
06121 
06122       /* Skip any further barriers before the next fix.  */
06123       while (fix && GET_CODE (fix->insn) == BARRIER)
06124   fix = fix->next;
06125 
06126       /* No more fixes.  */
06127       if (fix == NULL)
06128   break;
06129 
06130       last_added_fix = NULL;
06131 
06132       for (ftmp = fix; ftmp; ftmp = ftmp->next)
06133   {
06134     if (GET_CODE (ftmp->insn) == BARRIER)
06135       {
06136         if (ftmp->address >= minipool_vector_head->max_address)
06137     break;
06138 
06139         last_barrier = ftmp;
06140       }
06141     else if ((ftmp->minipool = add_minipool_forward_ref (ftmp)) == NULL)
06142       break;
06143 
06144     last_added_fix = ftmp;  /* Keep track of the last fix added.  */
06145   }
06146 
06147       /* If we found a barrier, drop back to that; any fixes that we
06148    could have reached but come after the barrier will now go in
06149    the next mini-pool.  */
06150       if (last_barrier != NULL)
06151   {
06152     /* Reduce the refcount for those fixes that won't go into this 
06153        pool after all.  */
06154     for (fdel = last_barrier->next;
06155          fdel && fdel != ftmp;
06156          fdel = fdel->next)
06157       {
06158         fdel->minipool->refcount--;
06159         fdel->minipool = NULL;
06160       }
06161 
06162     ftmp = last_barrier;
06163   }
06164       else
06165         {
06166     /* ftmp is first fix that we can't fit into this pool and
06167        there no natural barriers that we could use.  Insert a
06168        new barrier in the code somewhere between the previous
06169        fix and this one, and arrange to jump around it.  */
06170     HOST_WIDE_INT max_address;
06171 
06172     /* The last item on the list of fixes must be a barrier, so
06173        we can never run off the end of the list of fixes without
06174        last_barrier being set.  */
06175     if (ftmp == NULL)
06176       abort ();
06177 
06178     max_address = minipool_vector_head->max_address;
06179     /* Check that there isn't another fix that is in range that
06180        we couldn't fit into this pool because the pool was
06181        already too large: we need to put the pool before such an
06182        instruction.  */
06183     if (ftmp->address < max_address)
06184       max_address = ftmp->address;
06185 
06186     last_barrier = create_fix_barrier (last_added_fix, max_address);
06187   }
06188 
06189       assign_minipool_offsets (last_barrier);
06190 
06191       while (ftmp)
06192   {
06193     if (GET_CODE (ftmp->insn) != BARRIER
06194         && ((ftmp->minipool = add_minipool_backward_ref (ftmp))
06195       == NULL))
06196       break;
06197 
06198     ftmp = ftmp->next;
06199   }
06200 
06201       /* Scan over the fixes we have identified for this pool, fixing them
06202    up and adding the constants to the pool itself.  */
06203       for (this_fix = fix; this_fix && ftmp != this_fix;
06204      this_fix = this_fix->next)
06205   if (GET_CODE (this_fix->insn) != BARRIER)
06206     {
06207       rtx addr
06208         = plus_constant (gen_rtx_LABEL_REF (VOIDmode, 
06209               minipool_vector_label),
06210              this_fix->minipool->offset);
06211       *this_fix->loc = gen_rtx_MEM (this_fix->mode, addr);
06212     }
06213 
06214       dump_minipool (last_barrier->insn);
06215       fix = ftmp;
06216     }
06217 
06218   /* From now on we must synthesize any constants that we can't handle
06219      directly.  This can happen if the RTL gets split during final
06220      instruction generation.  */
06221   after_arm_reorg = 1;
06222 
06223   /* Free the minipool memory.  */
06224   obstack_free (&minipool_obstack, minipool_startobj);
06225 }
06226 
06227 /* Routines to output assembly language.  */
06228 
06229 /* If the rtx is the correct value then return the string of the number.
06230    In this way we can ensure that valid double constants are generated even
06231    when cross compiling.  */
06232 
06233 const char *
06234 fp_immediate_constant (x)
06235      rtx x;
06236 {
06237   REAL_VALUE_TYPE r;
06238   int i;
06239   
06240   if (!fpa_consts_inited)
06241     init_fpa_table ();
06242   
06243   REAL_VALUE_FROM_CONST_DOUBLE (r, x);
06244   for (i = 0; i < 8; i++)
06245     if (REAL_VALUES_EQUAL (r, values_fpa[i]))
06246       return strings_fpa[i];
06247 
06248   abort ();
06249 }
06250 
06251 /* As for fp_immediate_constant, but value is passed directly, not in rtx.  */
06252 
06253 static const char *
06254 fp_const_from_val (r)
06255      REAL_VALUE_TYPE * r;
06256 {
06257   int i;
06258 
06259   if (!fpa_consts_inited)
06260     init_fpa_table ();
06261 
06262   for (i = 0; i < 8; i++)
06263     if (REAL_VALUES_EQUAL (*r, values_fpa[i]))
06264       return strings_fpa[i];
06265 
06266   abort ();
06267 }
06268 
06269 /* Output the operands of a LDM/STM instruction to STREAM.
06270    MASK is the ARM register set mask of which only bits 0-15 are important.
06271    REG is the base register, either the frame pointer or the stack pointer,
06272    INSTR is the possibly suffixed load or store instruction.  */
06273 
06274 static void
06275 print_multi_reg (stream, instr, reg, mask)
06276      FILE * stream;
06277      const char * instr;
06278      int reg;
06279      int mask;
06280 {
06281   int i;
06282   int not_first = FALSE;
06283 
06284   fputc ('\t', stream);
06285   asm_fprintf (stream, instr, reg);
06286   fputs (", {", stream);
06287   
06288   for (i = 0; i <= LAST_ARM_REGNUM; i++)
06289     if (mask & (1 << i))
06290       {
06291   if (not_first)
06292     fprintf (stream, ", ");
06293   
06294   asm_fprintf (stream, "%r", i);
06295   not_first = TRUE;
06296       }
06297 
06298   fprintf (stream, "}%s\n", TARGET_APCS_32 ? "" : "^");
06299 }
06300 
06301 /* Output a 'call' insn.  */
06302 
06303 const char *
06304 output_call (operands)
06305      rtx * operands;
06306 {
06307   /* Handle calls to lr using ip (which may be clobbered in subr anyway).  */
06308 
06309   if (REGNO (operands[0]) == LR_REGNUM)
06310     {
06311       operands[0] = gen_rtx_REG (SImode, IP_REGNUM);
06312       output_asm_insn ("mov%?\t%0, %|lr", operands);
06313     }
06314   
06315   output_asm_insn ("mov%?\t%|lr, %|pc", operands);
06316   
06317   if (TARGET_INTERWORK)
06318     output_asm_insn ("bx%?\t%0", operands);
06319   else
06320     output_asm_insn ("mov%?\t%|pc, %0", operands);
06321   
06322   return "";
06323 }
06324 
06325 static int
06326 eliminate_lr2ip (x)
06327      rtx * x;
06328 {
06329   int something_changed = 0;
06330   rtx x0 = * x;
06331   int code = GET_CODE (x0);
06332   int i, j;
06333   const char * fmt;
06334   
06335   switch (code)
06336     {
06337     case REG:
06338       if (REGNO (x0) == LR_REGNUM)
06339         {
06340     *x = gen_rtx_REG (SImode, IP_REGNUM);
06341     return 1;
06342         }
06343       return 0;
06344     default:
06345       /* Scan through the sub-elements and change any references there.  */
06346       fmt = GET_RTX_FORMAT (code);
06347       
06348       for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
06349   if (fmt[i] == 'e')
06350     something_changed |= eliminate_lr2ip (&XEXP (x0, i));
06351   else if (fmt[i] == 'E')
06352     for (j = 0; j < XVECLEN (x0, i); j++)
06353       something_changed |= eliminate_lr2ip (&XVECEXP (x0, i, j));
06354       
06355       return something_changed;
06356     }
06357 }
06358   
06359 /* Output a 'call' insn that is a reference in memory.  */
06360 
06361 const char *
06362 output_call_mem (operands)
06363      rtx * operands;
06364 {
06365   operands[0] = copy_rtx (operands[0]); /* Be ultra careful.  */
06366   /* Handle calls using lr by using ip (which may be clobbered in subr anyway).  */
06367   if (eliminate_lr2ip (&operands[0]))
06368     output_asm_insn ("mov%?\t%|ip, %|lr", operands);
06369 
06370   if (TARGET_INTERWORK)
06371     {
06372       output_asm_insn ("ldr%?\t%|ip, %0", operands);
06373       output_asm_insn ("mov%?\t%|lr, %|pc", operands);
06374       output_asm_insn ("bx%?\t%|ip", operands);
06375     }
06376   else
06377     {
06378       output_asm_insn ("mov%?\t%|lr, %|pc", operands);
06379       output_asm_insn ("ldr%?\t%|pc, %0", operands);
06380     }
06381 
06382   return "";
06383 }
06384 
06385 
06386 /* Output a move from arm registers to an fpu registers.
06387    OPERANDS[0] is an fpu register.
06388    OPERANDS[1] is the first registers of an arm register pair.  */
06389 
06390 const char *
06391 output_mov_long_double_fpu_from_arm (operands)
06392      rtx * operands;
06393 {
06394   int arm_reg0 = REGNO (operands[1]);
06395   rtx ops[3];
06396 
06397   if (arm_reg0 == IP_REGNUM)
06398     abort ();
06399 
06400   ops[0] = gen_rtx_REG (SImode, arm_reg0);
06401   ops[1] = gen_rtx_REG (SImode, 1 + arm_reg0);
06402   ops[2] = gen_rtx_REG (SImode, 2 + arm_reg0);
06403   
06404   output_asm_insn ("stm%?fd\t%|sp!, {%0, %1, %2}", ops);
06405   output_asm_insn ("ldf%?e\t%0, [%|sp], #12", operands);
06406   
06407   return "";
06408 }
06409 
06410 /* Output a move from an fpu register to arm registers.
06411    OPERANDS[0] is the first registers of an arm register pair.
06412    OPERANDS[1] is an fpu register.  */
06413 
06414 const char *
06415 output_mov_long_double_arm_from_fpu (operands)
06416      rtx * operands;
06417 {
06418   int arm_reg0 = REGNO (operands[0]);
06419   rtx ops[3];
06420 
06421   if (arm_reg0 == IP_REGNUM)
06422     abort ();
06423 
06424   ops[0] = gen_rtx_REG (SImode, arm_reg0);
06425   ops[1] = gen_rtx_REG (SImode, 1 + arm_reg0);
06426   ops[2] = gen_rtx_REG (SImode, 2 + arm_reg0);
06427 
06428   output_asm_insn ("stf%?e\t%1, [%|sp, #-12]!", operands);
06429   output_asm_insn ("ldm%?fd\t%|sp!, {%0, %1, %2}", ops);
06430   return "";
06431 }
06432 
06433 /* Output a move from arm registers to arm registers of a long double
06434    OPERANDS[0] is the destination.
06435    OPERANDS[1] is the source.  */
06436 
06437 const char *
06438 output_mov_long_double_arm_from_arm (operands)
06439      rtx * operands;
06440 {
06441   /* We have to be careful here because the two might overlap.  */
06442   int dest_start = REGNO (operands[0]);
06443   int src_start = REGNO (operands[1]);
06444   rtx ops[2];
06445   int i;
06446 
06447   if (dest_start < src_start)
06448     {
06449       for (i = 0; i < 3; i++)
06450   {
06451     ops[0] = gen_rtx_REG (SImode, dest_start + i);
06452     ops[1] = gen_rtx_REG (SImode, src_start + i);
06453     output_asm_insn ("mov%?\t%0, %1", ops);
06454   }
06455     }
06456   else
06457     {
06458       for (i = 2; i >= 0; i--)
06459   {
06460     ops[0] = gen_rtx_REG (SImode, dest_start + i);
06461     ops[1] = gen_rtx_REG (SImode, src_start + i);
06462     output_asm_insn ("mov%?\t%0, %1", ops);
06463   }
06464     }
06465 
06466   return "";
06467 }
06468 
06469 
06470 /* Output a move from arm registers to an fpu registers.
06471    OPERANDS[0] is an fpu register.
06472    OPERANDS[1] is the first registers of an arm register pair.  */
06473 
06474 const char *
06475 output_mov_double_fpu_from_arm (operands)
06476      rtx * operands;
06477 {
06478   int arm_reg0 = REGNO (operands[1]);
06479   rtx ops[2];
06480 
06481   if (arm_reg0 == IP_REGNUM)
06482     abort ();
06483   
06484   ops[0] = gen_rtx_REG (SImode, arm_reg0);
06485   ops[1] = gen_rtx_REG (SImode, 1 + arm_reg0);
06486   output_asm_insn ("stm%?fd\t%|sp!, {%0, %1}", ops);
06487   output_asm_insn ("ldf%?d\t%0, [%|sp], #8", operands);
06488   return "";
06489 }
06490 
06491 /* Output a move from an fpu register to arm registers.
06492    OPERANDS[0] is the first registers of an arm register pair.
06493    OPERANDS[1] is an fpu register.  */
06494 
06495 const char *
06496 output_mov_double_arm_from_fpu (operands)
06497      rtx * operands;
06498 {
06499   int arm_reg0 = REGNO (operands[0]);
06500   rtx ops[2];
06501 
06502   if (arm_reg0 == IP_REGNUM)
06503     abort ();
06504 
06505   ops[0] = gen_rtx_REG (SImode, arm_reg0);
06506   ops[1] = gen_rtx_REG (SImode, 1 + arm_reg0);
06507   output_asm_insn ("stf%?d\t%1, [%|sp, #-8]!", operands);
06508   output_asm_insn ("ldm%?fd\t%|sp!, {%0, %1}", ops);
06509   return "";
06510 }
06511 
06512 /* Output a move between double words.
06513    It must be REG<-REG, REG<-CONST_DOUBLE, REG<-CONST_INT, REG<-MEM
06514    or MEM<-REG and all MEMs must be offsettable addresses.  */
06515 
06516 const char *
06517 output_move_double (operands)
06518      rtx * operands;
06519 {
06520   enum rtx_code code0 = GET_CODE (operands[0]);
06521   enum rtx_code code1 = GET_CODE (operands[1]);
06522   rtx otherops[3];
06523 
06524   if (code0 == REG)
06525     {
06526       int reg0 = REGNO (operands[0]);
06527 
06528       otherops[0] = gen_rtx_REG (SImode, 1 + reg0);
06529       
06530       if (code1 == REG)
06531   {
06532     int reg1 = REGNO (operands[1]);
06533     if (reg1 == IP_REGNUM)
06534       abort ();
06535 
06536     /* Ensure the second source is not overwritten.  */
06537     if (reg1 == reg0 + (WORDS_BIG_ENDIAN ? -1 : 1))
06538       output_asm_insn ("mov%?\t%Q0, %Q1\n\tmov%?\t%R0, %R1", operands);
06539     else
06540       output_asm_insn ("mov%?\t%R0, %R1\n\tmov%?\t%Q0, %Q1", operands);
06541   }
06542       else if (code1 == CONST_DOUBLE)
06543   {
06544     if (GET_MODE (operands[1]) == DFmode)
06545       {
06546         long l[2];
06547         union real_extract u;
06548 
06549         memcpy (&u, &CONST_DOUBLE_LOW (operands[1]), sizeof (u));
06550         REAL_VALUE_TO_TARGET_DOUBLE (u.d, l);
06551         otherops[1] = GEN_INT (l[1]);
06552         operands[1] = GEN_INT (l[0]);
06553       }
06554     else if (GET_MODE (operands[1]) != VOIDmode)
06555       abort ();
06556     else if (WORDS_BIG_ENDIAN)
06557       {
06558         otherops[1] = GEN_INT (CONST_DOUBLE_LOW (operands[1]));
06559         operands[1] = GEN_INT (CONST_DOUBLE_HIGH (operands[1]));
06560       }
06561     else
06562       {
06563         otherops[1] = GEN_INT (CONST_DOUBLE_HIGH (operands[1]));
06564         operands[1] = GEN_INT (CONST_DOUBLE_LOW (operands[1]));
06565       }
06566     
06567     output_mov_immediate (operands);
06568     output_mov_immediate (otherops);
06569   }
06570       else if (code1 == CONST_INT)
06571   {
06572 #if HOST_BITS_PER_WIDE_INT > 32
06573     /* If HOST_WIDE_INT is more than 32 bits, the intval tells us
06574        what the upper word is.  */
06575     if (WORDS_BIG_ENDIAN)
06576       {
06577         otherops[1] = GEN_INT (ARM_SIGN_EXTEND (INTVAL (operands[1])));
06578         operands[1] = GEN_INT (INTVAL (operands[1]) >> 32);
06579       }
06580     else
06581       {
06582         otherops[1] = GEN_INT (INTVAL (operands[1]) >> 32);
06583         operands[1] = GEN_INT (ARM_SIGN_EXTEND (INTVAL (operands[1])));
06584       }
06585 #else
06586     /* Sign extend the intval into the high-order word.  */
06587     if (WORDS_BIG_ENDIAN)
06588       {
06589         otherops[1] = operands[1];
06590         operands[1] = (INTVAL (operands[1]) < 0
06591            ? constm1_rtx : const0_rtx);
06592       }
06593     else
06594       otherops[1] = INTVAL (operands[1]) < 0 ? constm1_rtx : const0_rtx;
06595 #endif
06596     output_mov_immediate (otherops);
06597     output_mov_immediate (operands);
06598   }
06599       else if (code1 == MEM)
06600   {
06601     switch (GET_CODE (XEXP (operands[1], 0)))
06602       {
06603       case REG:
06604         output_asm_insn ("ldm%?ia\t%m1, %M0", operands);
06605         break;
06606 
06607         case PRE_INC:
06608         abort (); /* Should never happen now.  */
06609         break;
06610 
06611       case PRE_DEC:
06612         output_asm_insn ("ldm%?db\t%m1!, %M0", operands);
06613         break;
06614 
06615       case POST_INC:
06616         output_asm_insn ("ldm%?ia\t%m1!, %M0", operands);
06617         break;
06618 
06619       case POST_DEC:
06620         abort (); /* Should never happen now.  */
06621         break;
06622 
06623       case LABEL_REF:
06624       case CONST:
06625         output_asm_insn ("adr%?\t%0, %1", operands);
06626         output_asm_insn ("ldm%?ia\t%0, %M0", operands);
06627         break;
06628 
06629       default:
06630         if (arm_add_operand (XEXP (XEXP (operands[1], 0), 1),
06631            GET_MODE (XEXP (XEXP (operands[1], 0), 1))))
06632     {
06633       otherops[0] = operands[0];
06634       otherops[1] = XEXP (XEXP (operands[1], 0), 0);
06635       otherops[2] = XEXP (XEXP (operands[1], 0), 1);
06636 
06637       if (GET_CODE (XEXP (operands[1], 0)) == PLUS)
06638         {
06639           if (GET_CODE (otherops[2]) == CONST_INT)
06640       {
06641         switch (INTVAL (otherops[2]))
06642           {
06643           case -8:
06644             output_asm_insn ("ldm%?db\t%1, %M0", otherops);
06645             return "";
06646           case -4:
06647             output_asm_insn ("ldm%?da\t%1, %M0", otherops);
06648             return "";
06649           case 4:
06650             output_asm_insn ("ldm%?ib\t%1, %M0", otherops);
06651             return "";
06652           }
06653 
06654         if (!(const_ok_for_arm (INTVAL (otherops[2]))))
06655           output_asm_insn ("sub%?\t%0, %1, #%n2", otherops);
06656         else
06657           output_asm_insn ("add%?\t%0, %1, %2", otherops);
06658       }
06659           else
06660       output_asm_insn ("add%?\t%0, %1, %2", otherops);
06661         }
06662       else
06663         output_asm_insn ("sub%?\t%0, %1, %2", otherops);
06664       
06665       return "ldm%?ia\t%0, %M0";
06666                 }
06667               else
06668                 {
06669       otherops[1] = adjust_address (operands[1], VOIDmode, 4);
06670       /* Take care of overlapping base/data reg.  */
06671       if (reg_mentioned_p (operands[0], operands[1]))
06672         {
06673           output_asm_insn ("ldr%?\t%0, %1", otherops);
06674           output_asm_insn ("ldr%?\t%0, %1", operands);
06675         }
06676       else
06677         {
06678           output_asm_insn ("ldr%?\t%0, %1", operands);
06679           output_asm_insn ("ldr%?\t%0, %1", otherops);
06680         }
06681     }
06682       }
06683   }
06684       else
06685   abort ();  /* Constraints should prevent this.  */
06686     }
06687   else if (code0 == MEM && code1 == REG)
06688     {
06689       if (REGNO (operands[1]) == IP_REGNUM)
06690   abort ();
06691 
06692       switch (GET_CODE (XEXP (operands[0], 0)))
06693         {
06694   case REG:
06695     output_asm_insn ("stm%?ia\t%m0, %M1", operands);
06696     break;
06697 
06698         case PRE_INC:
06699     abort (); /* Should never happen now.  */
06700     break;
06701 
06702         case PRE_DEC:
06703     output_asm_insn ("stm%?db\t%m0!, %M1", operands);
06704     break;
06705 
06706         case POST_INC:
06707     output_asm_insn ("stm%?ia\t%m0!, %M1", operands);
06708     break;
06709 
06710         case POST_DEC:
06711     abort (); /* Should never happen now.  */
06712     break;
06713 
06714   case PLUS:
06715     if (GET_CODE (XEXP (XEXP (operands[0], 0), 1)) == CONST_INT)
06716       {
06717         switch (INTVAL (XEXP (XEXP (operands[0], 0), 1)))
06718     {
06719     case -8:
06720       output_asm_insn ("stm%?db\t%m0, %M1", operands);
06721       return "";
06722 
06723     case -4:
06724       output_asm_insn ("stm%?da\t%m0, %M1", operands);
06725       return "";
06726 
06727     case 4:
06728       output_asm_insn ("stm%?ib\t%m0, %M1", operands);
06729       return "";
06730     }
06731       }
06732     /* Fall through */
06733 
06734         default:
06735     otherops[0] = adjust_address (operands[0], VOIDmode, 4);
06736     otherops[1] = gen_rtx_REG (SImode, 1 + REGNO (operands[1]));
06737     output_asm_insn ("str%?\t%1, %0", operands);
06738     output_asm_insn ("str%?\t%1, %0", otherops);
06739   }
06740     }
06741   else
06742     /* Constraints should prevent this.  */
06743     abort ();
06744 
06745   return "";
06746 }
06747 
06748 
06749 /* Output an arbitrary MOV reg, #n.
06750    OPERANDS[0] is a register.  OPERANDS[1] is a const_int.  */
06751 
06752 const char *
06753 output_mov_immediate (operands)
06754      rtx * operands;
06755 {
06756   HOST_WIDE_INT n = INTVAL (operands[1]);
06757 
06758   /* Try to use one MOV.  */
06759   if (const_ok_for_arm (n))
06760     output_asm_insn ("mov%?\t%0, %1", operands);
06761 
06762   /* Try to use one MVN.  */
06763   else if (const_ok_for_arm (~n))
06764     {
06765       operands[1] = GEN_INT (~n);
06766       output_asm_insn ("mvn%?\t%0, %1", operands);
06767     }
06768   else
06769     {
06770       int n_ones = 0;
06771       int i;
06772 
06773       /* If all else fails, make it out of ORRs or BICs as appropriate.  */
06774       for (i = 0; i < 32; i ++)
06775   if (n & 1 << i)
06776     n_ones ++;
06777 
06778       if (n_ones > 16)  /* Shorter to use MVN with BIC in this case.  */
06779   output_multi_immediate (operands, "mvn%?\t%0, %1", "bic%?\t%0, %0, %1", 1, ~ n);
06780       else
06781   output_multi_immediate (operands, "mov%?\t%0, %1", "orr%?\t%0, %0, %1", 1, n);
06782     }
06783 
06784   return "";
06785 }
06786 
06787 /* Output an ADD r, s, #n where n may be too big for one instruction.
06788    If adding zero to one register, output nothing.  */
06789 
06790 const char *
06791 output_add_immediate (operands)
06792      rtx * operands;
06793 {
06794   HOST_WIDE_INT n = INTVAL (operands[2]);
06795 
06796   if (n != 0 || REGNO (operands[0]) != REGNO (operands[1]))
06797     {
06798       if (n < 0)
06799   output_multi_immediate (operands,
06800         "sub%?\t%0, %1, %2", "sub%?\t%0, %0, %2", 2,
06801         -n);
06802       else
06803   output_multi_immediate (operands,
06804         "add%?\t%0, %1, %2", "add%?\t%0, %0, %2", 2,
06805         n);
06806     }
06807 
06808   return "";
06809 }
06810 
06811 /* Output a multiple immediate operation.
06812    OPERANDS is the vector of operands referred to in the output patterns.
06813    INSTR1 is the output pattern to use for the first constant.
06814    INSTR2 is the output pattern to use for subsequent constants.
06815    IMMED_OP is the index of the constant slot in OPERANDS.
06816    N is the constant value.  */
06817 
06818 static const char *
06819 output_multi_immediate (operands, instr1, instr2, immed_op, n)
06820      rtx * operands;
06821      const char * instr1;
06822      const char * instr2;
06823      int immed_op;
06824      HOST_WIDE_INT n;
06825 {
06826 #if HOST_BITS_PER_WIDE_INT > 32
06827   n &= 0xffffffff;
06828 #endif
06829 
06830   if (n == 0)
06831     {
06832       /* Quick and easy output.  */
06833       operands[immed_op] = const0_rtx;
06834       output_asm_insn (instr1, operands);
06835     }
06836   else
06837     {
06838       int i;
06839       const char * instr = instr1;
06840 
06841       /* Note that n is never zero here (which would give no output).  */
06842       for (i = 0; i < 32; i += 2)
06843   {
06844     if (n & (3 << i))
06845       {
06846         operands[immed_op] = GEN_INT (n & (255 << i));
06847         output_asm_insn (instr, operands);
06848         instr = instr2;
06849         i += 6;
06850       }
06851   }
06852     }
06853   
06854   return "";
06855 }
06856 
06857 /* Return the appropriate ARM instruction for the operation code.
06858    The returned result should not be overwritten.  OP is the rtx of the
06859    operation.  SHIFT_FIRST_ARG is TRUE if the first argument of the operator
06860    was shifted.  */
06861 
06862 const char *
06863 arithmetic_instr (op, shift_first_arg)
06864      rtx op;
06865      int shift_first_arg;
06866 {
06867   switch (GET_CODE (op))
06868     {
06869     case PLUS:
06870       return "add";
06871 
06872     case MINUS:
06873       return shift_first_arg ? "rsb" : "sub";
06874 
06875     case IOR:
06876       return "orr";
06877 
06878     case XOR:
06879       return "eor";
06880 
06881     case AND:
06882       return "and";
06883 
06884     default:
06885       abort ();
06886     }
06887 }
06888 
06889 /* Ensure valid constant shifts and return the appropriate shift mnemonic
06890    for the operation code.  The returned result should not be overwritten.
06891    OP is the rtx code of the shift.
06892    On exit, *AMOUNTP will be -1 if the shift is by a register, or a constant
06893    shift.  */
06894 
06895 static const char *
06896 shift_op (op, amountp)
06897      rtx op;
06898      HOST_WIDE_INT *amountp;
06899 {
06900   const char * mnem;
06901   enum rtx_code code = GET_CODE (op);
06902 
06903   if (GET_CODE (XEXP (op, 1)) == REG || GET_CODE (XEXP (op, 1)) == SUBREG)
06904     *amountp = -1;
06905   else if (GET_CODE (XEXP (op, 1)) == CONST_INT)
06906     *amountp = INTVAL (XEXP (op, 1));
06907   else
06908     abort ();
06909 
06910   switch (code)
06911     {
06912     case ASHIFT:
06913       mnem = "asl";
06914       break;
06915 
06916     case ASHIFTRT:
06917       mnem = "asr";
06918       break;
06919 
06920     case LSHIFTRT:
06921       mnem = "lsr";
06922       break;
06923 
06924     case ROTATERT:
06925       mnem = "ror";
06926       break;
06927 
06928     case MULT:
06929       /* We never have to worry about the amount being other than a
06930    power of 2, since this case can never be reloaded from a reg.  */
06931       if (*amountp != -1)
06932   *amountp = int_log2 (*amountp);
06933       else
06934   abort ();
06935       return "asl";
06936 
06937     default:
06938       abort ();
06939     }
06940 
06941   if (*amountp != -1)
06942     {
06943       /* This is not 100% correct, but follows from the desire to merge
06944    multiplication by a power of 2 with the recognizer for a
06945    shift.  >=32 is not a valid shift for "asl", so we must try and
06946    output a shift that produces the correct arithmetical result.
06947    Using lsr #32 is identical except for the fact that the carry bit
06948    is not set correctly if we set the flags; but we never use the 
06949    carry bit from such an operation, so we can ignore that.  */
06950       if (code == ROTATERT)
06951   /* Rotate is just modulo 32.  */
06952   *amountp &= 31;
06953       else if (*amountp != (*amountp & 31))
06954   {
06955     if (code == ASHIFT)
06956       mnem = "lsr";
06957     *amountp = 32;
06958   }
06959 
06960       /* Shifts of 0 are no-ops.  */
06961       if (*amountp == 0)
06962   return NULL;
06963     }   
06964 
06965   return mnem;
06966 }
06967 
06968 /* Obtain the shift from the POWER of two.  */
06969 
06970 static HOST_WIDE_INT
06971 int_log2 (power)
06972      HOST_WIDE_INT power;
06973 {
06974   HOST_WIDE_INT shift = 0;
06975 
06976   while ((((HOST_WIDE_INT) 1 << shift) & power) == 0)
06977     {
06978       if (shift > 31)
06979   abort ();
06980       shift ++;
06981     }
06982 
06983   return shift;
06984 }
06985 
06986 /* Output a .ascii pseudo-op, keeping track of lengths.  This is because
06987    /bin/as is horribly restrictive.  */
06988 #define MAX_ASCII_LEN 51
06989 
06990 void
06991 output_ascii_pseudo_op (stream, p, len)
06992      FILE * stream;
06993      const unsigned char * p;
06994      int len;
06995 {
06996   int i;
06997   int len_so_far = 0;
06998 
06999   fputs ("\t.ascii\t\"", stream);
07000   
07001   for (i = 0; i < len; i++)
07002     {
07003       int c = p[i];
07004 
07005       if (len_so_far >= MAX_ASCII_LEN)
07006   {
07007     fputs ("\"\n\t.ascii\t\"", stream);
07008     len_so_far = 0;
07009   }
07010 
07011       switch (c)
07012   {
07013   case TARGET_TAB:    
07014     fputs ("\\t", stream);
07015     len_so_far += 2;      
07016     break;
07017     
07018   case TARGET_FF:
07019     fputs ("\\f", stream);
07020     len_so_far += 2;
07021     break;
07022     
07023   case TARGET_BS:
07024     fputs ("\\b", stream);
07025     len_so_far += 2;
07026     break;
07027     
07028   case TARGET_CR:
07029     fputs ("\\r", stream);
07030     len_so_far += 2;
07031     break;
07032     
07033   case TARGET_NEWLINE:
07034     fputs ("\\n", stream);
07035     c = p [i + 1];
07036     if ((c >= ' ' && c <= '~')
07037         || c == TARGET_TAB)
07038       /* This is a good place for a line break.  */
07039       len_so_far = MAX_ASCII_LEN;
07040     else
07041       len_so_far += 2;
07042     break;
07043     
07044   case '\"':
07045   case '\\':
07046     putc ('\\', stream);
07047     len_so_far++;
07048     /* drop through.  */
07049 
07050   default:
07051     if (c >= ' ' && c <= '~')
07052       {
07053         putc (c, stream);
07054         len_so_far++;
07055       }
07056     else
07057       {
07058         fprintf (stream, "\\%03o", c);
07059         len_so_far += 4;
07060       }
07061     break;
07062   }
07063     }
07064 
07065   fputs ("\"\n", stream);
07066 }
07067 
07068 /* Compute the register sabe mask for registers 0 through 12
07069    inclusive.  This code is used by both arm_compute_save_reg_mask
07070    and arm_compute_initial_elimination_offset.  */
07071 
07072 static unsigned long
07073 arm_compute_save_reg0_reg12_mask ()
07074 {
07075   unsigned long func_type = arm_current_func_type ();
07076   unsigned int save_reg_mask = 0;
07077   unsigned int reg;
07078 
07079   if (IS_INTERRUPT (func_type))
07080     {
07081       unsigned int max_reg;
07082       /* Interrupt functions must not corrupt any registers,
07083    even call clobbered ones.  If this is a leaf function
07084    we can just examine the registers used by the RTL, but
07085    otherwise we have to assume that whatever function is
07086    called might clobber anything, and so we have to save
07087    all the call-clobbered registers as well.  */
07088       if (ARM_FUNC_TYPE (func_type) == ARM_FT_FIQ)
07089   /* FIQ handlers have registers r8 - r12 banked, so
07090      we only need to check r0 - r7, Normal ISRs only
07091      bank r14 and r15, so we must check up to r12.
07092      r13 is the stack pointer which is always preserved,
07093      so we do not need to consider it here.  */
07094   max_reg = 7;
07095       else
07096   max_reg = 12;
07097   
07098       for (reg = 0; reg <= max_reg; reg++)
07099   if (regs_ever_live[reg]
07100       || (! current_function_is_leaf && call_used_regs [reg]))
07101     save_reg_mask |= (1 << reg);
07102     }
07103   else
07104     {
07105       /* In the normal case we only need to save those registers
07106    which are call saved and which are used by this function.  */
07107       for (reg = 0; reg <= 10; reg++)
07108   if (regs_ever_live[reg] && ! call_used_regs [reg])
07109     save_reg_mask |= (1 << reg);
07110 
07111       /* Handle the frame pointer as a special case.  */
07112       if (! TARGET_APCS_FRAME
07113     && ! frame_pointer_needed
07114     && regs_ever_live[HARD_FRAME_POINTER_REGNUM]
07115     && ! call_used_regs[HARD_FRAME_POINTER_REGNUM])
07116   save_reg_mask |= 1 << HARD_FRAME_POINTER_REGNUM;
07117 
07118       /* If we aren't loading the PIC register,
07119    don't stack it even though it may be live.  */
07120       if (flag_pic
07121     && ! TARGET_SINGLE_PIC_BASE 
07122     && regs_ever_live[PIC_OFFSET_TABLE_REGNUM])
07123   save_reg_mask |= 1 << PIC_OFFSET_TABLE_REGNUM;
07124     }
07125 
07126   return save_reg_mask;
07127 }
07128 
07129 /* Compute a bit mask of which registers need to be
07130    saved on the stack for the current function.  */
07131 
07132 static unsigned long
07133 arm_compute_save_reg_mask ()
07134 {
07135   unsigned int save_reg_mask = 0;
07136   unsigned long func_type = arm_current_func_type ();
07137 
07138   if (IS_NAKED (func_type))
07139     /* This should never really happen.  */
07140     return 0;
07141 
07142   /* If we are creating a stack frame, then we must save the frame pointer,
07143      IP (which will hold the old stack pointer), LR and the PC.  */
07144   if (frame_pointer_needed)
07145     save_reg_mask |=
07146       (1 << ARM_HARD_FRAME_POINTER_REGNUM)
07147       | (1 << IP_REGNUM)
07148       | (1 << LR_REGNUM)
07149       | (1 << PC_REGNUM);
07150 
07151   /* Volatile functions do not return, so there
07152      is no need to save any other registers.  */
07153   if (IS_VOLATILE (func_type))
07154     return save_reg_mask;
07155 
07156   save_reg_mask |= arm_compute_save_reg0_reg12_mask ();
07157 
07158   /* Decide if we need to save the link register.
07159      Interrupt routines have their own banked link register,
07160      so they never need to save it.
07161      Otherwise if we do not use the link register we do not need to save
07162      it.  If we are pushing other registers onto the stack however, we
07163      can save an instruction in the epilogue by pushing the link register
07164      now and then popping it back into the PC.  This incurs extra memory
07165      accesses though, so we only do it when optimising for size, and only
07166      if we know that we will not need a fancy return sequence.  */
07167   if (regs_ever_live [LR_REGNUM]
07168     || (save_reg_mask
07169         && optimize_size
07170         && ARM_FUNC_TYPE (func_type) == ARM_FT_NORMAL))
07171     save_reg_mask |= 1 << LR_REGNUM;
07172 
07173   if (cfun->machine->lr_save_eliminated)
07174     save_reg_mask &= ~ (1 << LR_REGNUM);
07175 
07176   return save_reg_mask;
07177 }
07178 
07179 /* Generate a function exit sequence.  If REALLY_RETURN is true, then do
07180    everything bar the final return instruction.  */
07181 
07182 const char *
07183 output_return_instruction (operand, really_return, reverse)
07184      rtx operand;
07185      int really_return;
07186      int reverse;
07187 {
07188   char conditional[10];
07189   char instr[100];
07190   int reg;
07191   unsigned long live_regs_mask;
07192   unsigned long func_type;
07193   
07194   func_type = arm_current_func_type ();
07195 
07196   if (IS_NAKED (func_type))
07197     return "";
07198 
07199   if (IS_VOLATILE (func_type) && TARGET_ABORT_NORETURN)
07200     {
07201       /* If this function was declared non-returning, and we have found a tail 
07202    call, then we have to trust that the called function won't return.  */
07203       if (really_return)
07204   {
07205     rtx ops[2];
07206       
07207     /* Otherwise, trap an attempted return by aborting.  */
07208     ops[0] = operand;
07209     ops[1] = gen_rtx_SYMBOL_REF (Pmode, NEED_PLT_RELOC ? "abort(PLT)" 
07210                : "abort");
07211     assemble_external_libcall (ops[1]);
07212     output_asm_insn (reverse ? "bl%D0\t%a1" : "bl%d0\t%a1", ops);
07213   }
07214       
07215       return "";
07216     }
07217 
07218   if (current_function_calls_alloca && !really_return)
07219     abort ();
07220 
07221   /* Construct the conditional part of the instruction(s) to be emitted.  */
07222   sprintf (conditional, "%%?%%%c0", reverse ? 'D' : 'd');
07223 
07224   return_used_this_function = 1;
07225 
07226   live_regs_mask = arm_compute_save_reg_mask ();
07227 
07228   if (live_regs_mask)
07229     {
07230       const char * return_reg;
07231 
07232       /* If we do not have any special requirements for function exit 
07233    (eg interworking, or ISR) then we can load the return address 
07234    directly into the PC.  Otherwise we must load it into LR.  */
07235       if (really_return
07236     && ! TARGET_INTERWORK)
07237   return_reg = reg_names[PC_REGNUM];
07238       else
07239   return_reg = reg_names[LR_REGNUM];
07240 
07241       if ((live_regs_mask & (1 << IP_REGNUM)) == (1 << IP_REGNUM))
07242   /* There are two possible reasons for the IP register being saved.
07243      Either a stack frame was created, in which case IP contains the
07244      old stack pointer, or an ISR routine corrupted it.  If this in an
07245      ISR routine then just restore IP, otherwise restore IP into SP.  */
07246   if (! IS_INTERRUPT (func_type))
07247     {
07248       live_regs_mask &= ~ (1 << IP_REGNUM);
07249       live_regs_mask |=   (1 << SP_REGNUM);
07250     }
07251 
07252       /* On some ARM architectures it is faster to use LDR rather than
07253    LDM to load a single register.  On other architectures, the
07254    cost is the same.  In 26 bit mode, or for exception handlers,
07255    we have to use LDM to load the PC so that the CPSR is also
07256    restored.  */
07257       for (reg = 0; reg <= LAST_ARM_REGNUM; reg++)
07258   {
07259     if (live_regs_mask == (unsigned int)(1 << reg))
07260       break;
07261   }
07262       if (reg <= LAST_ARM_REGNUM
07263     && (reg != LR_REGNUM
07264         || ! really_return 
07265         || (TARGET_APCS_32 && ! IS_INTERRUPT (func_type))))
07266   {
07267     sprintf (instr, "ldr%s\t%%|%s, [%%|sp], #4", conditional, 
07268        (reg == LR_REGNUM) ? return_reg : reg_names[reg]);
07269   }
07270       else
07271   {
07272     char *p;
07273     int first = 1;
07274 
07275     /* Generate the load multiple instruction to restore the registers.  */
07276     if (frame_pointer_needed)
07277       sprintf (instr, "ldm%sea\t%%|fp, {", conditional);
07278     else
07279       sprintf (instr, "ldm%sfd\t%%|sp!, {", conditional);
07280 
07281     p = instr + strlen (instr);
07282 
07283     for (reg = 0; reg <= SP_REGNUM; reg++)
07284       if (live_regs_mask & (1 << reg))
07285         {
07286     int l = strlen (reg_names[reg]);
07287 
07288     if (first)
07289       first = 0;
07290     else
07291       {
07292         memcpy (p, ", ", 2);
07293         p += 2;
07294       }
07295 
07296     memcpy (p, "%|", 2);
07297     memcpy (p + 2, reg_names[reg], l);
07298     p += l + 2;
07299         }
07300     
07301     if (live_regs_mask & (1 << LR_REGNUM))
07302       {
07303         int l = strlen (return_reg);
07304 
07305         if (! first)
07306     {
07307       memcpy (p, ", ", 2);
07308       p += 2;
07309     }
07310 
07311         memcpy (p, "%|", 2);
07312         memcpy (p + 2, return_reg, l);
07313         strcpy (p + 2 + l, ((TARGET_APCS_32 
07314            && !IS_INTERRUPT (func_type)) 
07315           || !really_return) 
07316           ? "}" : "}^");
07317       }
07318     else
07319       strcpy (p, "}");
07320   }
07321 
07322       output_asm_insn (instr, & operand);
07323 
07324       /* See if we need to generate an extra instruction to
07325    perform the actual function return.  */
07326       if (really_return
07327     && func_type != ARM_FT_INTERWORKED
07328     && (live_regs_mask & (1 << LR_REGNUM)) != 0)
07329   {
07330     /* The return has already been handled
07331        by loading the LR into the PC.  */
07332     really_return = 0;
07333   }
07334     }
07335   
07336   if (really_return)
07337     {
07338       switch ((int) ARM_FUNC_TYPE (func_type))
07339   {
07340   case ARM_FT_ISR:
07341   case ARM_FT_FIQ:
07342     sprintf (instr, "sub%ss\t%%|pc, %%|lr, #4", conditional);
07343     break;
07344 
07345   case ARM_FT_INTERWORKED:
07346     sprintf (instr, "bx%s\t%%|lr", conditional);
07347     break;
07348 
07349   case ARM_FT_EXCEPTION:
07350     sprintf (instr, "mov%ss\t%%|pc, %%|lr", conditional);
07351     break;
07352 
07353   default:
07354     /* ARMv5 implementations always provide BX, so interworking
07355        is the default unless APCS-26 is in use.  */
07356     if ((insn_flags & FL_ARCH5) != 0 && TARGET_APCS_32)
07357       sprintf (instr, "bx%s\t%%|lr", conditional);      
07358     else
07359       sprintf (instr, "mov%s%s\t%%|pc, %%|lr",
07360          conditional, TARGET_APCS_32 ? "" : "s");
07361     break;
07362   }
07363 
07364       output_asm_insn (instr, & operand);
07365     }
07366 
07367   return "";
07368 }
07369 
07370 /* Write the function name into the code section, directly preceding
07371    the function prologue.
07372 
07373    Code will be output similar to this:
07374      t0
07375    .ascii "arm_poke_function_name", 0
07376    .align
07377      t1
07378    .word 0xff000000 + (t1 - t0)
07379      arm_poke_function_name
07380    mov     ip, sp
07381    stmfd   sp!, {fp, ip, lr, pc}
07382    sub     fp, ip, #4
07383 
07384    When performing a stack backtrace, code can inspect the value
07385    of 'pc' stored at 'fp' + 0.  If the trace function then looks
07386    at location pc - 12 and the top 8 bits are set, then we know
07387    that there is a function name embedded immediately preceding this
07388    location and has length ((pc[-3]) & 0xff000000).
07389 
07390    We assume that pc is declared as a pointer to an unsigned long.
07391 
07392    It is of no benefit to output the function name if we are assembling
07393    a leaf function.  These function types will not contain a stack
07394    backtrace structure, therefore it is not possible to determine the
07395    function name.  */
07396 
07397 void
07398 arm_poke_function_name (stream, name)
07399    FILE * stream;
07400    const char * name;
07401 {
07402   unsigned long alignlength;
07403   unsigned long length;
07404   rtx           x;
07405 
07406   length      = strlen (name) + 1;
07407   alignlength = ROUND_UP (length);
07408   
07409   ASM_OUTPUT_ASCII (stream, name, length);
07410   ASM_OUTPUT_ALIGN (stream, 2);
07411   x = GEN_INT ((unsigned HOST_WIDE_INT) 0xff000000 + alignlength);
07412   assemble_aligned_integer (UNITS_PER_WORD, x);
07413 }
07414 
07415 /* Place some comments into the assembler stream
07416    describing the current function.  */
07417 
07418 static void
07419 arm_output_function_prologue (f, frame_size)
07420      FILE * f;
07421      HOST_WIDE_INT frame_size;
07422 {
07423   unsigned long func_type;
07424 
07425   if (!TARGET_ARM)
07426     {
07427       thumb_output_function_prologue (f, frame_size);
07428       return;
07429     }
07430   
07431   /* Sanity check.  */
07432   if (arm_ccfsm_state || arm_target_insn)
07433     abort ();
07434 
07435   func_type = arm_current_func_type ();
07436   
07437   switch ((int) ARM_FUNC_TYPE (func_type))
07438     {
07439     default:
07440     case ARM_FT_NORMAL:
07441       break;
07442     case ARM_FT_INTERWORKED:
07443       asm_fprintf (f, "\t%@ Function supports interworking.\n");
07444       break;
07445     case ARM_FT_EXCEPTION_HANDLER:
07446       asm_fprintf (f, "\t%@ C++ Exception Handler.\n");
07447       break;
07448     case ARM_FT_ISR:
07449       asm_fprintf (f, "\t%@ Interrupt Service Routine.\n");
07450       break;
07451     case ARM_FT_FIQ:
07452       asm_fprintf (f, "\t%@ Fast Interrupt Service Routine.\n");
07453       break;
07454     case ARM_FT_EXCEPTION:
07455       asm_fprintf (f, "\t%@ ARM Exception Handler.\n");
07456       break;
07457     }
07458   
07459   if (IS_NAKED (func_type))
07460     asm_fprintf (f, "\t%@ Naked Function: prologue and epilogue provided by programmer.\n");
07461 
07462   if (IS_VOLATILE (func_type))
07463     asm_fprintf (f, "\t%@ Volatile: function does not return.\n");
07464 
07465   if (IS_NESTED (func_type))
07466     asm_fprintf (f, "\t%@ Nested: function declared inside another function.\n");
07467     
07468   asm_fprintf (f, "\t%@ args = %d, pretend = %d, frame = %d\n",
07469