• Main Page
  • Modules
  • Data Types
  • Files

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

Go to the documentation of this file.
00001 /* Subroutines used for code generation on the DEC Alpha.
00002    Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
00003    2000, 2001 Free Software Foundation, Inc. 
00004    Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
00005 
00006 This file is part of GNU CC.
00007 
00008 GNU CC is free software; you can redistribute it and/or modify
00009 it under the terms of the GNU General Public License as published by
00010 the Free Software Foundation; either version 2, or (at your option)
00011 any later version.
00012 
00013 GNU CC is distributed in the hope that it will be useful,
00014 but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016 GNU General Public License for more details.
00017 
00018 You should have received a copy of the GNU General Public License
00019 along with GNU CC; see the file COPYING.  If not, write to
00020 the Free Software Foundation, 59 Temple Place - Suite 330,
00021 Boston, MA 02111-1307, USA.  */
00022 
00023 
00024 #include "config.h"
00025 #include "system.h"
00026 #include "rtl.h"
00027 #include "tree.h"
00028 #include "regs.h"
00029 #include "hard-reg-set.h"
00030 #include "real.h"
00031 #include "insn-config.h"
00032 #include "conditions.h"
00033 #include "output.h"
00034 #include "insn-attr.h"
00035 #include "flags.h"
00036 #include "recog.h"
00037 #include "expr.h"
00038 #include "optabs.h"
00039 #include "reload.h"
00040 #include "obstack.h"
00041 #include "except.h"
00042 #include "function.h"
00043 #include "toplev.h"
00044 #include "ggc.h"
00045 #include "integrate.h"
00046 #include "tm_p.h"
00047 #include "target.h"
00048 #include "target-def.h"
00049 #include "debug.h"
00050 
00051 /* Specify which cpu to schedule for.  */
00052 
00053 enum processor_type alpha_cpu;
00054 static const char * const alpha_cpu_name[] = 
00055 {
00056   "ev4", "ev5", "ev6"
00057 };
00058 
00059 /* Specify how accurate floating-point traps need to be.  */
00060 
00061 enum alpha_trap_precision alpha_tp;
00062 
00063 /* Specify the floating-point rounding mode.  */
00064 
00065 enum alpha_fp_rounding_mode alpha_fprm;
00066 
00067 /* Specify which things cause traps.  */
00068 
00069 enum alpha_fp_trap_mode alpha_fptm;
00070 
00071 /* Strings decoded into the above options.  */
00072 
00073 const char *alpha_cpu_string; /* -mcpu= */
00074 const char *alpha_tune_string;  /* -mtune= */
00075 const char *alpha_tp_string;  /* -mtrap-precision=[p|s|i] */
00076 const char *alpha_fprm_string;  /* -mfp-rounding-mode=[n|m|c|d] */
00077 const char *alpha_fptm_string;  /* -mfp-trap-mode=[n|u|su|sui] */
00078 const char *alpha_mlat_string;  /* -mmemory-latency= */
00079 
00080 /* Save information from a "cmpxx" operation until the branch or scc is
00081    emitted.  */
00082 
00083 struct alpha_compare alpha_compare;
00084 
00085 /* Non-zero if inside of a function, because the Alpha asm can't
00086    handle .files inside of functions.  */
00087 
00088 static int inside_function = FALSE;
00089 
00090 /* The number of cycles of latency we should assume on memory reads.  */
00091 
00092 int alpha_memory_latency = 3;
00093 
00094 /* Whether the function needs the GP.  */
00095 
00096 static int alpha_function_needs_gp;
00097 
00098 /* The alias set for prologue/epilogue register save/restore.  */
00099 
00100 static int alpha_sr_alias_set;
00101 
00102 /* The assembler name of the current function.  */
00103 
00104 static const char *alpha_fnname;
00105 
00106 /* The next explicit relocation sequence number.  */
00107 int alpha_next_sequence_number = 1;
00108 
00109 /* The literal and gpdisp sequence numbers for this insn, as printed
00110    by %# and %* respectively.  */
00111 int alpha_this_literal_sequence_number;
00112 int alpha_this_gpdisp_sequence_number;
00113 
00114 /* Declarations of static functions.  */
00115 static bool decl_in_text_section
00116   PARAMS ((tree));
00117 static int some_small_symbolic_operand_1
00118   PARAMS ((rtx *, void *));
00119 static int split_small_symbolic_operand_1
00120   PARAMS ((rtx *, void *));
00121 static bool local_symbol_p
00122   PARAMS ((rtx));
00123 static void alpha_set_memflags_1
00124   PARAMS ((rtx, int, int, int));
00125 static rtx alpha_emit_set_const_1
00126   PARAMS ((rtx, enum machine_mode, HOST_WIDE_INT, int));
00127 static void alpha_expand_unaligned_load_words
00128   PARAMS ((rtx *out_regs, rtx smem, HOST_WIDE_INT words, HOST_WIDE_INT ofs));
00129 static void alpha_expand_unaligned_store_words
00130   PARAMS ((rtx *out_regs, rtx smem, HOST_WIDE_INT words, HOST_WIDE_INT ofs));
00131 static void alpha_sa_mask
00132   PARAMS ((unsigned long *imaskP, unsigned long *fmaskP));
00133 static int find_lo_sum
00134   PARAMS ((rtx *, void *));
00135 static int alpha_does_function_need_gp
00136   PARAMS ((void));
00137 static int alpha_ra_ever_killed
00138   PARAMS ((void));
00139 static const char *get_trap_mode_suffix
00140   PARAMS ((void));
00141 static const char *get_round_mode_suffix
00142   PARAMS ((void));
00143 static rtx set_frame_related_p
00144   PARAMS ((void));
00145 static const char *alpha_lookup_xfloating_lib_func
00146   PARAMS ((enum rtx_code));
00147 static int alpha_compute_xfloating_mode_arg
00148   PARAMS ((enum rtx_code, enum alpha_fp_rounding_mode));
00149 static void alpha_emit_xfloating_libcall
00150   PARAMS ((const char *, rtx, rtx[], int, rtx));
00151 static rtx alpha_emit_xfloating_compare
00152   PARAMS ((enum rtx_code, rtx, rtx));
00153 static void alpha_output_function_end_prologue
00154   PARAMS ((FILE *));
00155 static int alpha_adjust_cost
00156   PARAMS ((rtx, rtx, rtx, int));
00157 static int alpha_issue_rate
00158   PARAMS ((void));
00159 static int alpha_variable_issue
00160   PARAMS ((FILE *, int, rtx, int));
00161 
00162 #if TARGET_ABI_UNICOSMK
00163 static void alpha_init_machine_status
00164   PARAMS ((struct function *p));
00165 static void alpha_mark_machine_status
00166   PARAMS ((struct function *p));
00167 static void alpha_free_machine_status
00168   PARAMS ((struct function *p));
00169 #endif
00170 
00171 static void unicosmk_output_deferred_case_vectors PARAMS ((FILE *));
00172 static void unicosmk_gen_dsib PARAMS ((unsigned long *imaskP));
00173 static void unicosmk_output_ssib PARAMS ((FILE *, const char *));
00174 static int unicosmk_need_dex PARAMS ((rtx));
00175 
00176 /* Get the number of args of a function in one of two ways.  */
00177 #if TARGET_ABI_OPEN_VMS || TARGET_ABI_UNICOSMK
00178 #define NUM_ARGS current_function_args_info.num_args
00179 #else
00180 #define NUM_ARGS current_function_args_info
00181 #endif
00182 
00183 #define REG_PV 27
00184 #define REG_RA 26
00185 
00186 /* Initialize the GCC target structure.  */
00187 #if TARGET_ABI_OPEN_VMS
00188 const struct attribute_spec vms_attribute_table[];
00189 static unsigned int vms_section_type_flags PARAMS ((tree, const char *, int));
00190 static void vms_asm_named_section PARAMS ((const char *, unsigned int));
00191 static void vms_asm_out_constructor PARAMS ((rtx, int));
00192 static void vms_asm_out_destructor PARAMS ((rtx, int));
00193 # undef TARGET_ATTRIBUTE_TABLE
00194 # define TARGET_ATTRIBUTE_TABLE vms_attribute_table
00195 # undef TARGET_SECTION_TYPE_FLAGS
00196 # define TARGET_SECTION_TYPE_FLAGS vms_section_type_flags
00197 #endif
00198 
00199 #if TARGET_ABI_UNICOSMK
00200 static void unicosmk_asm_named_section PARAMS ((const char *, unsigned int));
00201 static void unicosmk_insert_attributes PARAMS ((tree, tree *));
00202 static unsigned int unicosmk_section_type_flags PARAMS ((tree, const char *, 
00203                int));
00204 # undef TARGET_INSERT_ATTRIBUTES
00205 # define TARGET_INSERT_ATTRIBUTES unicosmk_insert_attributes
00206 # undef TARGET_SECTION_TYPE_FLAGS
00207 # define TARGET_SECTION_TYPE_FLAGS unicosmk_section_type_flags
00208 #endif
00209 
00210 #undef TARGET_ASM_ALIGNED_HI_OP
00211 #define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
00212 #undef TARGET_ASM_ALIGNED_DI_OP
00213 #define TARGET_ASM_ALIGNED_DI_OP "\t.quad\t"
00214 
00215 /* Default unaligned ops are provided for ELF systems.  To get unaligned
00216    data for non-ELF systems, we have to turn off auto alignment.  */
00217 #ifndef OBJECT_FORMAT_ELF
00218 #undef TARGET_ASM_UNALIGNED_HI_OP
00219 #define TARGET_ASM_UNALIGNED_HI_OP "\t.align 0\n\t.word\t"
00220 #undef TARGET_ASM_UNALIGNED_SI_OP
00221 #define TARGET_ASM_UNALIGNED_SI_OP "\t.align 0\n\t.long\t"
00222 #undef TARGET_ASM_UNALIGNED_DI_OP
00223 #define TARGET_ASM_UNALIGNED_DI_OP "\t.align 0\n\t.quad\t"
00224 #endif
00225 
00226 #undef TARGET_ASM_FUNCTION_END_PROLOGUE
00227 #define TARGET_ASM_FUNCTION_END_PROLOGUE alpha_output_function_end_prologue
00228 
00229 #undef TARGET_SCHED_ADJUST_COST
00230 #define TARGET_SCHED_ADJUST_COST alpha_adjust_cost
00231 #undef TARGET_SCHED_ISSUE_RATE
00232 #define TARGET_SCHED_ISSUE_RATE alpha_issue_rate
00233 #undef TARGET_SCHED_VARIABLE_ISSUE
00234 #define TARGET_SCHED_VARIABLE_ISSUE alpha_variable_issue
00235 
00236 struct gcc_target targetm = TARGET_INITIALIZER;
00237 
00238 /* Parse target option strings.  */
00239 
00240 void
00241 override_options ()
00242 {
00243   int i;
00244   static const struct cpu_table {
00245     const char *const name;
00246     const enum processor_type processor;
00247     const int flags;
00248   } cpu_table[] = {
00249 #define EV5_MASK (MASK_CPU_EV5)
00250 #define EV6_MASK (MASK_CPU_EV6|MASK_BWX|MASK_MAX|MASK_FIX)
00251     { "ev4",  PROCESSOR_EV4, 0 },
00252     { "ev45", PROCESSOR_EV4, 0 },
00253     { "21064",  PROCESSOR_EV4, 0 },
00254     { "ev5",  PROCESSOR_EV5, EV5_MASK },
00255     { "21164",  PROCESSOR_EV5, EV5_MASK },
00256     { "ev56", PROCESSOR_EV5, EV5_MASK|MASK_BWX },
00257     { "21164a", PROCESSOR_EV5, EV5_MASK|MASK_BWX },
00258     { "pca56",  PROCESSOR_EV5, EV5_MASK|MASK_BWX|MASK_MAX },
00259     { "21164PC",PROCESSOR_EV5, EV5_MASK|MASK_BWX|MASK_MAX },
00260     { "21164pc",PROCESSOR_EV5, EV5_MASK|MASK_BWX|MASK_MAX },
00261     { "ev6",  PROCESSOR_EV6, EV6_MASK },
00262     { "21264",  PROCESSOR_EV6, EV6_MASK },
00263     { "ev67", PROCESSOR_EV6, EV6_MASK|MASK_CIX },
00264     { "21264a", PROCESSOR_EV6, EV6_MASK|MASK_CIX },
00265     { 0, 0, 0 }
00266   };
00267                   
00268   /* Unicos/Mk doesn't have shared libraries.  */
00269   if (TARGET_ABI_UNICOSMK && flag_pic)
00270     {
00271       warning ("-f%s ignored for Unicos/Mk (not supported)",
00272          (flag_pic > 1) ? "PIC" : "pic");
00273       flag_pic = 0;
00274     }
00275 
00276   /* On Unicos/Mk, the native compiler consistenly generates /d suffices for 
00277      floating-point instructions.  Make that the default for this target.  */
00278   if (TARGET_ABI_UNICOSMK)
00279     alpha_fprm = ALPHA_FPRM_DYN;
00280   else
00281     alpha_fprm = ALPHA_FPRM_NORM;
00282 
00283   alpha_tp = ALPHA_TP_PROG;
00284   alpha_fptm = ALPHA_FPTM_N;
00285 
00286   /* We cannot use su and sui qualifiers for conversion instructions on 
00287      Unicos/Mk.  I'm not sure if this is due to assembler or hardware
00288      limitations.  Right now, we issue a warning if -mieee is specified
00289      and then ignore it; eventually, we should either get it right or
00290      disable the option altogether.  */
00291 
00292   if (TARGET_IEEE)
00293     {
00294       if (TARGET_ABI_UNICOSMK)
00295   warning ("-mieee not supported on Unicos/Mk");
00296       else
00297   {
00298     alpha_tp = ALPHA_TP_INSN;
00299     alpha_fptm = ALPHA_FPTM_SU;
00300   }
00301     }
00302 
00303   if (TARGET_IEEE_WITH_INEXACT)
00304     {
00305       if (TARGET_ABI_UNICOSMK)
00306   warning ("-mieee-with-inexact not supported on Unicos/Mk");
00307       else
00308   {
00309     alpha_tp = ALPHA_TP_INSN;
00310     alpha_fptm = ALPHA_FPTM_SUI;
00311   }
00312     }
00313 
00314   if (alpha_tp_string)
00315     {
00316       if (! strcmp (alpha_tp_string, "p"))
00317   alpha_tp = ALPHA_TP_PROG;
00318       else if (! strcmp (alpha_tp_string, "f"))
00319   alpha_tp = ALPHA_TP_FUNC;
00320       else if (! strcmp (alpha_tp_string, "i"))
00321   alpha_tp = ALPHA_TP_INSN;
00322       else
00323   error ("bad value `%s' for -mtrap-precision switch", alpha_tp_string);
00324     }
00325 
00326   if (alpha_fprm_string)
00327     {
00328       if (! strcmp (alpha_fprm_string, "n"))
00329   alpha_fprm = ALPHA_FPRM_NORM;
00330       else if (! strcmp (alpha_fprm_string, "m"))
00331   alpha_fprm = ALPHA_FPRM_MINF;
00332       else if (! strcmp (alpha_fprm_string, "c"))
00333   alpha_fprm = ALPHA_FPRM_CHOP;
00334       else if (! strcmp (alpha_fprm_string,"d"))
00335   alpha_fprm = ALPHA_FPRM_DYN;
00336       else
00337   error ("bad value `%s' for -mfp-rounding-mode switch",
00338          alpha_fprm_string);
00339     }
00340 
00341   if (alpha_fptm_string)
00342     {
00343       if (strcmp (alpha_fptm_string, "n") == 0)
00344   alpha_fptm = ALPHA_FPTM_N;
00345       else if (strcmp (alpha_fptm_string, "u") == 0)
00346   alpha_fptm = ALPHA_FPTM_U;
00347       else if (strcmp (alpha_fptm_string, "su") == 0)
00348   alpha_fptm = ALPHA_FPTM_SU;
00349       else if (strcmp (alpha_fptm_string, "sui") == 0)
00350   alpha_fptm = ALPHA_FPTM_SUI;
00351       else
00352   error ("bad value `%s' for -mfp-trap-mode switch", alpha_fptm_string);
00353     }
00354 
00355   alpha_cpu
00356     = TARGET_CPU_DEFAULT & MASK_CPU_EV6 ? PROCESSOR_EV6
00357       : (TARGET_CPU_DEFAULT & MASK_CPU_EV5 ? PROCESSOR_EV5 : PROCESSOR_EV4);
00358 
00359   if (alpha_cpu_string)
00360     {
00361       for (i = 0; cpu_table [i].name; i++)
00362   if (! strcmp (alpha_cpu_string, cpu_table [i].name))
00363     {
00364       alpha_cpu = cpu_table [i].processor;
00365       target_flags &= ~ (MASK_BWX | MASK_MAX | MASK_FIX | MASK_CIX
00366              | MASK_CPU_EV5 | MASK_CPU_EV6);
00367       target_flags |= cpu_table [i].flags;
00368       break;
00369     }
00370       if (! cpu_table [i].name)
00371   error ("bad value `%s' for -mcpu switch", alpha_cpu_string);
00372     }
00373 
00374   if (alpha_tune_string)
00375     {
00376       for (i = 0; cpu_table [i].name; i++)
00377   if (! strcmp (alpha_tune_string, cpu_table [i].name))
00378     {
00379       alpha_cpu = cpu_table [i].processor;
00380       break;
00381     }
00382       if (! cpu_table [i].name)
00383   error ("bad value `%s' for -mcpu switch", alpha_tune_string);
00384     }
00385 
00386   /* Do some sanity checks on the above options.  */
00387 
00388   if (TARGET_ABI_UNICOSMK && alpha_fptm != ALPHA_FPTM_N)
00389     {
00390       warning ("trap mode not supported on Unicos/Mk");
00391       alpha_fptm = ALPHA_FPTM_N;
00392     }
00393 
00394   if ((alpha_fptm == ALPHA_FPTM_SU || alpha_fptm == ALPHA_FPTM_SUI)
00395       && alpha_tp != ALPHA_TP_INSN && ! TARGET_CPU_EV6)
00396     {
00397       warning ("fp software completion requires -mtrap-precision=i");
00398       alpha_tp = ALPHA_TP_INSN;
00399     }
00400 
00401   if (TARGET_CPU_EV6)
00402     {
00403       /* Except for EV6 pass 1 (not released), we always have precise
00404    arithmetic traps.  Which means we can do software completion
00405    without minding trap shadows.  */
00406       alpha_tp = ALPHA_TP_PROG;
00407     }
00408 
00409   if (TARGET_FLOAT_VAX)
00410     {
00411       if (alpha_fprm == ALPHA_FPRM_MINF || alpha_fprm == ALPHA_FPRM_DYN)
00412   {
00413     warning ("rounding mode not supported for VAX floats");
00414     alpha_fprm = ALPHA_FPRM_NORM;
00415   }
00416       if (alpha_fptm == ALPHA_FPTM_SUI)
00417   {
00418     warning ("trap mode not supported for VAX floats");
00419     alpha_fptm = ALPHA_FPTM_SU;
00420   }
00421     }
00422 
00423   {
00424     char *end;
00425     int lat;
00426 
00427     if (!alpha_mlat_string)
00428       alpha_mlat_string = "L1";
00429 
00430     if (ISDIGIT ((unsigned char)alpha_mlat_string[0])
00431   && (lat = strtol (alpha_mlat_string, &end, 10), *end == '\0'))
00432       ;
00433     else if ((alpha_mlat_string[0] == 'L' || alpha_mlat_string[0] == 'l')
00434        && ISDIGIT ((unsigned char)alpha_mlat_string[1])
00435        && alpha_mlat_string[2] == '\0')
00436       {
00437   static int const cache_latency[][4] = 
00438   {
00439     { 3, 30, -1 },  /* ev4 -- Bcache is a guess */
00440     { 2, 12, 38 },  /* ev5 -- Bcache from PC164 LMbench numbers */
00441     { 3, 12, 30 },  /* ev6 -- Bcache from DS20 LMbench.  */
00442   };
00443 
00444   lat = alpha_mlat_string[1] - '0';
00445   if (lat <= 0 || lat > 3 || cache_latency[alpha_cpu][lat-1] == -1)
00446     {
00447       warning ("L%d cache latency unknown for %s",
00448          lat, alpha_cpu_name[alpha_cpu]);
00449       lat = 3;
00450     }
00451   else
00452     lat = cache_latency[alpha_cpu][lat-1];
00453       }
00454     else if (! strcmp (alpha_mlat_string, "main"))
00455       {
00456   /* Most current memories have about 370ns latency.  This is
00457      a reasonable guess for a fast cpu.  */
00458   lat = 150;
00459       }
00460     else
00461       {
00462   warning ("bad value `%s' for -mmemory-latency", alpha_mlat_string);
00463   lat = 3;
00464       }
00465 
00466     alpha_memory_latency = lat;
00467   }
00468 
00469   /* Default the definition of "small data" to 8 bytes.  */
00470   if (!g_switch_set)
00471     g_switch_value = 8;
00472 
00473   /* Infer TARGET_SMALL_DATA from -fpic/-fPIC.  */
00474   if (flag_pic == 1)
00475     target_flags |= MASK_SMALL_DATA;
00476   else if (flag_pic == 2)
00477     target_flags &= ~MASK_SMALL_DATA;
00478 
00479   /* Align labels and loops for optimal branching.  */
00480   /* ??? Kludge these by not doing anything if we don't optimize and also if
00481      we are writing ECOFF symbols to work around a bug in DEC's assembler.  */
00482   if (optimize > 0 && write_symbols != SDB_DEBUG)
00483     {
00484       if (align_loops <= 0)
00485   align_loops = 16;
00486       if (align_jumps <= 0)
00487   align_jumps = 16;
00488     }
00489   if (align_functions <= 0)
00490     align_functions = 16;
00491 
00492   /* Acquire a unique set number for our register saves and restores.  */
00493   alpha_sr_alias_set = new_alias_set ();
00494 
00495   /* Register variables and functions with the garbage collector.  */
00496 
00497 #if TARGET_ABI_UNICOSMK
00498   /* Set up function hooks.  */
00499   init_machine_status = alpha_init_machine_status;
00500   mark_machine_status = alpha_mark_machine_status;
00501   free_machine_status = alpha_free_machine_status;
00502 #endif
00503 }
00504 
00505 /* Returns 1 if VALUE is a mask that contains full bytes of zero or ones.  */
00506 
00507 int
00508 zap_mask (value)
00509      HOST_WIDE_INT value;
00510 {
00511   int i;
00512 
00513   for (i = 0; i < HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR;
00514        i++, value >>= 8)
00515     if ((value & 0xff) != 0 && (value & 0xff) != 0xff)
00516       return 0;
00517 
00518   return 1;
00519 }
00520 
00521 /* Returns 1 if OP is either the constant zero or a register.  If a
00522    register, it must be in the proper mode unless MODE is VOIDmode.  */
00523 
00524 int
00525 reg_or_0_operand (op, mode)
00526       register rtx op;
00527       enum machine_mode mode;
00528 {
00529   return op == const0_rtx || register_operand (op, mode);
00530 }
00531 
00532 /* Return 1 if OP is a constant in the range of 0-63 (for a shift) or
00533    any register.  */
00534 
00535 int
00536 reg_or_6bit_operand (op, mode)
00537      register rtx op;
00538      enum machine_mode mode;
00539 {
00540   return ((GET_CODE (op) == CONST_INT
00541      && (unsigned HOST_WIDE_INT) INTVAL (op) < 64)
00542     || register_operand (op, mode));
00543 }
00544 
00545 
00546 /* Return 1 if OP is an 8-bit constant or any register.  */
00547 
00548 int
00549 reg_or_8bit_operand (op, mode)
00550      register rtx op;
00551      enum machine_mode mode;
00552 {
00553   return ((GET_CODE (op) == CONST_INT
00554      && (unsigned HOST_WIDE_INT) INTVAL (op) < 0x100)
00555     || register_operand (op, mode));
00556 }
00557 
00558 /* Return 1 if OP is an 8-bit constant.  */
00559 
00560 int
00561 cint8_operand (op, mode)
00562      register rtx op;
00563      enum machine_mode mode ATTRIBUTE_UNUSED;
00564 {
00565   return ((GET_CODE (op) == CONST_INT
00566      && (unsigned HOST_WIDE_INT) INTVAL (op) < 0x100));
00567 }
00568 
00569 /* Return 1 if the operand is a valid second operand to an add insn.  */
00570 
00571 int
00572 add_operand (op, mode)
00573      register rtx op;
00574      enum machine_mode mode;
00575 {
00576   if (GET_CODE (op) == CONST_INT)
00577     /* Constraints I, J, O and P are covered by K.  */
00578     return (CONST_OK_FOR_LETTER_P (INTVAL (op), 'K')
00579       || CONST_OK_FOR_LETTER_P (INTVAL (op), 'L'));
00580 
00581   return register_operand (op, mode);
00582 }
00583 
00584 /* Return 1 if the operand is a valid second operand to a sign-extending
00585    add insn.  */
00586 
00587 int
00588 sext_add_operand (op, mode)
00589      register rtx op;
00590      enum machine_mode mode;
00591 {
00592   if (GET_CODE (op) == CONST_INT)
00593     return (CONST_OK_FOR_LETTER_P (INTVAL (op), 'I')
00594       || CONST_OK_FOR_LETTER_P (INTVAL (op), 'O'));
00595 
00596   return reg_not_elim_operand (op, mode);
00597 }
00598 
00599 /* Return 1 if OP is the constant 4 or 8.  */
00600 
00601 int
00602 const48_operand (op, mode)
00603      register rtx op;
00604      enum machine_mode mode ATTRIBUTE_UNUSED;
00605 {
00606   return (GET_CODE (op) == CONST_INT
00607     && (INTVAL (op) == 4 || INTVAL (op) == 8));
00608 }
00609 
00610 /* Return 1 if OP is a valid first operand to an AND insn.  */
00611 
00612 int
00613 and_operand (op, mode)
00614      register rtx op;
00615      enum machine_mode mode;
00616 {
00617   if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == VOIDmode)
00618     return (zap_mask (CONST_DOUBLE_LOW (op))
00619       && zap_mask (CONST_DOUBLE_HIGH (op)));
00620 
00621   if (GET_CODE (op) == CONST_INT)
00622     return ((unsigned HOST_WIDE_INT) INTVAL (op) < 0x100
00623       || (unsigned HOST_WIDE_INT) ~ INTVAL (op) < 0x100
00624       || zap_mask (INTVAL (op)));
00625 
00626   return register_operand (op, mode);
00627 }
00628 
00629 /* Return 1 if OP is a valid first operand to an IOR or XOR insn.  */
00630 
00631 int
00632 or_operand (op, mode)
00633      register rtx op;
00634      enum machine_mode mode;
00635 {
00636   if (GET_CODE (op) == CONST_INT)
00637     return ((unsigned HOST_WIDE_INT) INTVAL (op) < 0x100
00638       || (unsigned HOST_WIDE_INT) ~ INTVAL (op) < 0x100);
00639 
00640   return register_operand (op, mode);
00641 }
00642 
00643 /* Return 1 if OP is a constant that is the width, in bits, of an integral
00644    mode smaller than DImode.  */
00645 
00646 int
00647 mode_width_operand (op, mode)
00648      register rtx op;
00649      enum machine_mode mode ATTRIBUTE_UNUSED;
00650 {
00651   return (GET_CODE (op) == CONST_INT
00652     && (INTVAL (op) == 8 || INTVAL (op) == 16
00653         || INTVAL (op) == 32 || INTVAL (op) == 64));
00654 }
00655 
00656 /* Return 1 if OP is a constant that is the width of an integral machine mode
00657    smaller than an integer.  */
00658 
00659 int
00660 mode_mask_operand (op, mode)
00661      register rtx op;
00662      enum machine_mode mode ATTRIBUTE_UNUSED;
00663 {
00664 #if HOST_BITS_PER_WIDE_INT == 32
00665   if (GET_CODE (op) == CONST_DOUBLE)
00666     return (CONST_DOUBLE_LOW (op) == -1
00667       && (CONST_DOUBLE_HIGH (op) == -1
00668     || CONST_DOUBLE_HIGH (op) == 0));
00669 #else
00670   if (GET_CODE (op) == CONST_DOUBLE)
00671     return (CONST_DOUBLE_LOW (op) == -1 && CONST_DOUBLE_HIGH (op) == 0);
00672 #endif
00673 
00674   return (GET_CODE (op) == CONST_INT
00675     && (INTVAL (op) == 0xff
00676         || INTVAL (op) == 0xffff
00677         || INTVAL (op) == (HOST_WIDE_INT)0xffffffff
00678 #if HOST_BITS_PER_WIDE_INT == 64
00679         || INTVAL (op) == -1
00680 #endif
00681         ));
00682 }
00683 
00684 /* Return 1 if OP is a multiple of 8 less than 64.  */
00685 
00686 int
00687 mul8_operand (op, mode)
00688      register rtx op;
00689      enum machine_mode mode ATTRIBUTE_UNUSED;
00690 {
00691   return (GET_CODE (op) == CONST_INT
00692     && (unsigned HOST_WIDE_INT) INTVAL (op) < 64
00693     && (INTVAL (op) & 7) == 0);
00694 }
00695 
00696 /* Return 1 if OP is the constant zero in floating-point.  */
00697 
00698 int
00699 fp0_operand (op, mode)
00700      register rtx op;
00701      enum machine_mode mode;
00702 {
00703   return (GET_MODE (op) == mode
00704     && GET_MODE_CLASS (mode) == MODE_FLOAT && op == CONST0_RTX (mode));
00705 }
00706 
00707 /* Return 1 if OP is the floating-point constant zero or a register.  */
00708 
00709 int
00710 reg_or_fp0_operand (op, mode)
00711      register rtx op;
00712      enum machine_mode mode;
00713 {
00714   return fp0_operand (op, mode) || register_operand (op, mode);
00715 }
00716 
00717 /* Return 1 if OP is a hard floating-point register.  */
00718 
00719 int
00720 hard_fp_register_operand (op, mode)
00721      register rtx op;
00722      enum machine_mode mode;
00723 {
00724   if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op))
00725     return 0;
00726 
00727   if (GET_CODE (op) == SUBREG)
00728     op = SUBREG_REG (op);
00729   return GET_CODE (op) == REG && REGNO_REG_CLASS (REGNO (op)) == FLOAT_REGS;
00730 }
00731 
00732 /* Return 1 if OP is a hard general register.  */
00733 
00734 int
00735 hard_int_register_operand (op, mode)
00736      register rtx op;
00737      enum machine_mode mode;
00738 {
00739   if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op))
00740     return 0;
00741 
00742   if (GET_CODE (op) == SUBREG)
00743     op = SUBREG_REG (op);
00744   return GET_CODE (op) == REG && REGNO_REG_CLASS (REGNO (op)) == GENERAL_REGS;
00745 }
00746 
00747 /* Return 1 if OP is a register or a constant integer.  */
00748 
00749 
00750 int
00751 reg_or_cint_operand (op, mode)
00752     register rtx op;
00753     enum machine_mode mode;
00754 {
00755      return (GET_CODE (op) == CONST_INT
00756        || register_operand (op, mode));
00757 }
00758 
00759 /* Return 1 if OP is something that can be reloaded into a register;
00760    if it is a MEM, it need not be valid.  */
00761 
00762 int
00763 some_operand (op, mode)
00764      register rtx op;
00765      enum machine_mode mode;
00766 {
00767   if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op))
00768     return 0;
00769 
00770   switch (GET_CODE (op))
00771     {
00772     case REG:  case MEM:  case CONST_DOUBLE:  case CONST_INT:  case LABEL_REF:
00773     case SYMBOL_REF:  case CONST:  case HIGH:
00774       return 1;
00775 
00776     case SUBREG:
00777       return some_operand (SUBREG_REG (op), VOIDmode);
00778 
00779     default:
00780       break;
00781     }
00782 
00783   return 0;
00784 }
00785 
00786 /* Likewise, but don't accept constants.  */
00787 
00788 int
00789 some_ni_operand (op, mode)
00790      register rtx op;
00791      enum machine_mode mode;
00792 {
00793   if (GET_MODE (op) != mode && mode != VOIDmode)
00794     return 0;
00795 
00796   if (GET_CODE (op) == SUBREG)
00797     op = SUBREG_REG (op);
00798 
00799   return (GET_CODE (op) == REG || GET_CODE (op) == MEM);
00800 }
00801 
00802 /* Return 1 if OP is a valid operand for the source of a move insn.  */
00803 
00804 int
00805 input_operand (op, mode)
00806      register rtx op;
00807      enum machine_mode mode;
00808 {
00809   if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op))
00810     return 0;
00811 
00812   if (GET_MODE_CLASS (mode) == MODE_FLOAT && GET_MODE (op) != mode)
00813     return 0;
00814 
00815   switch (GET_CODE (op))
00816     {
00817     case LABEL_REF:
00818     case SYMBOL_REF:
00819     case CONST:
00820       if (TARGET_EXPLICIT_RELOCS)
00821   {
00822     /* We don't split symbolic operands into something unintelligable
00823        until after reload, but we do not wish non-small, non-global
00824        symbolic operands to be reconstructed from their high/lo_sum
00825        form.  */
00826     return (small_symbolic_operand (op, mode)
00827       || global_symbolic_operand (op, mode));
00828   }
00829 
00830       /* This handles both the Windows/NT and OSF cases.  */
00831       return mode == ptr_mode || mode == DImode;
00832 
00833     case HIGH:
00834       return (TARGET_EXPLICIT_RELOCS
00835         && local_symbolic_operand (XEXP (op, 0), mode));
00836 
00837     case REG:
00838     case ADDRESSOF:
00839       return 1;
00840 
00841     case SUBREG:
00842       if (register_operand (op, mode))
00843   return 1;
00844       /* ... fall through ...  */
00845     case MEM:
00846       return ((TARGET_BWX || (mode != HImode && mode != QImode))
00847         && general_operand (op, mode));
00848 
00849     case CONST_DOUBLE:
00850       return GET_MODE_CLASS (mode) == MODE_FLOAT && op == CONST0_RTX (mode);
00851 
00852     case CONST_INT:
00853       return mode == QImode || mode == HImode || add_operand (op, mode);
00854 
00855     case CONSTANT_P_RTX:
00856       return 1;
00857 
00858     default:
00859       break;
00860     }
00861 
00862   return 0;
00863 }
00864 
00865 /* Return 1 if OP is a SYMBOL_REF for a function known to be in this
00866    file, and in the same section as the current function.  */
00867 
00868 int
00869 current_file_function_operand (op, mode)
00870      rtx op;
00871      enum machine_mode mode ATTRIBUTE_UNUSED;
00872 {
00873   if (GET_CODE (op) != SYMBOL_REF)
00874     return 0;
00875 
00876   /* Easy test for recursion.  */
00877   if (op == XEXP (DECL_RTL (current_function_decl), 0))
00878     return 1;
00879 
00880   /* Otherwise, we need the DECL for the SYMBOL_REF, which we can't get.
00881      So SYMBOL_REF_FLAG has been declared to imply that the function is
00882      in the default text section.  So we must also check that the current
00883      function is also in the text section.  */
00884   if (SYMBOL_REF_FLAG (op) && decl_in_text_section (current_function_decl))
00885     return 1;
00886 
00887   return 0;
00888 }
00889 
00890 /* Return 1 if OP is a SYMBOL_REF for which we can make a call via bsr.  */
00891 
00892 int
00893 direct_call_operand (op, mode)
00894      rtx op;
00895      enum machine_mode mode;
00896 {
00897   /* Must be defined in this file.  */
00898   if (! current_file_function_operand (op, mode))
00899     return 0;
00900 
00901   /* If profiling is implemented via linker tricks, we can't jump
00902      to the nogp alternate entry point.  */
00903   /* ??? TARGET_PROFILING_NEEDS_GP isn't really the right test,
00904      but is approximately correct for the OSF ABIs.  Don't know
00905      what to do for VMS, NT, or UMK.  */
00906   if (! TARGET_PROFILING_NEEDS_GP
00907       && ! current_function_profile)
00908     return 0;
00909 
00910   return 1;
00911 }
00912 
00913 /* Return true if OP is a LABEL_REF, or SYMBOL_REF or CONST referencing
00914    a variable known to be defined in this file.  */
00915 
00916 static bool
00917 local_symbol_p (op)
00918      rtx op;
00919 {
00920   const char *str = XSTR (op, 0);
00921 
00922   /* ??? SYMBOL_REF_FLAG is set for local function symbols, but we
00923      run into problems with the rtl inliner in that the symbol was
00924      once external, but is local after inlining, which results in
00925      unrecognizable insns.  */
00926 
00927   return (CONSTANT_POOL_ADDRESS_P (op)
00928     /* If @, then ENCODE_SECTION_INFO sez it's local.  */
00929     || str[0] == '@'
00930     /* If *$, then ASM_GENERATE_INTERNAL_LABEL sez it's local.  */
00931     || (str[0] == '*' && str[1] == '$'));
00932 }
00933 
00934 int
00935 local_symbolic_operand (op, mode)
00936      rtx op;
00937      enum machine_mode mode;
00938 {
00939   if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op))
00940     return 0;
00941 
00942   if (GET_CODE (op) == LABEL_REF)
00943     return 1;
00944 
00945   if (GET_CODE (op) == CONST
00946       && GET_CODE (XEXP (op, 0)) == PLUS
00947       && GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT)
00948     op = XEXP (XEXP (op, 0), 0);
00949 
00950   if (GET_CODE (op) != SYMBOL_REF)
00951     return 0;
00952 
00953   return local_symbol_p (op);
00954 }
00955 
00956 /* Return true if OP is a SYMBOL_REF or CONST referencing a variable
00957    known to be defined in this file in the small data area.  */
00958 
00959 int
00960 small_symbolic_operand (op, mode)
00961      rtx op;
00962      enum machine_mode mode ATTRIBUTE_UNUSED;
00963 {
00964   const char *str;
00965 
00966   if (! TARGET_SMALL_DATA)
00967     return 0;
00968 
00969   if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op))
00970     return 0;
00971 
00972   if (GET_CODE (op) == CONST
00973       && GET_CODE (XEXP (op, 0)) == PLUS
00974       && GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT)
00975     op = XEXP (XEXP (op, 0), 0);
00976 
00977   if (GET_CODE (op) != SYMBOL_REF)
00978     return 0;
00979 
00980   if (CONSTANT_POOL_ADDRESS_P (op))
00981     return GET_MODE_SIZE (get_pool_mode (op)) <= (unsigned) g_switch_value;
00982   else
00983     {
00984       str = XSTR (op, 0);
00985       return str[0] == '@' && str[1] == 's';
00986     }
00987 }
00988 
00989 /* Return true if OP is a SYMBOL_REF or CONST referencing a variable
00990    not known (or known not) to be defined in this file.  */
00991 
00992 int
00993 global_symbolic_operand (op, mode)
00994      rtx op;
00995      enum machine_mode mode;
00996 {
00997   if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op))
00998     return 0;
00999 
01000   if (GET_CODE (op) == CONST
01001       && GET_CODE (XEXP (op, 0)) == PLUS
01002       && GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT)
01003     op = XEXP (XEXP (op, 0), 0);
01004 
01005   if (GET_CODE (op) != SYMBOL_REF)
01006     return 0;
01007 
01008   return ! local_symbol_p (op);
01009 }
01010 
01011 /* Return 1 if OP is a valid operand for the MEM of a CALL insn.  */
01012 
01013 int
01014 call_operand (op, mode)
01015      rtx op;
01016      enum machine_mode mode;
01017 {
01018   if (mode != Pmode)
01019     return 0;
01020 
01021   if (GET_CODE (op) == REG)
01022     {
01023       if (TARGET_ABI_OSF)
01024   {
01025     /* Disallow virtual registers to cope with pathalogical test cases
01026        such as compile/930117-1.c in which the virtual reg decomposes
01027        to the frame pointer.  Which is a hard reg that is not $27.  */
01028     return (REGNO (op) == 27 || REGNO (op) > LAST_VIRTUAL_REGISTER);
01029   }
01030       else
01031   return 1;
01032     }
01033   if (TARGET_ABI_UNICOSMK)
01034     return 0;
01035   if (GET_CODE (op) == SYMBOL_REF)
01036     return 1;
01037 
01038   return 0;
01039 }
01040 
01041 /* Returns 1 if OP is a symbolic operand, i.e. a symbol_ref or a label_ref,
01042    possibly with an offset.  */
01043 
01044 int
01045 symbolic_operand (op, mode)
01046       register rtx op;
01047       enum machine_mode mode;
01048 {
01049   if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op))
01050     return 0;
01051   if (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF)
01052     return 1;
01053   if (GET_CODE (op) == CONST
01054       && GET_CODE (XEXP (op,0)) == PLUS
01055       && GET_CODE (XEXP (XEXP (op,0), 0)) == SYMBOL_REF
01056       && GET_CODE (XEXP (XEXP (op,0), 1)) == CONST_INT)
01057     return 1;
01058   return 0;
01059 }
01060 
01061 /* Return 1 if OP is a valid Alpha comparison operator.  Here we know which
01062    comparisons are valid in which insn.  */
01063 
01064 int
01065 alpha_comparison_operator (op, mode)
01066      register rtx op;
01067      enum machine_mode mode;
01068 {
01069   enum rtx_code code = GET_CODE (op);
01070 
01071   if (mode != GET_MODE (op) && mode != VOIDmode)
01072     return 0;
01073 
01074   return (code == EQ || code == LE || code == LT
01075     || code == LEU || code == LTU);
01076 }
01077 
01078 /* Return 1 if OP is a valid Alpha comparison operator against zero. 
01079    Here we know which comparisons are valid in which insn.  */
01080 
01081 int
01082 alpha_zero_comparison_operator (op, mode)
01083      register rtx op;
01084      enum machine_mode mode;
01085 {
01086   enum rtx_code code = GET_CODE (op);
01087 
01088   if (mode != GET_MODE (op) && mode != VOIDmode)
01089     return 0;
01090 
01091   return (code == EQ || code == NE || code == LE || code == LT
01092     || code == LEU || code == LTU);
01093 }
01094 
01095 /* Return 1 if OP is a valid Alpha swapped comparison operator.  */
01096 
01097 int
01098 alpha_swapped_comparison_operator (op, mode)
01099      register rtx op;
01100      enum machine_mode mode;
01101 {
01102   enum rtx_code code = GET_CODE (op);
01103 
01104   if ((mode != GET_MODE (op) && mode != VOIDmode)
01105       || GET_RTX_CLASS (code) != '<')
01106     return 0;
01107 
01108   code = swap_condition (code);
01109   return (code == EQ || code == LE || code == LT
01110     || code == LEU || code == LTU);
01111 }
01112 
01113 /* Return 1 if OP is a signed comparison operation.  */
01114 
01115 int
01116 signed_comparison_operator (op, mode)
01117      register rtx op;
01118      enum machine_mode mode ATTRIBUTE_UNUSED;
01119 {
01120   enum rtx_code code = GET_CODE (op);
01121 
01122   if (mode != GET_MODE (op) && mode != VOIDmode)
01123     return 0;
01124 
01125   return (code == EQ || code == NE
01126     || code == LE || code == LT
01127     || code == GE || code == GT);
01128 }
01129 
01130 /* Return 1 if OP is a valid Alpha floating point comparison operator.
01131    Here we know which comparisons are valid in which insn.  */
01132 
01133 int
01134 alpha_fp_comparison_operator (op, mode)
01135      register rtx op;
01136      enum machine_mode mode;
01137 {
01138   enum rtx_code code = GET_CODE (op);
01139 
01140   if (mode != GET_MODE (op) && mode != VOIDmode)
01141     return 0;
01142 
01143   return (code == EQ || code == LE || code == LT || code == UNORDERED);
01144 }
01145 
01146 /* Return 1 if this is a divide or modulus operator.  */
01147 
01148 int
01149 divmod_operator (op, mode)
01150      register rtx op;
01151      enum machine_mode mode ATTRIBUTE_UNUSED;
01152 {
01153   switch (GET_CODE (op))
01154     {
01155     case DIV:  case MOD:  case UDIV:  case UMOD:
01156       return 1;
01157 
01158     default:
01159       break;
01160     }
01161 
01162   return 0;
01163 }
01164 
01165 /* Return 1 if this memory address is a known aligned register plus
01166    a constant.  It must be a valid address.  This means that we can do
01167    this as an aligned reference plus some offset.
01168 
01169    Take into account what reload will do.  */
01170 
01171 int
01172 aligned_memory_operand (op, mode)
01173      register rtx op;
01174      enum machine_mode mode;
01175 {
01176   rtx base;
01177 
01178   if (reload_in_progress)
01179     {
01180       rtx tmp = op;
01181       if (GET_CODE (tmp) == SUBREG)
01182   tmp = SUBREG_REG (tmp);
01183       if (GET_CODE (tmp) == REG
01184     && REGNO (tmp) >= FIRST_PSEUDO_REGISTER)
01185   {
01186     op = reg_equiv_memory_loc[REGNO (tmp)];
01187     if (op == 0)
01188       return 0;
01189   }
01190     }
01191 
01192   if (GET_CODE (op) != MEM
01193       || GET_MODE (op) != mode)
01194     return 0;
01195   op = XEXP (op, 0);
01196 
01197   /* LEGITIMIZE_RELOAD_ADDRESS creates (plus (plus reg const_hi) const_lo)
01198      sorts of constructs.  Dig for the real base register.  */
01199   if (reload_in_progress
01200       && GET_CODE (op) == PLUS
01201       && GET_CODE (XEXP (op, 0)) == PLUS)
01202     base = XEXP (XEXP (op, 0), 0);
01203   else
01204     {
01205       if (! memory_address_p (mode, op))
01206   return 0;
01207       base = (GET_CODE (op) == PLUS ? XEXP (op, 0) : op);
01208     }
01209 
01210   return (GET_CODE (base) == REG && REGNO_POINTER_ALIGN (REGNO (base)) >= 32);
01211 }
01212 
01213 /* Similar, but return 1 if OP is a MEM which is not alignable.  */
01214 
01215 int
01216 unaligned_memory_operand (op, mode)
01217      register rtx op;
01218      enum machine_mode mode;
01219 {
01220   rtx base;
01221 
01222   if (reload_in_progress)
01223     {
01224       rtx tmp = op;
01225       if (GET_CODE (tmp) == SUBREG)
01226   tmp = SUBREG_REG (tmp);
01227       if (GET_CODE (tmp) == REG
01228     && REGNO (tmp) >= FIRST_PSEUDO_REGISTER)
01229   {
01230     op = reg_equiv_memory_loc[REGNO (tmp)];
01231     if (op == 0)
01232       return 0;
01233   }
01234     }
01235 
01236   if (GET_CODE (op) != MEM
01237       || GET_MODE (op) != mode)
01238     return 0;
01239   op = XEXP (op, 0);
01240 
01241   /* LEGITIMIZE_RELOAD_ADDRESS creates (plus (plus reg const_hi) const_lo)
01242      sorts of constructs.  Dig for the real base register.  */
01243   if (reload_in_progress
01244       && GET_CODE (op) == PLUS
01245       && GET_CODE (XEXP (op, 0)) == PLUS)
01246     base = XEXP (XEXP (op, 0), 0);
01247   else
01248     {
01249       if (! memory_address_p (mode, op))
01250   return 0;
01251       base = (GET_CODE (op) == PLUS ? XEXP (op, 0) : op);
01252     }
01253 
01254   return (GET_CODE (base) == REG && REGNO_POINTER_ALIGN (REGNO (base)) < 32);
01255 }
01256 
01257 /* Return 1 if OP is either a register or an unaligned memory location.  */
01258 
01259 int
01260 reg_or_unaligned_mem_operand (op, mode)
01261      rtx op;
01262      enum machine_mode mode;
01263 {
01264   return register_operand (op, mode) || unaligned_memory_operand (op, mode);
01265 }
01266 
01267 /* Return 1 if OP is any memory location.  During reload a pseudo matches.  */
01268 
01269 int
01270 any_memory_operand (op, mode)
01271      register rtx op;
01272      enum machine_mode mode ATTRIBUTE_UNUSED;
01273 {
01274   return (GET_CODE (op) == MEM
01275     || (GET_CODE (op) == SUBREG && GET_CODE (SUBREG_REG (op)) == REG)
01276     || (reload_in_progress && GET_CODE (op) == REG
01277         && REGNO (op) >= FIRST_PSEUDO_REGISTER)
01278     || (reload_in_progress && GET_CODE (op) == SUBREG
01279         && GET_CODE (SUBREG_REG (op)) == REG
01280         && REGNO (SUBREG_REG (op)) >= FIRST_PSEUDO_REGISTER));
01281 }
01282 
01283 /* Returns 1 if OP is not an eliminable register.
01284 
01285    This exists to cure a pathological abort in the s8addq (et al) patterns,
01286 
01287   long foo () { long t; bar(); return (long) &t * 26107; }
01288 
01289    which run afoul of a hack in reload to cure a (presumably) similar
01290    problem with lea-type instructions on other targets.  But there is
01291    one of us and many of them, so work around the problem by selectively
01292    preventing combine from making the optimization.  */
01293 
01294 int
01295 reg_not_elim_operand (op, mode)
01296       register rtx op;
01297       enum machine_mode mode;
01298 {
01299   rtx inner = op;
01300   if (GET_CODE (op) == SUBREG)
01301     inner = SUBREG_REG (op);
01302   if (inner == frame_pointer_rtx || inner == arg_pointer_rtx)
01303     return 0;
01304 
01305   return register_operand (op, mode);
01306 }
01307 
01308 /* Return 1 is OP is a memory location that is not a reference (using
01309    an AND) to an unaligned location.  Take into account what reload
01310    will do.  */
01311 
01312 int
01313 normal_memory_operand (op, mode)
01314      register rtx op;
01315      enum machine_mode mode ATTRIBUTE_UNUSED;
01316 {
01317   if (reload_in_progress)
01318     {
01319       rtx tmp = op;
01320       if (GET_CODE (tmp) == SUBREG)
01321   tmp = SUBREG_REG (tmp);
01322       if (GET_CODE (tmp) == REG
01323     && REGNO (tmp) >= FIRST_PSEUDO_REGISTER)
01324   {
01325     op = reg_equiv_memory_loc[REGNO (tmp)];
01326 
01327     /* This may not have been assigned an equivalent address if it will
01328        be eliminated.  In that case, it doesn't matter what we do.  */
01329     if (op == 0)
01330       return 1;
01331   }
01332     }
01333 
01334   return GET_CODE (op) == MEM && GET_CODE (XEXP (op, 0)) != AND;
01335 }
01336 
01337 /* Accept a register, but not a subreg of any kind.  This allows us to
01338    avoid pathological cases in reload wrt data movement common in 
01339    int->fp conversion.  */
01340 
01341 int
01342 reg_no_subreg_operand (op, mode)
01343      register rtx op;
01344      enum machine_mode mode;
01345 {
01346   if (GET_CODE (op) != REG)
01347     return 0;
01348   return register_operand (op, mode);
01349 }
01350 
01351 /* Recognize an addition operation that includes a constant.  Used to
01352    convince reload to canonize (plus (plus reg c1) c2) during register
01353    elimination.  */
01354 
01355 int
01356 addition_operation (op, mode)
01357      register rtx op;
01358      enum machine_mode mode;
01359 {
01360   if (GET_MODE (op) != mode && mode != VOIDmode)
01361     return 0;
01362   if (GET_CODE (op) == PLUS
01363       && register_operand (XEXP (op, 0), mode)
01364       && GET_CODE (XEXP (op, 1)) == CONST_INT
01365       && CONST_OK_FOR_LETTER_P (INTVAL (XEXP (op, 1)), 'K'))
01366     return 1;
01367   return 0;
01368 }
01369 
01370 /* Implements CONST_OK_FOR_LETTER_P.  Return true if the value matches
01371    the range defined for C in [I-P].  */
01372 
01373 bool
01374 alpha_const_ok_for_letter_p (value, c)
01375      HOST_WIDE_INT value;
01376      int c;
01377 {
01378   switch (c)
01379     {
01380     case 'I':
01381       /* An unsigned 8 bit constant.  */
01382       return (unsigned HOST_WIDE_INT) value < 0x100;
01383     case 'J':
01384       /* The constant zero.  */
01385       return value == 0;
01386     case 'K':
01387       /* A signed 16 bit constant.  */
01388       return (unsigned HOST_WIDE_INT) (value + 0x8000) < 0x10000;
01389     case 'L':
01390       /* A shifted signed 16 bit constant appropriate for LDAH.  */
01391       return ((value & 0xffff) == 0
01392               && ((value) >> 31 == -1 || value >> 31 == 0));
01393     case 'M':
01394       /* A constant that can be AND'ed with using a ZAP insn.  */
01395       return zap_mask (value);
01396     case 'N':
01397       /* A complemented unsigned 8 bit constant.  */
01398       return (unsigned HOST_WIDE_INT) (~ value) < 0x100;
01399     case 'O':
01400       /* A negated unsigned 8 bit constant.  */
01401       return (unsigned HOST_WIDE_INT) (- value) < 0x100;
01402     case 'P':
01403       /* The constant 1, 2 or 3.  */
01404       return value == 1 || value == 2 || value == 3;
01405 
01406     default:
01407       return false;
01408     }
01409 }
01410 
01411 /* Implements CONST_DOUBLE_OK_FOR_LETTER_P.  Return true if VALUE
01412    matches for C in [GH].  */
01413 
01414 bool
01415 alpha_const_double_ok_for_letter_p (value, c)
01416      rtx value;
01417      int c;
01418 {
01419   switch (c)
01420     {
01421     case 'G':
01422       /* The floating point zero constant.  */
01423       return (GET_MODE_CLASS (GET_MODE (value)) == MODE_FLOAT
01424         && value == CONST0_RTX (GET_MODE (value)));
01425 
01426     case 'H':
01427       /* A valid operand of a ZAP insn.  */
01428       return (GET_MODE (value) == VOIDmode
01429         && zap_mask (CONST_DOUBLE_LOW (value))
01430         && zap_mask (CONST_DOUBLE_HIGH (value)));
01431 
01432     default:
01433       return false;
01434     }
01435 }
01436 
01437 /* Implements CONST_DOUBLE_OK_FOR_LETTER_P.  Return true if VALUE
01438    matches for C.  */
01439 
01440 bool
01441 alpha_extra_constraint (value, c)
01442      rtx value;
01443      int c;
01444 {
01445   switch (c)
01446     {
01447     case 'Q':
01448       return normal_memory_operand (value, VOIDmode);
01449     case 'R':
01450       return direct_call_operand (value, Pmode);
01451     case 'S':
01452       return (GET_CODE (value) == CONST_INT
01453         && (unsigned HOST_WIDE_INT) INTVAL (value) < 64);
01454     case 'T':
01455       return GET_CODE (value) == HIGH;
01456     case 'U':
01457       return TARGET_ABI_UNICOSMK && symbolic_operand (value, VOIDmode);
01458 
01459     default:
01460       return false;
01461     }
01462 }
01463 
01464 /* Return 1 if this function can directly return via $26.  */
01465 
01466 int
01467 direct_return ()
01468 {
01469   return (! TARGET_ABI_OPEN_VMS && ! TARGET_ABI_UNICOSMK
01470     && reload_completed
01471     && alpha_sa_size () == 0
01472     && get_frame_size () == 0
01473     && current_function_outgoing_args_size == 0
01474     && current_function_pretend_args_size == 0);
01475 }
01476 
01477 /* Return the ADDR_VEC associated with a tablejump insn.  */
01478 
01479 rtx
01480 alpha_tablejump_addr_vec (insn)
01481      rtx insn;
01482 {
01483   rtx tmp;
01484 
01485   tmp = JUMP_LABEL (insn);
01486   if (!tmp)
01487     return NULL_RTX;
01488   tmp = NEXT_INSN (tmp);
01489   if (!tmp)
01490     return NULL_RTX;
01491   if (GET_CODE (tmp) == JUMP_INSN
01492       && GET_CODE (PATTERN (tmp)) == ADDR_DIFF_VEC)
01493     return PATTERN (tmp);
01494   return NULL_RTX;
01495 }
01496 
01497 /* Return the label of the predicted edge, or CONST0_RTX if we don't know.  */
01498 
01499 rtx
01500 alpha_tablejump_best_label (insn)
01501      rtx insn;
01502 {
01503   rtx jump_table = alpha_tablejump_addr_vec (insn);
01504   rtx best_label = NULL_RTX;
01505 
01506   /* ??? Once the CFG doesn't keep getting completely rebuilt, look
01507      there for edge frequency counts from profile data.  */
01508 
01509   if (jump_table)
01510     {
01511       int n_labels = XVECLEN (jump_table, 1);
01512       int best_count = -1;
01513       int i, j;
01514 
01515       for (i = 0; i < n_labels; i++)
01516   {
01517     int count = 1;
01518 
01519     for (j = i + 1; j < n_labels; j++)
01520       if (XEXP (XVECEXP (jump_table, 1, i), 0)
01521     == XEXP (XVECEXP (jump_table, 1, j), 0))
01522         count++;
01523 
01524     if (count > best_count)
01525       best_count = count, best_label = XVECEXP (jump_table, 1, i);
01526   }
01527     }
01528 
01529   return best_label ? best_label : const0_rtx;
01530 }
01531 
01532 /* Return true if the function DECL will be placed in the default text
01533    section.  */
01534 /* ??? Ideally we'd be able to always move from a SYMBOL_REF back to the
01535    decl, as that would allow us to determine if two functions are in the
01536    same section, which is what we really want to know.  */
01537 
01538 static bool
01539 decl_in_text_section (decl)
01540      tree decl;
01541 {
01542   return (DECL_SECTION_NAME (decl) == NULL_TREE
01543     && ! (flag_function_sections
01544           || (targetm.have_named_sections
01545         && DECL_ONE_ONLY (decl))));
01546 }
01547 
01548 /* If we are referencing a function that is static, make the SYMBOL_REF
01549    special.  We use this to see indicate we can branch to this function
01550    without setting PV or restoring GP. 
01551 
01552    If this is a variable that is known to be defined locally, add "@v"
01553    to the name.  If in addition the variable is to go in .sdata/.sbss,
01554    then add "@s" instead.  */
01555 
01556 void
01557 alpha_encode_section_info (decl)
01558      tree decl;
01559 {
01560   const char *symbol_str;
01561   bool is_local, is_small;
01562 
01563   if (TREE_CODE (decl) == FUNCTION_DECL)
01564     {
01565       /* We mark public functions once they are emitted; otherwise we
01566    don't know that they exist in this unit of translation.  */
01567       if (TREE_PUBLIC (decl))
01568   return;
01569       /* Do not mark functions that are not in .text; otherwise we
01570    don't know that they are near enough for a direct branch.  */
01571       if (! decl_in_text_section (decl))
01572   return;
01573 
01574       SYMBOL_REF_FLAG (XEXP (DECL_RTL (decl), 0)) = 1;
01575       return;
01576     }
01577 
01578   /* Early out if we're not going to do anything with this data.  */
01579   if (! TARGET_EXPLICIT_RELOCS)
01580     return;
01581 
01582   /* Careful not to prod global register variables.  */
01583   if (TREE_CODE (decl) != VAR_DECL
01584       || GET_CODE (DECL_RTL (decl)) != MEM
01585       || GET_CODE (XEXP (DECL_RTL (decl), 0)) != SYMBOL_REF)
01586     return;
01587     
01588   symbol_str = XSTR (XEXP (DECL_RTL (decl), 0), 0);
01589 
01590   /* A variable is considered "local" if it is defined in this module.  */
01591 
01592   if (DECL_EXTERNAL (decl))
01593     is_local = false;
01594   /* Linkonce and weak data is never local.  */
01595   else if (DECL_ONE_ONLY (decl) || DECL_WEAK (decl))
01596     is_local = false;
01597   else if (! TREE_PUBLIC (decl))
01598     is_local = true;
01599   /* If PIC, then assume that any global name can be overridden by
01600      symbols resolved from other modules.  */
01601   else if (flag_pic)
01602     is_local = false;
01603   /* Uninitialized COMMON variable may be unified with symbols
01604      resolved from other modules.  */
01605   else if (DECL_COMMON (decl)
01606      && (DECL_INITIAL (decl) == NULL
01607          || DECL_INITIAL (decl) == error_mark_node))
01608     is_local = false;
01609   /* Otherwise we're left with initialized (or non-common) global data
01610      which is of necessity defined locally.  */
01611   else
01612     is_local = true;
01613 
01614   /* Determine if DECL will wind up in .sdata/.sbss.  */
01615 
01616   is_small = false;
01617   if (DECL_SECTION_NAME (decl))
01618     {
01619       const char *section = TREE_STRING_POINTER (DECL_SECTION_NAME (decl));
01620       if (strcmp (section, ".sdata") == 0
01621     || strcmp (section, ".sbss") == 0)
01622   is_small = true;
01623     }
01624   else
01625     {
01626       HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (decl));
01627 
01628       /* If the variable has already been defined in the output file, then it
01629    is too late to put it in sdata if it wasn't put there in the first
01630    place.  The test is here rather than above, because if it is already
01631    in sdata, then it can stay there.  */
01632 
01633       if (TREE_ASM_WRITTEN (decl))
01634   ;
01635 
01636       /* If this is an incomplete type with size 0, then we can't put it in
01637    sdata because it might be too big when completed.  */
01638       else if (size > 0 && size <= g_switch_value)
01639   is_small = true;
01640     }
01641 
01642   /* Finally, encode this into the symbol string.  */
01643   if (is_local)
01644     {
01645       const char *string;
01646       char *newstr;
01647       size_t len;
01648 
01649       if (symbol_str[0] == '@')
01650   {
01651     if (symbol_str[1] == (is_small ? 's' : 'v'))
01652       return;
01653     symbol_str += 2;
01654   }
01655 
01656       len = strlen (symbol_str) + 1;
01657       newstr = alloca (len + 2);
01658 
01659       newstr[0] = '@';
01660       newstr[1] = (is_small ? 's' : 'v');
01661       memcpy (newstr + 2, symbol_str, len);
01662     
01663       string = ggc_alloc_string (newstr, len + 2 - 1);
01664       XSTR (XEXP (DECL_RTL (decl), 0), 0) = string;
01665     }
01666   else if (symbol_str[0] == '@')
01667     {
01668       /* We're hosed.  This can happen when the user adds a weak
01669    attribute after rtl generation.  They should have gotten
01670    a warning about unspecified behaviour from varasm.c.  */
01671     }
01672 }
01673 
01674 /* legitimate_address_p recognizes an RTL expression that is a valid
01675    memory address for an instruction.  The MODE argument is the
01676    machine mode for the MEM expression that wants to use this address.
01677 
01678    For Alpha, we have either a constant address or the sum of a
01679    register and a constant address, or just a register.  For DImode,
01680    any of those forms can be surrounded with an AND that clear the
01681    low-order three bits; this is an "unaligned" access.  */
01682 
01683 bool
01684 alpha_legitimate_address_p (mode, x, strict)
01685      enum machine_mode mode;
01686      rtx x;
01687      int strict;
01688 {
01689   /* If this is an ldq_u type address, discard the outer AND.  */
01690   if (mode == DImode
01691       && GET_CODE (x) == AND
01692       && GET_CODE (XEXP (x, 1)) == CONST_INT
01693       && INTVAL (XEXP (x, 1)) == -8)
01694     x = XEXP (x, 0);
01695 
01696   /* Discard non-paradoxical subregs.  */
01697   if (GET_CODE (x) == SUBREG
01698       && (GET_MODE_SIZE (GET_MODE (x))
01699     < GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))))
01700     x = SUBREG_REG (x);
01701 
01702   /* Unadorned general registers are valid.  */
01703   if (REG_P (x)
01704       && (strict
01705     ? STRICT_REG_OK_FOR_BASE_P (x)
01706     : NONSTRICT_REG_OK_FOR_BASE_P (x)))
01707     return true;
01708 
01709   /* Constant addresses (i.e. +/- 32k) are valid.  */
01710   if (CONSTANT_ADDRESS_P (x))
01711     return true;
01712 
01713   /* Register plus a small constant offset is valid.  */
01714   if (GET_CODE (x) == PLUS)
01715     {
01716       rtx ofs = XEXP (x, 1);
01717       x = XEXP (x, 0);
01718 
01719       /* Discard non-paradoxical subregs.  */
01720       if (GET_CODE (x) == SUBREG
01721           && (GET_MODE_SIZE (GET_MODE (x))
01722         < GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))))
01723   x = SUBREG_REG (x);
01724 
01725       if (REG_P (x))
01726   {
01727     if (! strict
01728         && NONSTRICT_REG_OK_FP_BASE_P (x)
01729         && GET_CODE (ofs) == CONST_INT)
01730       return true;
01731     if ((strict
01732          ? STRICT_REG_OK_FOR_BASE_P (x)
01733          : NONSTRICT_REG_OK_FOR_BASE_P (x))
01734         && CONSTANT_ADDRESS_P (ofs))
01735       return true;
01736   }
01737       else if (GET_CODE (x) == ADDRESSOF
01738          && GET_CODE (ofs) == CONST_INT)
01739   return true;
01740     }
01741 
01742   /* If we're managing explicit relocations, LO_SUM is valid, as
01743      are small data symbols.  */
01744   else if (TARGET_EXPLICIT_RELOCS)
01745     {
01746       if (small_symbolic_operand (x, Pmode))
01747   return true;
01748 
01749       if (GET_CODE (x) == LO_SUM)
01750   {
01751     rtx ofs = XEXP (x, 1);
01752     x = XEXP (x, 0);
01753 
01754     /* Discard non-paradoxical subregs.  */
01755     if (GET_CODE (x) == SUBREG
01756         && (GET_MODE_SIZE (GET_MODE (x))
01757       < GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))))
01758       x = SUBREG_REG (x);
01759 
01760     /* Must have a valid base register.  */
01761     if (! (REG_P (x)
01762      && (strict
01763          ? STRICT_REG_OK_FOR_BASE_P (x)
01764          : NONSTRICT_REG_OK_FOR_BASE_P (x))))
01765       return false;
01766 
01767     /* The symbol must be local.  */
01768     if (local_symbolic_operand (ofs, Pmode))
01769       return true;
01770   }
01771     }
01772 
01773   return false;
01774 }
01775 
01776 /* Try machine-dependent ways of modifying an illegitimate address
01777    to be legitimate.  If we find one, return the new, valid address.  */
01778 
01779 rtx
01780 alpha_legitimize_address (x, scratch, mode)
01781      rtx x;
01782      rtx scratch;
01783      enum machine_mode mode ATTRIBUTE_UNUSED;
01784 {
01785   HOST_WIDE_INT addend;
01786 
01787   /* If the address is (plus reg const_int) and the CONST_INT is not a
01788      valid offset, compute the high part of the constant and add it to
01789      the register.  Then our address is (plus temp low-part-const).  */
01790   if (GET_CODE (x) == PLUS
01791       && GET_CODE (XEXP (x, 0)) == REG
01792       && GET_CODE (XEXP (x, 1)) == CONST_INT
01793       && ! CONSTANT_ADDRESS_P (XEXP (x, 1)))
01794     {
01795       addend = INTVAL (XEXP (x, 1));
01796       x = XEXP (x, 0);
01797       goto split_addend;
01798     }
01799 
01800   /* If the address is (const (plus FOO const_int)), find the low-order
01801      part of the CONST_INT.  Then load FOO plus any high-order part of the
01802      CONST_INT into a register.  Our address is (plus reg low-part-const).
01803      This is done to reduce the number of GOT entries.  */
01804   if (!no_new_pseudos
01805       && GET_CODE (x) == CONST
01806       && GET_CODE (XEXP (x, 0)) == PLUS
01807       && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT)
01808     {
01809       addend = INTVAL (XEXP (XEXP (x, 0), 1));
01810       x = force_reg (Pmode, XEXP (XEXP (x, 0), 0));
01811       goto split_addend;
01812     }
01813 
01814   /* If we have a (plus reg const), emit the load as in (2), then add
01815      the two registers, and finally generate (plus reg low-part-const) as
01816      our address.  */
01817   if (!no_new_pseudos
01818       && GET_CODE (x) == PLUS
01819       && GET_CODE (XEXP (x, 0)) == REG
01820       && GET_CODE (XEXP (x, 1)) == CONST
01821       && GET_CODE (XEXP (XEXP (x, 1), 0)) == PLUS
01822       && GET_CODE (XEXP (XEXP (XEXP (x, 1), 0), 1)) == CONST_INT)
01823     {
01824       addend = INTVAL (XEXP (XEXP (XEXP (x, 1), 0), 1));
01825       x = expand_simple_binop (Pmode, PLUS, XEXP (x, 0),
01826              XEXP (XEXP (XEXP (x, 1), 0), 0),
01827              NULL_RTX, 1, OPTAB_LIB_WIDEN);
01828       goto split_addend;
01829     }
01830 
01831   /* If this is a local symbol, split the address into HIGH/LO_SUM parts.  */
01832   if (TARGET_EXPLICIT_RELOCS && symbolic_operand (x, Pmode))
01833     {
01834       if (local_symbolic_operand (x, Pmode))
01835   {
01836     if (small_symbolic_operand (x, Pmode))
01837       return x;
01838     else
01839       {
01840         if (!no_new_pseudos)
01841           scratch = gen_reg_rtx (Pmode);
01842         emit_insn (gen_rtx_SET (VOIDmode, scratch,
01843               gen_rtx_HIGH (Pmode, x)));
01844         return gen_rtx_LO_SUM (Pmode, scratch, x);
01845       }
01846   }
01847     }
01848 
01849   return NULL;
01850 
01851  split_addend:
01852   {
01853     HOST_WIDE_INT low, high;
01854 
01855     low = ((addend & 0xffff) ^ 0x8000) - 0x8000;
01856     addend -= low;
01857     high = ((addend & 0xffffffff) ^ 0x80000000) - 0x80000000;
01858     addend -= high;
01859 
01860     if (addend)
01861       x = expand_simple_binop (Pmode, PLUS, x, GEN_INT (addend),
01862              (no_new_pseudos ? scratch : NULL_RTX),
01863              1, OPTAB_LIB_WIDEN);
01864     if (high)
01865       x = expand_simple_binop (Pmode, PLUS, x, GEN_INT (high),
01866              (no_new_pseudos ? scratch : NULL_RTX),
01867              1, OPTAB_LIB_WIDEN);
01868 
01869     return plus_constant (x, low);
01870   }
01871 }
01872 
01873 /* For TARGET_EXPLICIT_RELOCS, we don't obfuscate a SYMBOL_REF to a
01874    small symbolic operand until after reload.  At which point we need
01875    to replace (mem (symbol_ref)) with (mem (lo_sum $29 symbol_ref))
01876    so that sched2 has the proper dependency information.  */
01877 
01878 int
01879 some_small_symbolic_operand (x, mode)
01880      rtx x;
01881      enum machine_mode mode ATTRIBUTE_UNUSED;
01882 {
01883   return for_each_rtx (&x, some_small_symbolic_operand_1, NULL);
01884 }
01885 
01886 static int
01887 some_small_symbolic_operand_1 (px, data)
01888      rtx *px;
01889      void *data ATTRIBUTE_UNUSED;
01890 {
01891   rtx x = *px;
01892 
01893   /* Don't re-split.  */
01894   if (GET_CODE (x) == LO_SUM)
01895     return -1;
01896 
01897   return small_symbolic_operand (x, Pmode) != 0;
01898 }
01899 
01900 rtx
01901 split_small_symbolic_operand (x)
01902      rtx x;
01903 {
01904   x = copy_insn (x);
01905   for_each_rtx (&x, split_small_symbolic_operand_1, NULL);
01906   return x;
01907 }
01908 
01909 static int
01910 split_small_symbolic_operand_1 (px, data)
01911      rtx *px;
01912      void *data ATTRIBUTE_UNUSED;
01913 {
01914   rtx x = *px;
01915 
01916   /* Don't re-split.  */
01917   if (GET_CODE (x) == LO_SUM)
01918     return -1;
01919 
01920   if (small_symbolic_operand (x, Pmode))
01921     {
01922       x = gen_rtx_LO_SUM (Pmode, pic_offset_table_rtx, x);
01923       *px = x;
01924       return -1;
01925     }
01926 
01927   return 0;
01928 }
01929 
01930 /* Try a machine-dependent way of reloading an illegitimate address
01931    operand.  If we find one, push the reload and return the new rtx.  */
01932    
01933 rtx
01934 alpha_legitimize_reload_address (x, mode, opnum, type, ind_levels)
01935      rtx x;
01936      enum machine_mode mode ATTRIBUTE_UNUSED;
01937      int opnum;
01938      int type;
01939      int ind_levels ATTRIBUTE_UNUSED;
01940 {
01941   /* We must recognize output that we have already generated ourselves.  */
01942   if (GET_CODE (x) == PLUS
01943       && GET_CODE (XEXP (x, 0)) == PLUS
01944       && GET_CODE (XEXP (XEXP (x, 0), 0)) == REG
01945       && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
01946       && GET_CODE (XEXP (x, 1)) == CONST_INT)
01947     {
01948       push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL,
01949        BASE_REG_CLASS, GET_MODE (x), VOIDmode, 0, 0,
01950        opnum, type);
01951       return x;
01952     }
01953 
01954   /* We wish to handle large displacements off a base register by
01955      splitting the addend across an ldah and the mem insn.  This
01956      cuts number of extra insns needed from 3 to 1.  */
01957   if (GET_CODE (x) == PLUS
01958       && GET_CODE (XEXP (x, 0)) == REG
01959       && REGNO (XEXP (x, 0)) < FIRST_PSEUDO_REGISTER
01960       && REGNO_OK_FOR_BASE_P (REGNO (XEXP (x, 0)))
01961       && GET_CODE (XEXP (x, 1)) == CONST_INT)
01962     {
01963       HOST_WIDE_INT val = INTVAL (XEXP (x, 1));
01964       HOST_WIDE_INT low = ((val & 0xffff) ^ 0x8000) - 0x8000;
01965       HOST_WIDE_INT high
01966   = (((val - low) & 0xffffffff) ^ 0x80000000) - 0x80000000;
01967 
01968       /* Check for 32-bit overflow.  */
01969       if (high + low != val)
01970   return NULL_RTX;
01971 
01972       /* Reload the high part into a base reg; leave the low part
01973    in the mem directly.  */
01974       x = gen_rtx_PLUS (GET_MODE (x),
01975       gen_rtx_PLUS (GET_MODE (x), XEXP (x, 0),
01976               GEN_INT (high)),
01977       GEN_INT (low));
01978 
01979       push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL,
01980        BASE_REG_CLASS, GET_MODE (x), VOIDmode, 0, 0,
01981        opnum, type);
01982       return x;
01983     }
01984 
01985   return NULL_RTX;
01986 }
01987 
01988 /* REF is an alignable memory location.  Place an aligned SImode
01989    reference into *PALIGNED_MEM and the number of bits to shift into
01990    *PBITNUM.  SCRATCH is a free register for use in reloading out
01991    of range stack slots.  */
01992 
01993 void
01994 get_aligned_mem (ref, paligned_mem, pbitnum)
01995      rtx ref;
01996      rtx *paligned_mem, *pbitnum;
01997 {
01998   rtx base;
01999   HOST_WIDE_INT offset = 0;
02000 
02001   if (GET_CODE (ref) != MEM)
02002     abort ();
02003 
02004   if (reload_in_progress
02005       && ! memory_address_p (GET_MODE (ref), XEXP (ref, 0)))
02006     {
02007       base = find_replacement (&XEXP (ref, 0));
02008 
02009       if (! memory_address_p (GET_MODE (ref), base))
02010   abort ();
02011     }
02012   else
02013     {
02014       base = XEXP (ref, 0);
02015     }
02016 
02017   if (GET_CODE (base) == PLUS)
02018     offset += INTVAL (XEXP (base, 1)), base = XEXP (base, 0);
02019 
02020   *paligned_mem
02021     = widen_memory_access (ref, SImode, (offset & ~3) - offset);
02022 
02023   if (WORDS_BIG_ENDIAN)
02024     *pbitnum = GEN_INT (32 - (GET_MODE_BITSIZE (GET_MODE (ref))
02025             + (offset & 3) * 8));
02026   else
02027     *pbitnum = GEN_INT ((offset & 3) * 8);
02028 }
02029 
02030 /* Similar, but just get the address.  Handle the two reload cases.  
02031    Add EXTRA_OFFSET to the address we return.  */
02032 
02033 rtx
02034 get_unaligned_address (ref, extra_offset)
02035      rtx ref;
02036      int extra_offset;
02037 {
02038   rtx base;
02039   HOST_WIDE_INT offset = 0;
02040 
02041   if (GET_CODE (ref) != MEM)
02042     abort ();
02043 
02044   if (reload_in_progress
02045       && ! memory_address_p (GET_MODE (ref), XEXP (ref, 0)))
02046     {
02047       base = find_replacement (&XEXP (ref, 0));
02048 
02049       if (! memory_address_p (GET_MODE (ref), base))
02050   abort ();
02051     }
02052   else
02053     {
02054       base = XEXP (ref, 0);
02055     }
02056 
02057   if (GET_CODE (base) == PLUS)
02058     offset += INTVAL (XEXP (base, 1)), base = XEXP (base, 0);
02059 
02060   return plus_constant (base, offset + extra_offset);
02061 }
02062 
02063 /* On the Alpha, all (non-symbolic) constants except zero go into
02064    a floating-point register via memory.  Note that we cannot 
02065    return anything that is not a subset of CLASS, and that some
02066    symbolic constants cannot be dropped to memory.  */
02067 
02068 enum reg_class
02069 alpha_preferred_reload_class(x, class)
02070      rtx x;
02071      enum reg_class class;
02072 {
02073   /* Zero is present in any register class.  */
02074   if (x == CONST0_RTX (GET_MODE (x)))
02075     return class;
02076 
02077   /* These sorts of constants we can easily drop to memory.  */
02078   if (GET_CODE (x) == CONST_INT || GET_CODE (x) == CONST_DOUBLE)
02079     {
02080       if (class == FLOAT_REGS)
02081   return NO_REGS;
02082       if (class == ALL_REGS)
02083   return GENERAL_REGS;
02084       return class;
02085     }
02086 
02087   /* All other kinds of constants should not (and in the case of HIGH
02088      cannot) be dropped to memory -- instead we use a GENERAL_REGS
02089      secondary reload.  */
02090   if (CONSTANT_P (x))
02091     return (class == ALL_REGS ? GENERAL_REGS : class);
02092 
02093   return class;
02094 }
02095 
02096 /* Loading and storing HImode or QImode values to and from memory
02097    usually requires a scratch register.  The exceptions are loading
02098    QImode and HImode from an aligned address to a general register
02099    unless byte instructions are permitted. 
02100 
02101    We also cannot load an unaligned address or a paradoxical SUBREG
02102    into an FP register. 
02103 
02104    We also cannot do integral arithmetic into FP regs, as might result
02105    from register elimination into a DImode fp register.  */
02106 
02107 enum reg_class
02108 secondary_reload_class (class, mode, x, in)
02109      enum reg_class class;
02110      enum machine_mode mode;
02111      rtx x;
02112      int in;
02113 {
02114   if ((mode == QImode || mode == HImode) && ! TARGET_BWX)
02115     {
02116       if (GET_CODE (x) == MEM
02117     || (GET_CODE (x) == REG && REGNO (x) >= FIRST_PSEUDO_REGISTER)
02118     || (GET_CODE (x) == SUBREG
02119         && (GET_CODE (SUBREG_REG (x)) == MEM
02120       || (GET_CODE (SUBREG_REG (x)) == REG
02121           && REGNO (SUBREG_REG (x)) >= FIRST_PSEUDO_REGISTER))))
02122   {
02123     if (!in || !aligned_memory_operand(x, mode))
02124       return GENERAL_REGS;
02125   }
02126     }
02127 
02128   if (class == FLOAT_REGS)
02129     {
02130       if (GET_CODE (x) == MEM && GET_CODE (XEXP (x, 0)) == AND)
02131   return GENERAL_REGS;
02132 
02133       if (GET_CODE (x) == SUBREG
02134     && (GET_MODE_SIZE (GET_MODE (x))
02135         > GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))))
02136   return GENERAL_REGS;
02137 
02138       if (in && INTEGRAL_MODE_P (mode)
02139     && ! (memory_operand (x, mode) || x == const0_rtx))
02140   return GENERAL_REGS;
02141     }
02142 
02143   return NO_REGS;
02144 }
02145 
02146 /* Subfunction of the following function.  Update the flags of any MEM
02147    found in part of X.  */
02148 
02149 static void
02150 alpha_set_memflags_1 (x, in_struct_p, volatile_p, unchanging_p)
02151      rtx x;
02152      int in_struct_p, volatile_p, unchanging_p;
02153 {
02154   int i;
02155 
02156   switch (GET_CODE (x))
02157     {
02158     case SEQUENCE:
02159     case PARALLEL:
02160       for (i = XVECLEN (x, 0) - 1; i >= 0; i--)
02161   alpha_set_memflags_1 (XVECEXP (x, 0, i), in_struct_p, volatile_p,
02162             unchanging_p);
02163       break;
02164 
02165     case INSN:
02166       alpha_set_memflags_1 (PATTERN (x), in_struct_p, volatile_p,
02167           unchanging_p);
02168       break;
02169 
02170     case SET:
02171       alpha_set_memflags_1 (SET_DEST (x), in_struct_p, volatile_p,
02172           unchanging_p);
02173       alpha_set_memflags_1 (SET_SRC (x), in_struct_p, volatile_p,
02174           unchanging_p);
02175       break;
02176 
02177     case MEM:
02178       MEM_IN_STRUCT_P (x) = in_struct_p;
02179       MEM_VOLATILE_P (x) = volatile_p;
02180       RTX_UNCHANGING_P (x) = unchanging_p;
02181       /* Sadly, we cannot use alias sets because the extra aliasing
02182    produced by the AND interferes.  Given that two-byte quantities
02183    are the only thing we would be able to differentiate anyway,
02184    there does not seem to be any point in convoluting the early
02185    out of the alias check.  */
02186       break;
02187 
02188     default:
02189       break;
02190     }
02191 }
02192 
02193 /* Given INSN, which is either an INSN or a SEQUENCE generated to
02194    perform a memory operation, look for any MEMs in either a SET_DEST or
02195    a SET_SRC and copy the in-struct, unchanging, and volatile flags from
02196    REF into each of the MEMs found.  If REF is not a MEM, don't do
02197    anything.  */
02198 
02199 void
02200 alpha_set_memflags (insn, ref)
02201      rtx insn;
02202      rtx ref;
02203 {
02204   int in_struct_p, volatile_p, unchanging_p;
02205 
02206   if (GET_CODE (ref) != MEM)
02207     return;
02208 
02209   in_struct_p = MEM_IN_STRUCT_P (ref);
02210   volatile_p = MEM_VOLATILE_P (ref);
02211   unchanging_p = RTX_UNCHANGING_P (ref);
02212 
02213   /* This is only called from alpha.md, after having had something 
02214      generated from one of the insn patterns.  So if everything is
02215      zero, the pattern is already up-to-date.  */
02216   if (! in_struct_p && ! volatile_p && ! unchanging_p)
02217     return;
02218 
02219   alpha_set_memflags_1 (insn, in_struct_p, volatile_p, unchanging_p);
02220 }
02221 
02222 /* Try to output insns to set TARGET equal to the constant C if it can be
02223    done in less than N insns.  Do all computations in MODE.  Returns the place
02224    where the output has been placed if it can be done and the insns have been
02225    emitted.  If it would take more than N insns, zero is returned and no
02226    insns and emitted.  */
02227 
02228 rtx
02229 alpha_emit_set_const (target, mode, c, n)
02230      rtx target;
02231      enum machine_mode mode;
02232      HOST_WIDE_INT c;
02233      int n;
02234 {
02235   rtx result = 0;
02236   rtx orig_target = target;
02237   int i;
02238 
02239   /* If we can't make any pseudos, TARGET is an SImode hard register, we
02240      can't load this constant in one insn, do this in DImode.  */
02241   if (no_new_pseudos && mode == SImode
02242       && GET_CODE (target) == REG && REGNO (target) < FIRST_PSEUDO_REGISTER
02243       && (result = alpha_emit_set_const_1 (target, mode, c, 1)) == 0)
02244     {
02245       target = gen_lowpart (DImode, target);
02246       mode = DImode;
02247     }
02248 
02249   /* Try 1 insn, then 2, then up to N.  */
02250   for (i = 1; i <= n; i++)
02251     {
02252       result = alpha_emit_set_const_1 (target, mode, c, i);
02253       if (result)
02254   {
02255     rtx insn = get_last_insn ();
02256     rtx set = single_set (insn);
02257     if (! CONSTANT_P (SET_SRC (set)))
02258       set_unique_reg_note (get_last_insn (), REG_EQUAL, GEN_INT (c));
02259     break;
02260   }
02261     }
02262 
02263   /* Allow for the case where we changed the mode of TARGET.  */
02264   if (result == target)
02265     result = orig_target;
02266 
02267   return result;
02268 }
02269 
02270 /* Internal routine for the above to check for N or below insns.  */
02271 
02272 static rtx
02273 alpha_emit_set_const_1 (target, mode, c, n)
02274      rtx target;
02275      enum machine_mode mode;
02276      HOST_WIDE_INT c;
02277      int n;
02278 {
02279   HOST_WIDE_INT new;
02280   int i, bits;
02281   /* Use a pseudo if highly optimizing and still generating RTL.  */
02282   rtx subtarget
02283     = (flag_expensive_optimizations && !no_new_pseudos ? 0 : target);
02284   rtx temp, insn;
02285 
02286   /* If this is a sign-extended 32-bit constant, we can do this in at most
02287      three insns, so do it if we have enough insns left.  We always have
02288      a sign-extended 32-bit constant when compiling on a narrow machine.  */
02289 
02290   if (HOST_BITS_PER_WIDE_INT != 64
02291       || c >> 31 == -1 || c >> 31 == 0)
02292     {
02293       HOST_WIDE_INT low = ((c & 0xffff) ^ 0x8000) - 0x8000;
02294       HOST_WIDE_INT tmp1 = c - low;
02295       HOST_WIDE_INT high = (((tmp1 >> 16) & 0xffff) ^ 0x8000) - 0x8000;
02296       HOST_WIDE_INT extra = 0;
02297 
02298       /* If HIGH will be interpreted as negative but the constant is
02299    positive, we must adjust it to do two ldha insns.  */
02300 
02301       if ((high & 0x8000) != 0 && c >= 0)
02302   {
02303     extra = 0x4000;
02304     tmp1 -= 0x40000000;
02305     high = ((tmp1 >> 16) & 0xffff) - 2 * ((tmp1 >> 16) & 0x8000);
02306   }
02307 
02308       if (c == low || (low == 0 && extra == 0))
02309   {
02310     /* We used to use copy_to_suggested_reg (GEN_INT (c), target, mode)
02311        but that meant that we can't handle INT_MIN on 32-bit machines
02312        (like NT/Alpha), because we recurse indefinitely through 
02313        emit_move_insn to gen_movdi.  So instead, since we know exactly
02314        what we want, create it explicitly.  */
02315 
02316     if (target == NULL)
02317       target = gen_reg_rtx (mode);
02318     emit_insn (gen_rtx_SET (VOIDmode, target, GEN_INT (c)));
02319     return target;
02320   }
02321       else if (n >= 2 + (extra != 0))
02322   {
02323     temp = copy_to_suggested_reg (GEN_INT (high << 16), subtarget, mode);
02324 
02325     /* As of 2002-02-23, addsi3 is only available when not optimizing.
02326        This means that if we go through expand_binop, we'll try to
02327        generate extensions, etc, which will require new pseudos, which
02328        will fail during some split phases.  The SImode add patterns
02329        still exist, but are not named.  So build the insns by hand.  */
02330 
02331     if (extra != 0)
02332       {
02333         if (! subtarget)
02334     subtarget = gen_reg_rtx (mode);
02335         insn = gen_rtx_PLUS (mode, temp, GEN_INT (extra << 16));
02336         insn = gen_rtx_SET (VOIDmode, subtarget, insn);
02337         emit_insn (insn);
02338         temp = subtarget;
02339       }
02340 
02341     if (target == NULL)
02342       target = gen_reg_rtx (mode);
02343     insn = gen_rtx_PLUS (mode, temp, GEN_INT (low));
02344     insn = gen_rtx_SET (VOIDmode, target, insn);
02345     emit_insn (insn);
02346     return target;
02347   }
02348     }
02349 
02350   /* If we couldn't do it that way, try some other methods.  But if we have
02351      no instructions left, don't bother.  Likewise, if this is SImode and
02352      we can't make pseudos, we can't do anything since the expand_binop
02353      and expand_unop calls will widen and try to make pseudos.  */
02354 
02355   if (n == 1 || (mode == SImode && no_new_pseudos))
02356     return 0;
02357 
02358   /* Next, see if we can load a related constant and then shift and possibly
02359      negate it to get the constant we want.  Try this once each increasing
02360      numbers of insns.  */
02361 
02362   for (i = 1; i < n; i++)
02363     {
02364       /* First, see if minus some low bits, we've an easy load of
02365    high bits.  */
02366 
02367       new = ((c & 0xffff) ^ 0x8000) - 0x8000;
02368       if (new != 0
02369           && (temp = alpha_emit_set_const (subtarget, mode, c - new, i)) != 0)
02370   return expand_binop (mode, add_optab, temp, GEN_INT (new),
02371            target, 0, OPTAB_WIDEN);
02372 
02373       /* Next try complementing.  */
02374       if ((temp = alpha_emit_set_const (subtarget, mode, ~ c, i)) != 0)
02375   return expand_unop (mode, one_cmpl_optab, temp, target, 0);
02376 
02377       /* Next try to form a constant and do a left shift.  We can do this
02378    if some low-order bits are zero; the exact_log2 call below tells
02379    us that information.  The bits we are shifting out could be any
02380    value, but here we'll just try the 0- and sign-extended forms of
02381    the constant.  To try to increase the chance of having the same
02382    constant in more than one insn, start at the highest number of
02383    bits to shift, but try all possibilities in case a ZAPNOT will
02384    be useful.  */
02385 
02386       if ((bits = exact_log2 (c & - c)) > 0)
02387   for (; bits > 0; bits--)
02388     if ((temp = (alpha_emit_set_const
02389            (subtarget, mode, c >> bits, i))) != 0
02390         || ((temp = (alpha_emit_set_const
02391         (subtarget, mode,
02392          ((unsigned HOST_WIDE_INT) c) >> bits, i)))
02393       != 0))
02394       return expand_binop (mode, ashl_optab, temp, GEN_INT (bits),
02395          target, 0, OPTAB_WIDEN);
02396 
02397       /* Now try high-order zero bits.  Here we try the shifted-in bits as
02398    all zero and all ones.  Be careful to avoid shifting outside the
02399    mode and to avoid shifting outside the host wide int size.  */
02400       /* On narrow hosts, don't shift a 1 into the high bit, since we'll
02401    confuse the recursive call and set all of the high 32 bits.  */
02402 
02403       if ((bits = (MIN (HOST_BITS_PER_WIDE_INT, GET_MODE_SIZE (mode) * 8)
02404        - floor_log2 (c) - 1 - (HOST_BITS_PER_WIDE_INT < 64))) > 0)
02405   for (; bits > 0; bits--)
02406     if ((temp = alpha_emit_set_const (subtarget, mode,
02407               c << bits, i)) != 0
02408         || ((temp = (alpha_emit_set_const
02409          (subtarget, mode,
02410           ((c << bits) | (((HOST_WIDE_INT) 1 << bits) - 1)),
02411           i)))
02412       != 0))
02413       return expand_binop (mode, lshr_optab, temp, GEN_INT (bits),
02414          target, 1, OPTAB_WIDEN);
02415 
02416       /* Now try high-order 1 bits.  We get that with a sign-extension.
02417    But one bit isn't enough here.  Be careful to avoid shifting outside
02418    the mode and to avoid shifting outside the host wide int size.  */
02419 
02420       if ((bits = (MIN (HOST_BITS_PER_WIDE_INT, GET_MODE_SIZE (mode) * 8)
02421        - floor_log2 (~ c) - 2)) > 0)
02422   for (; bits > 0; bits--)
02423     if ((temp = alpha_emit_set_const (subtarget, mode,
02424               c << bits, i)) != 0
02425         || ((temp = (alpha_emit_set_const
02426          (subtarget, mode,
02427           ((c << bits) | (((HOST_WIDE_INT) 1 << bits) - 1)),
02428           i)))
02429       != 0))
02430       return expand_binop (mode, ashr_optab, temp, GEN_INT (bits),
02431          target, 0, OPTAB_WIDEN);
02432     }
02433 
02434 #if HOST_BITS_PER_WIDE_INT == 64
02435   /* Finally, see if can load a value into the target that is the same as the
02436      constant except that all bytes that are 0 are changed to be 0xff.  If we
02437      can, then we can do a ZAPNOT to obtain the desired constant.  */
02438 
02439   new = c;
02440   for (i = 0; i < 64; i += 8)
02441     if ((new & ((HOST_WIDE_INT) 0xff << i)) == 0)
02442       new |= (HOST_WIDE_INT) 0xff << i;
02443 
02444   /* We are only called for SImode and DImode.  If this is SImode, ensure that
02445      we are sign extended to a full word.  */
02446 
02447   if (mode == SImode)
02448     new = ((new & 0xffffffff) ^ 0x80000000) - 0x80000000;
02449 
02450   if (new != c && new != -1
02451       && (temp = alpha_emit_set_const (subtarget, mode, new, n - 1)) != 0)
02452     return expand_binop (mode, and_optab, temp, GEN_INT (c | ~ new),
02453        target, 0, OPTAB_WIDEN);
02454 #endif
02455 
02456   return 0;
02457 }
02458 
02459 /* Having failed to find a 3 insn sequence in alpha_emit_set_const,
02460    fall back to a straight forward decomposition.  We do this to avoid
02461    exponential run times encountered when looking for longer sequences
02462    with alpha_emit_set_const.  */
02463 
02464 rtx
02465 alpha_emit_set_long_const (target, c1, c2)
02466      rtx target;
02467      HOST_WIDE_INT c1, c2;
02468 {
02469   HOST_WIDE_INT d1, d2, d3, d4;
02470 
02471   /* Decompose the entire word */
02472 #if HOST_BITS_PER_WIDE_INT >= 64
02473   if (c2 != -(c1 < 0))
02474     abort ();
02475   d1 = ((c1 & 0xffff) ^ 0x8000) - 0x8000;
02476   c1 -= d1;
02477   d2 = ((c1 & 0xffffffff) ^ 0x80000000) - 0x80000000;
02478   c1 = (c1 - d2) >> 32;
02479   d3 = ((c1 & 0xffff) ^ 0x8000) - 0x8000;
02480   c1 -= d3;
02481   d4 = ((c1 & 0xffffffff) ^ 0x80000000) - 0x80000000;
02482   if (c1 != d4)
02483     abort ();
02484 #else
02485   d1 = ((c1 & 0xffff) ^ 0x8000) - 0x8000;
02486   c1 -= d1;
02487   d2 = ((c1 & 0xffffffff) ^ 0x80000000) - 0x80000000;
02488   if (c1 != d2)
02489     abort ();
02490   c2 += (d2 < 0);
02491   d3 = ((c2 & 0xffff) ^ 0x8000) - 0x8000;
02492   c2 -= d3;
02493   d4 = ((c2 & 0xffffffff) ^ 0x80000000) - 0x80000000;
02494   if (c2 != d4)
02495     abort ();
02496 #endif
02497 
02498   /* Construct the high word */
02499   if (d4)
02500     {
02501       emit_move_insn (target, GEN_INT (d4));
02502       if (d3)
02503   emit_move_insn (target, gen_rtx_PLUS (DImode, target, GEN_INT (d3)));
02504     }
02505   else
02506     emit_move_insn (target, GEN_INT (d3));
02507 
02508   /* Shift it into place */
02509   emit_move_insn (target, gen_rtx_ASHIFT (DImode, target, GEN_INT (32)));
02510 
02511   /* Add in the low bits.  */
02512   if (d2)
02513     emit_move_insn (target, gen_rtx_PLUS (DImode, target, GEN_INT (d2)));
02514   if (d1)
02515     emit_move_insn (target, gen_rtx_PLUS (DImode, target, GEN_INT (d1)));
02516 
02517   return target;
02518 }
02519 
02520 /* Expand a move instruction; return true if all work is done.
02521    We don't handle non-bwx subword loads here.  */
02522 
02523 bool
02524 alpha_expand_mov (mode, operands)
02525      enum machine_mode mode;
02526      rtx *operands;
02527 {
02528   /* If the output is not a register, the input must be.  */
02529   if (GET_CODE (operands[0]) == MEM
02530       && ! reg_or_0_operand (operands[1], mode))
02531     operands[1] = force_reg (mode, operands[1]);
02532 
02533   /* Allow legitimize_address to perform some simplifications.  */
02534   if (mode == Pmode && symbolic_operand (operands[1], mode))
02535     {
02536       rtx tmp;
02537 
02538       /* With RTL inlining, at -O3, rtl is generated, stored, then actually
02539    compiled at the end of compilation.  In the meantime, someone can
02540    re-encode-section-info on some symbol changing it e.g. from global
02541    to local-not-small.  If this happens, we'd have emitted a plain
02542    load rather than a high+losum load and not recognize the insn.
02543 
02544    So if rtl inlining is in effect, we delay the global/not-global
02545    decision until rest_of_compilation by wrapping it in an
02546    UNSPEC_SYMBOL.  */
02547       if (TARGET_EXPLICIT_RELOCS && flag_inline_functions
02548     && rtx_equal_function_value_matters
02549     && global_symbolic_operand (operands[1], mode))
02550   {
02551     emit_insn (gen_movdi_er_maybe_g (operands[0], operands[1]));
02552     return true;
02553   }
02554 
02555       tmp = alpha_legitimize_address (operands[1], operands[0], mode);
02556       if (tmp)
02557   {
02558     operands[1] = tmp;
02559     return false;
02560   }
02561     }
02562 
02563   /* Early out for non-constants and valid constants.  */
02564   if (! CONSTANT_P (operands[1]) || input_operand (operands[1], mode))
02565     return false;
02566 
02567   /* Split large integers.  */
02568   if (GET_CODE (operands[1]) == CONST_INT
02569       || GET_CODE (operands[1]) == CONST_DOUBLE)
02570     {
02571       HOST_WIDE_INT i0, i1;
02572       rtx temp = NULL_RTX;
02573 
02574       if (GET_CODE (operands[1]) == CONST_INT)
02575   {
02576     i0 = INTVAL (operands[1]);
02577     i1 = -(i0 < 0);
02578   }
02579       else if (HOST_BITS_PER_WIDE_INT >= 64)
02580   {
02581     i0 = CONST_DOUBLE_LOW (operands[1]);
02582     i1 = -(i0 < 0);
02583   }
02584       else
02585   {
02586     i0 = CONST_DOUBLE_LOW (operands[1]);
02587     i1 = CONST_DOUBLE_HIGH (operands[1]);
02588   }
02589 
02590       if (HOST_BITS_PER_WIDE_INT >= 64 || i1 == -(i0 < 0))
02591   temp = alpha_emit_set_const (operands[0], mode, i0, 3);
02592 
02593       if (!temp && TARGET_BUILD_CONSTANTS)
02594   temp = alpha_emit_set_long_const (operands[0], i0, i1);
02595 
02596       if (temp)
02597   {
02598     if (rtx_equal_p (operands[0], temp))
02599       return true;
02600     operands[1] = temp;
02601     return false;
02602   }
02603     }
02604 
02605   /* Otherwise we've nothing left but to drop the thing to memory.  */
02606   operands[1] = force_const_mem (DImode, operands[1]);
02607   if (reload_in_progress)
02608     {
02609       emit_move_insn (operands[0], XEXP (operands[1], 0));
02610       operands[1] = copy_rtx (operands[1]);
02611       XEXP (operands[1], 0) = operands[0];
02612     }
02613   else
02614     operands[1] = validize_mem (operands[1]);
02615   return false;
02616 }
02617 
02618 /* Expand a non-bwx QImode or HImode move instruction;
02619    return true if all work is done.  */
02620 
02621 bool
02622 alpha_expand_mov_nobwx (mode, operands)
02623      enum machine_mode mode;
02624      rtx *operands;
02625 {
02626   /* If the output is not a register, the input must be.  */
02627   if (GET_CODE (operands[0]) == MEM)
02628     operands[1] = force_reg (mode, operands[1]);
02629 
02630   /* Handle four memory cases, unaligned and aligned for either the input
02631      or the output.  The only case where we can be called during reload is
02632      for aligned loads; all other cases require temporaries.  */
02633 
02634   if (GET_CODE (operands[1]) == MEM
02635       || (GET_CODE (operands[1]) == SUBREG
02636     && GET_CODE (SUBREG_REG (operands[1])) == MEM)
02637       || (reload_in_progress && GET_CODE (operands[1]) == REG
02638     && REGNO (operands[1]) >= FIRST_PSEUDO_REGISTER)
02639       || (reload_in_progress && GET_CODE (operands[1]) == SUBREG
02640     && GET_CODE (SUBREG_REG (operands[1])) == REG
02641     && REGNO (SUBREG_REG (operands[1])) >= FIRST_PSEUDO_REGISTER))
02642     {
02643       if (aligned_memory_operand (operands[1], mode))
02644   {
02645     if (reload_in_progress)
02646       {
02647         emit_insn ((mode == QImode
02648         ? gen_reload_inqi_help
02649         : gen_reload_inhi_help)
02650              (operands[0], operands[1],
02651         gen_rtx_REG (SImode, REGNO (operands[0]))));
02652       }
02653     else
02654       {
02655         rtx aligned_mem, bitnum;
02656         rtx scratch = gen_reg_rtx (SImode);
02657 
02658         get_aligned_mem (operands[1], &aligned_mem, &bitnum);
02659 
02660         emit_insn ((mode == QImode
02661         ? gen_aligned_loadqi
02662         : gen_aligned_loadhi)
02663        (operands[0], aligned_mem, bitnum, scratch));
02664       }
02665   }
02666       else
02667   {
02668     /* Don't pass these as parameters since that makes the generated
02669        code depend on parameter evaluation order which will cause
02670        bootstrap failures.  */
02671 
02672     rtx temp1 = gen_reg_rtx (DImode);
02673     rtx temp2 = gen_reg_rtx (DImode);
02674     rtx seq = ((mode == QImode
02675           ? gen_unaligned_loadqi
02676           : gen_unaligned_loadhi)
02677          (operands[0], get_unaligned_address (operands[1], 0),
02678           temp1, temp2));
02679 
02680     alpha_set_memflags (seq, operands[1]);
02681     emit_insn (seq);
02682   }
02683       return true;
02684     }
02685 
02686   if (GET_CODE (operands[0]) == MEM
02687       || (GET_CODE (operands[0]) == SUBREG
02688     && GET_CODE (SUBREG_REG (operands[0])) == MEM)
02689       || (reload_in_progress && GET_CODE (operands[0]) == REG
02690     && REGNO (operands[0]) >= FIRST_PSEUDO_REGISTER)
02691       || (reload_in_progress && GET_CODE (operands[0]) == SUBREG
02692     && GET_CODE (SUBREG_REG (operands[0])) == REG
02693     && REGNO (operands[0]) >= FIRST_PSEUDO_REGISTER))
02694     {
02695       if (aligned_memory_operand (operands[0], mode))
02696   {
02697     rtx aligned_mem, bitnum;
02698     rtx temp1 = gen_reg_rtx (SImode);
02699     rtx temp2 = gen_reg_rtx (SImode);
02700 
02701     get_aligned_mem (operands[0], &aligned_mem, &bitnum);
02702 
02703     emit_insn (gen_aligned_store (aligned_mem, operands[1], bitnum,
02704           temp1, temp2));
02705   }
02706       else
02707   {
02708     rtx temp1 = gen_reg_rtx (DImode);
02709     rtx temp2 = gen_reg_rtx (DImode);
02710     rtx temp3 = gen_reg_rtx (DImode);
02711     rtx seq = ((mode == QImode
02712           ? gen_unaligned_storeqi
02713           : gen_unaligned_storehi)
02714          (get_unaligned_address (operands[0], 0),
02715           operands[1], temp1, temp2, temp3));
02716 
02717     alpha_set_memflags (seq, operands[0]);
02718     emit_insn (seq);
02719   }
02720       return true;
02721     }
02722 
02723   return false;
02724 }
02725 
02726 /* Generate an unsigned DImode to FP conversion.  This is the same code
02727    optabs would emit if we didn't have TFmode patterns.
02728 
02729    For SFmode, this is the only construction I've found that can pass
02730    gcc.c-torture/execute/ieee/rbug.c.  No scenario that uses DFmode
02731    intermediates will work, because you'll get intermediate rounding
02732    that ruins the end result.  Some of this could be fixed by turning
02733    on round-to-positive-infinity, but that requires diddling the fpsr,
02734    which kills performance.  I tried turning this around and converting
02735    to a negative number, so that I could turn on /m, but either I did
02736    it wrong or there's something else cause I wound up with the exact
02737    same single-bit error.  There is a branch-less form of this same code:
02738 
02739   srl     $16,1,$1
02740   and     $16,1,$2
02741   cmplt   $16,0,$3
02742   or      $1,$2,$2
02743   cmovge  $16,$16,$2
02744   itoft $3,$f10
02745   itoft $2,$f11
02746   cvtqs   $f11,$f11
02747   adds    $f11,$f11,$f0
02748   fcmoveq $f10,$f11,$f0
02749 
02750    I'm not using it because it's the same number of instructions as
02751    this branch-full form, and it has more serialized long latency
02752    instructions on the critical path.
02753 
02754    For DFmode, we can avoid rounding errors by breaking up the word
02755    into two pieces, converting them separately, and adding them back:
02756 
02757    LC0: .long 0,0x5f800000
02758 
02759   itoft $16,$f11
02760   lda $2,LC0
02761   cmplt $16,0,$1
02762   cpyse $f11,$f31,$f10
02763   cpyse $f31,$f11,$f11
02764   s4addq  $1,$2,$1
02765   lds $f12,0($1)
02766   cvtqt $f10,$f10
02767   cvtqt $f11,$f11
02768   addt  $f12,$f10,$f0
02769   addt  $f0,$f11,$f0
02770 
02771    This doesn't seem to be a clear-cut win over the optabs form.
02772    It probably all depends on the distribution of numbers being
02773    converted -- in the optabs form, all but high-bit-set has a
02774    much lower minimum execution time.  */
02775 
02776 void
02777 alpha_emit_floatuns (operands)
02778      rtx operands[2];
02779 {
02780   rtx neglab, donelab, i0, i1, f0, in, out;
02781   enum machine_mode mode;
02782 
02783   out = operands[0];
02784   in = force_reg (DImode, operands[1]);
02785   mode = GET_MODE (out);
02786   neglab = gen_label_rtx ();
02787   donelab = gen_label_rtx ();
02788   i0 = gen_reg_rtx (DImode);
02789   i1 = gen_reg_rtx (DImode);
02790   f0 = gen_reg_rtx (mode);
02791 
02792   emit_cmp_and_jump_insns (in, const0_rtx, LT, const0_rtx, DImode, 0, neglab);
02793 
02794   emit_insn (gen_rtx_SET (VOIDmode, out, gen_rtx_FLOAT (mode, in)));
02795   emit_jump_insn (gen_jump (donelab));
02796   emit_barrier ();
02797 
02798   emit_label (neglab);
02799 
02800   emit_insn (gen_lshrdi3 (i0, in, const1_rtx));
02801   emit_insn (gen_anddi3 (i1, in, const1_rtx));
02802   emit_insn (gen_iordi3 (i0, i0, i1));
02803   emit_insn (gen_rtx_SET (VOIDmode, f0, gen_rtx_FLOAT (mode, i0)));
02804   emit_insn (gen_rtx_SET (VOIDmode, out, gen_rtx_PLUS (mode, f0, f0)));
02805 
02806   emit_label (donelab);
02807 }
02808 
02809 /* Generate the comparison for a conditional branch.  */
02810 
02811 rtx
02812 alpha_emit_conditional_branch (code)
02813      enum rtx_code code;
02814 {
02815   enum rtx_code cmp_code, branch_code;
02816   enum machine_mode cmp_mode, branch_mode = VOIDmode;
02817   rtx op0 = alpha_compare.op0, op1 = alpha_compare.op1;
02818   rtx tem;
02819 
02820   if (alpha_compare.fp_p && GET_MODE (op0) == TFmode)
02821     {
02822       if (! TARGET_HAS_XFLOATING_LIBS)
02823   abort ();
02824 
02825       /* X_floating library comparison functions return
02826      -1  unordered
02827       0  false
02828       1  true
02829    Convert the compare against the raw return value.  */
02830 
02831       switch (code)
02832   {
02833   case UNORDERED:
02834     cmp_code = EQ;
02835     code = LT;
02836     break;
02837   case ORDERED:
02838     cmp_code = EQ;
02839     code = GE;
02840     break;
02841   case NE:
02842     cmp_code = NE;
02843     code = NE;
02844     break;
02845   default:
02846     cmp_code = code;
02847     code = GT;
02848     break;
02849   }
02850 
02851       op0 = alpha_emit_xfloating_compare (cmp_code, op0, op1);
02852       op1 = const0_rtx;
02853       alpha_compare.fp_p = 0;
02854     }
02855 
02856   /* The general case: fold the comparison code to the types of compares
02857      that we have, choosing the branch as necessary.  */
02858   switch (code)
02859     {
02860     case EQ:  case LE:  case LT:  case LEU:  case LTU:
02861     case UNORDERED:
02862       /* We have these compares: */
02863       cmp_code = code, branch_code = NE;
02864       break;
02865 
02866     case NE:
02867     case ORDERED:
02868       /* These must be reversed.  */
02869       cmp_code = reverse_condition (code), branch_code = EQ;
02870       break;
02871 
02872     case GE:  case GT: case GEU:  case GTU:
02873       /* For FP, we swap them, for INT, we reverse them.  */
02874       if (alpha_compare.fp_p)
02875   {
02876     cmp_code = swap_condition (code);
02877     branch_code = NE;
02878     tem = op0, op0 = op1, op1 = tem;
02879   }
02880       else
02881   {
02882     cmp_code = reverse_condition (code);
02883     branch_code = EQ;
02884   }
02885       break;
02886 
02887     default:
02888       abort ();
02889     }
02890 
02891   if (alpha_compare.fp_p)
02892     {
02893       cmp_mode = DFmode;
02894       if (flag_unsafe_math_optimizations)
02895   {
02896     /* When we are not as concerned about non-finite values, and we
02897        are comparing against zero, we can branch directly.  */
02898     if (op1 == CONST0_RTX (DFmode))
02899       cmp_code = NIL, branch_code = code;
02900     else if (op0 == CONST0_RTX (DFmode))
02901       {
02902         /* Undo the swap we probably did just above.  */
02903         tem = op0, op0 = op1, op1 = tem;
02904         branch_code = swap_condition (cmp_code);
02905         cmp_code = NIL;
02906       }
02907   }
02908       else
02909   {
02910     /* ??? We mark the the branch mode to be CCmode to prevent the
02911        compare and branch from being combined, since the compare 
02912        insn follows IEEE rules that the branch does not.  */
02913     branch_mode = CCmode;
02914   }
02915     }
02916   else
02917     {
02918       cmp_mode = DImode;
02919 
02920       /* The following optimizations are only for signed compares.  */
02921       if (code != LEU && code != LTU && code != GEU && code != GTU)
02922   {
02923     /* Whee.  Compare and branch against 0 directly.  */
02924     if (op1 == const0_rtx)
02925       cmp_code = NIL, branch_code = code;
02926 
02927     /* We want to use cmpcc/bcc when we can, since there is a zero delay
02928        bypass between logicals and br/cmov on EV5.  But we don't want to
02929        force valid immediate constants into registers needlessly.  */
02930     else if (GET_CODE (op1) == CONST_INT)
02931       {
02932         HOST_WIDE_INT v = INTVAL (op1), n = -v;
02933 
02934         if (! CONST_OK_FOR_LETTER_P (v, 'I')
02935       && (CONST_OK_FOR_LETTER_P (n, 'K')
02936           || CONST_OK_FOR_LETTER_P (n, 'L')))
02937     {
02938       cmp_code = PLUS, branch_code = code;
02939       op1 = GEN_INT (n);
02940     }
02941       }
02942   }
02943 
02944       if (!reg_or_0_operand (op0, DImode))
02945   op0 = force_reg (DImode, op0);
02946       if (cmp_code != PLUS && !reg_or_8bit_operand (op1, DImode))
02947   op1 = force_reg (DImode, op1);
02948     }
02949 
02950   /* Emit an initial compare instruction, if necessary.  */
02951   tem = op0;
02952   if (cmp_code != NIL)
02953     {
02954       tem = gen_reg_rtx (cmp_mode);
02955       emit_move_insn (tem, gen_rtx_fmt_ee (cmp_code, cmp_mode, op0, op1));
02956     }
02957 
02958   /* Zero the operands.  */
02959   memset (&alpha_compare, 0, sizeof (alpha_compare));
02960 
02961   /* Return the branch comparison.  */
02962   return gen_rtx_fmt_ee (branch_code, branch_mode, tem, CONST0_RTX (cmp_mode));
02963 }
02964 
02965 /* Certain simplifications can be done to make invalid setcc operations
02966    valid.  Return the final comparison, or NULL if we can't work.  */
02967 
02968 rtx
02969 alpha_emit_setcc (code)
02970      enum rtx_code code;
02971 {
02972   enum rtx_code cmp_code;
02973   rtx op0 = alpha_compare.op0, op1 = alpha_compare.op1;
02974   int fp_p = alpha_compare.fp_p;
02975   rtx tmp;
02976 
02977   /* Zero the operands.  */
02978   memset (&alpha_compare, 0, sizeof (alpha_compare));
02979 
02980   if (fp_p && GET_MODE (op0) == TFmode)
02981     {
02982       if (! TARGET_HAS_XFLOATING_LIBS)
02983   abort ();
02984 
02985       /* X_floating library comparison functions return
02986      -1  unordered
02987       0  false
02988       1  true
02989    Convert the compare against the raw return value.  */
02990 
02991       if (code == UNORDERED || code == ORDERED)
02992   cmp_code = EQ;
02993       else
02994   cmp_code = code;
02995 
02996       op0 = alpha_emit_xfloating_compare (cmp_code, op0, op1);
02997       op1 = const0_rtx;
02998       fp_p = 0;
02999 
03000       if (code == UNORDERED)
03001   code = LT;
03002       else if (code == ORDERED)
03003   code = GE;
03004       else
03005         code = GT;
03006     }
03007 
03008   if (fp_p && !TARGET_FIX)
03009     return NULL_RTX;
03010 
03011   /* The general case: fold the comparison code to the types of compares
03012      that we have, choosing the branch as necessary.  */
03013 
03014   cmp_code = NIL;
03015   switch (code)
03016     {
03017     case EQ:  case LE:  case LT:  case LEU:  case LTU:
03018     case UNORDERED:
03019       /* We have these compares.  */
03020       if (fp_p)
03021   cmp_code = code, code = NE;
03022       break;
03023 
03024     case NE:
03025       if (!fp_p && op1 == const0_rtx)
03026   break;
03027       /* FALLTHRU */
03028 
03029     case ORDERED:
03030       cmp_code = reverse_condition (code);
03031       code = EQ;
03032       break;
03033 
03034     case GE:  case GT: case GEU:  case GTU:
03035       /* These normally need swapping, but for integer zero we have
03036    special patterns that recognize swapped operands.  */
03037       if (!fp_p && op1 == const0_rtx)
03038   break;
03039       code = swap_condition (code);
03040       if (fp_p)
03041   cmp_code = code, code = NE;
03042       tmp = op0, op0 = op1, op1 = tmp;
03043       break;
03044 
03045     default:
03046       abort ();
03047     }
03048 
03049   if (!fp_p)
03050     {
03051       if (!register_operand (op0, DImode))
03052   op0 = force_reg (DImode, op0);
03053       if (!reg_or_8bit_operand (op1, DImode))
03054   op1 = force_reg (DImode, op1);
03055     }
03056 
03057   /* Emit an initial compare instruction, if necessary.  */
03058   if (cmp_code != NIL)
03059     {
03060       enum machine_mode mode = fp_p ? DFmode : DImode;
03061 
03062       tmp = gen_reg_rtx (mode);
03063       emit_insn (gen_rtx_SET (VOIDmode, tmp,
03064             gen_rtx_fmt_ee (cmp_code, mode, op0, op1)));
03065 
03066       op0 = fp_p ? gen_lowpart (DImode, tmp) : tmp;
03067       op1 = const0_rtx;
03068     }
03069 
03070   /* Return the setcc comparison.  */
03071   return gen_rtx_fmt_ee (code, DImode, op0, op1);
03072 }
03073 
03074 
03075 /* Rewrite a comparison against zero CMP of the form
03076    (CODE (cc0) (const_int 0)) so it can be written validly in
03077    a conditional move (if_then_else CMP ...).
03078    If both of the operands that set cc0 are non-zero we must emit
03079    an insn to perform the compare (it can't be done within
03080    the conditional move).  */
03081 rtx
03082 alpha_emit_conditional_move (cmp, mode)
03083      rtx cmp;
03084      enum machine_mode mode;
03085 {
03086   enum rtx_code code = GET_CODE (cmp);
03087   enum rtx_code cmov_code = NE;
03088   rtx op0 = alpha_compare.op0;
03089   rtx op1 = alpha_compare.op1;
03090   int fp_p = alpha_compare.fp_p;
03091   enum machine_mode cmp_mode
03092     = (GET_MODE (op0) == VOIDmode ? DImode : GET_MODE (op0));
03093   enum machine_mode cmp_op_mode = fp_p ? DFmode : DImode;
03094   enum machine_mode cmov_mode = VOIDmode;
03095   int local_fast_math = flag_unsafe_math_optimizations;
03096   rtx tem;
03097 
03098   /* Zero the operands.  */
03099   memset (&alpha_compare, 0, sizeof (alpha_compare));
03100 
03101   if (fp_p != FLOAT_MODE_P (mode))
03102     {
03103       enum rtx_code cmp_code;
03104 
03105       if (! TARGET_FIX)
03106   return 0;
03107 
03108       /* If we have fp<->int register move instructions, do a cmov by
03109    performing the comparison in fp registers, and move the
03110    zero/non-zero value to integer registers, where we can then
03111    use a normal cmov, or vice-versa.  */
03112 
03113       switch (code)
03114   {
03115   case EQ: case LE: case LT: case LEU: case LTU:
03116     /* We have these compares.  */
03117     cmp_code = code, code = NE;
03118     break;
03119 
03120   case NE:
03121     /* This must be reversed.  */
03122     cmp_code = EQ, code = EQ;
03123     break;
03124 
03125   case GE: case GT: case GEU: case GTU:
03126     /* These normally need swapping, but for integer zero we have
03127        special patterns that recognize swapped operands.  */
03128     if (!fp_p && op1 == const0_rtx)
03129       cmp_code = code, code = NE;
03130     else
03131       {
03132         cmp_code = swap_condition (code);
03133         code = NE;
03134         tem = op0, op0 = op1, op1 = tem;
03135       }
03136     break;
03137 
03138   default:
03139     abort ();
03140   }
03141 
03142       tem = gen_reg_rtx (cmp_op_mode);
03143       emit_insn (gen_rtx_SET (VOIDmode, tem,
03144             gen_rtx_fmt_ee (cmp_code, cmp_op_mode,
03145                 op0, op1)));
03146 
03147       cmp_mode = cmp_op_mode = fp_p ? DImode : DFmode;
03148       op0 = gen_lowpart (cmp_op_mode, tem);
03149       op1 = CONST0_RTX (cmp_op_mode);
03150       fp_p = !fp_p;
03151       local_fast_math = 1;
03152     }
03153 
03154   /* We may be able to use a conditional move directly.
03155      This avoids emitting spurious compares.  */
03156   if (signed_comparison_operator (cmp, VOIDmode)
03157       && (!fp_p || local_fast_math)
03158       && (op0 == CONST0_RTX (cmp_mode) || op1 == CONST0_RTX (cmp_mode)))
03159     return gen_rtx_fmt_ee (code, VOIDmode, op0, op1);
03160 
03161   /* We can't put the comparison inside the conditional move;
03162      emit a compare instruction and put that inside the
03163      conditional move.  Make sure we emit only comparisons we have;
03164      swap or reverse as necessary.  */
03165 
03166   if (no_new_pseudos)
03167     return NULL_RTX;
03168 
03169   switch (code)
03170     {
03171     case EQ:  case LE:  case LT:  case LEU:  case LTU:
03172       /* We have these compares: */
03173       break;
03174 
03175     case NE:
03176       /* This must be reversed.  */
03177       code = reverse_condition (code);
03178       cmov_code = EQ;
03179       break;
03180 
03181     case GE:  case GT:  case GEU:  case GTU:
03182       /* These must be swapped.  */
03183       if (op1 != CONST0_RTX (cmp_mode))
03184   {
03185     code = swap_condition (code);
03186     tem = op0, op0 = op1, op1 = tem;
03187   }
03188       break;
03189 
03190     default:
03191       abort ();
03192     }
03193 
03194   if (!fp_p)
03195     {
03196       if (!reg_or_0_operand (op0, DImode))
03197   op0 = force_reg (DImode, op0);
03198       if (!reg_or_8bit_operand (op1, DImode))
03199   op1 = force_reg (DImode, op1);
03200     }
03201 
03202   /* ??? We mark the branch mode to be CCmode to prevent the compare
03203      and cmov from being combined, since the compare insn follows IEEE
03204      rules that the cmov does not.  */
03205   if (fp_p && !local_fast_math)
03206     cmov_mode = CCmode;
03207 
03208   tem = gen_reg_rtx (cmp_op_mode);
03209   emit_move_insn (tem, gen_rtx_fmt_ee (code, cmp_op_mode, op0, op1));
03210   return gen_rtx_fmt_ee (cmov_code, cmov_mode, tem, CONST0_RTX (cmp_op_mode));
03211 }
03212 
03213 /* Simplify a conditional move of two constants into a setcc with
03214    arithmetic.  This is done with a splitter since combine would
03215    just undo the work if done during code generation.  It also catches
03216    cases we wouldn't have before cse.  */
03217 
03218 int
03219 alpha_split_conditional_move (code, dest, cond, t_rtx, f_rtx)
03220      enum rtx_code code;
03221      rtx dest, cond, t_rtx, f_rtx;
03222 {
03223   HOST_WIDE_INT t, f, diff;
03224   enum machine_mode mode;
03225   rtx target, subtarget, tmp;
03226 
03227   mode = GET_MODE (dest);
03228   t = INTVAL (t_rtx);
03229   f = INTVAL (f_rtx);
03230   diff = t - f;
03231 
03232   if (((code == NE || code == EQ) && diff < 0)
03233       || (code == GE || code == GT))
03234     {
03235       code = reverse_condition (code);
03236       diff = t, t = f, f = diff;
03237       diff = t - f;
03238     }
03239 
03240   subtarget = target = dest;
03241   if (mode != DImode)
03242     {
03243       target = gen_lowpart (DImode, dest);
03244       if (! no_new_pseudos)
03245         subtarget = gen_reg_rtx (DImode);
03246       else
03247   subtarget = target;
03248     }
03249   /* Below, we must be careful to use copy_rtx on target and subtarget
03250      in intermediate insns, as they may be a subreg rtx, which may not
03251      be shared.  */
03252 
03253   if (f == 0 && exact_log2 (diff) > 0
03254       /* On EV6, we've got enough shifters to make non-arithmatic shifts
03255    viable over a longer latency cmove.  On EV5, the E0 slot is a
03256    scarce resource, and on EV4 shift has the same latency as a cmove.  */
03257       && (diff <= 8 || alpha_cpu == PROCESSOR_EV6))
03258     {
03259       tmp = gen_rtx_fmt_ee (code, DImode, cond, const0_rtx);
03260       emit_insn (gen_rtx_SET (VOIDmode, copy_rtx (subtarget), tmp));
03261 
03262       tmp = gen_rtx_ASHIFT (DImode, copy_rtx (subtarget),
03263           GEN_INT (exact_log2 (t)));
03264       emit_insn (gen_rtx_SET (VOIDmode, target, tmp));
03265     }
03266   else if (f == 0 && t == -1)
03267     {
03268       tmp = gen_rtx_fmt_ee (code, DImode, cond, const0_rtx);
03269       emit_insn (gen_rtx_SET (VOIDmode, copy_rtx (subtarget), tmp));
03270 
03271       emit_insn (gen_negdi2 (target, copy_rtx (subtarget)));
03272     }
03273   else if (diff == 1 || diff == 4 || diff == 8)
03274     {
03275       rtx add_op;
03276 
03277       tmp = gen_rtx_fmt_ee (code, DImode, cond, const0_rtx);
03278       emit_insn (gen_rtx_SET (VOIDmode, copy_rtx (subtarget), tmp));
03279 
03280       if (diff == 1)
03281   emit_insn (gen_adddi3 (target, copy_rtx (subtarget), GEN_INT (f)));
03282       else
03283   {
03284     add_op = GEN_INT (f);
03285     if (sext_add_operand (add_op, mode))
03286       {
03287         tmp = gen_rtx_MULT (DImode, copy_rtx (subtarget),
03288           GEN_INT (diff));
03289         tmp = gen_rtx_PLUS (DImode, tmp, add_op);
03290         emit_insn (gen_rtx_SET (VOIDmode, target, tmp));
03291       }
03292     else
03293       return 0;
03294   }
03295     }
03296   else
03297     return 0;
03298 
03299   return 1;
03300 }
03301 
03302 /* Look up the function X_floating library function name for the
03303    given operation.  */
03304 
03305 static const char *
03306 alpha_lookup_xfloating_lib_func (code)
03307      enum rtx_code code;
03308 {
03309   struct xfloating_op
03310     {
03311       const enum rtx_code code;
03312       const char *const func;
03313     };
03314 
03315   static const struct xfloating_op vms_xfloating_ops[] = 
03316     {
03317       { PLUS,   "OTS$ADD_X" },
03318       { MINUS,    "OTS$SUB_X" },
03319       { MULT,   "OTS$MUL_X" },
03320       { DIV,    "OTS$DIV_X" },
03321       { EQ,   "OTS$EQL_X" },
03322       { NE,   "OTS$NEQ_X" },
03323       { LT,   "OTS$LSS_X" },
03324       { LE,   "OTS$LEQ_X" },
03325       { GT,   "OTS$GTR_X" },
03326       { GE,   "OTS$GEQ_X" },
03327       { FIX,    "OTS$CVTXQ" },
03328       { FLOAT,    "OTS$CVTQX" },
03329       { UNSIGNED_FLOAT, "OTS$CVTQUX" },
03330       { FLOAT_EXTEND, "OTS$CVT_FLOAT_T_X" },
03331       { FLOAT_TRUNCATE, "OTS$CVT_FLOAT_X_T" },
03332     };
03333 
03334   static const struct xfloating_op osf_xfloating_ops[] = 
03335     {
03336       { PLUS,   "_OtsAddX" },
03337       { MINUS,    "_OtsSubX" },
03338       { MULT,   "_OtsMulX" },
03339       { DIV,    "_OtsDivX" },
03340       { EQ,   "_OtsEqlX" },
03341       { NE,   "_OtsNeqX" },
03342       { LT,   "_OtsLssX" },
03343       { LE,   "_OtsLeqX" },
03344       { GT,   "_OtsGtrX" },
03345       { GE,   "_OtsGeqX" },
03346       { FIX,    "_OtsCvtXQ" },
03347       { FLOAT,    "_OtsCvtQX" },
03348       { UNSIGNED_FLOAT, "_OtsCvtQUX" },
03349       { FLOAT_EXTEND, "_OtsConvertFloatTX" },
03350       { FLOAT_TRUNCATE, "_OtsConvertFloatXT" },
03351     };
03352 
03353   const struct xfloating_op *ops;
03354   const long n = ARRAY_SIZE (osf_xfloating_ops);
03355   long i;
03356 
03357   /* How irritating.  Nothing to key off for the table.  Hardcode
03358      knowledge of the G_floating routines.  */
03359   if (TARGET_FLOAT_VAX)
03360     {
03361       if (TARGET_ABI_OPEN_VMS)
03362   {
03363     if (code == FLOAT_EXTEND)
03364       return "OTS$CVT_FLOAT_G_X";
03365     if (code == FLOAT_TRUNCATE)
03366       return "OTS$CVT_FLOAT_X_G";
03367   }
03368       else
03369   {
03370     if (code == FLOAT_EXTEND)
03371       return "_OtsConvertFloatGX";
03372     if (code == FLOAT_TRUNCATE)
03373       return "_OtsConvertFloatXG";
03374   }
03375     }
03376 
03377   if (TARGET_ABI_OPEN_VMS)
03378     ops = vms_xfloating_ops;
03379   else
03380     ops = osf_xfloating_ops;
03381 
03382   for (i = 0; i < n; ++i)
03383     if (ops[i].code == code)
03384       return ops[i].func;
03385 
03386   abort();
03387 }
03388 
03389 /* Most X_floating operations take the rounding mode as an argument.
03390    Compute that here.  */
03391 
03392 static int
03393 alpha_compute_xfloating_mode_arg (code, round)
03394      enum rtx_code code;
03395      enum alpha_fp_rounding_mode round;
03396 {
03397   int mode;
03398 
03399   switch (round)
03400     {
03401     case ALPHA_FPRM_NORM:
03402       mode = 2;
03403       break;
03404     case ALPHA_FPRM_MINF:
03405       mode = 1;
03406       break;
03407     case ALPHA_FPRM_CHOP:
03408       mode = 0;
03409       break;
03410     case ALPHA_FPRM_DYN:
03411       mode = 4;
03412       break;
03413     default:
03414       abort ();
03415 
03416     /* XXX For reference, round to +inf is mode = 3.  */
03417     }
03418 
03419   if (code == FLOAT_TRUNCATE && alpha_fptm == ALPHA_FPTM_N)
03420     mode |= 0x10000;
03421 
03422   return mode;
03423 }
03424 
03425 /* Emit an X_floating library function call.
03426 
03427    Note that these functions do not follow normal calling conventions:
03428    TFmode arguments are passed in two integer registers (as opposed to
03429    indirect); TFmode return values appear in R16+R17. 
03430 
03431    FUNC is the function name to call.
03432    TARGET is where the output belongs.
03433    OPERANDS are the inputs.
03434    NOPERANDS is the count of inputs.
03435    EQUIV is the expression equivalent for the function.
03436 */
03437 
03438 static void
03439 alpha_emit_xfloating_libcall (func, target, operands, noperands, equiv)
03440      const char *func;
03441      rtx target;
03442      rtx operands[];
03443      int noperands;
03444      rtx equiv;
03445 {
03446   rtx usage = NULL_RTX, tmp, reg;
03447   int regno = 16, i;
03448 
03449   start_sequence ();
03450 
03451   for (i = 0; i < noperands; ++i)
03452     {
03453       switch (GET_MODE (operands[i]))
03454   {
03455   case TFmode:
03456     reg = gen_rtx_REG (TFmode, regno);
03457     regno += 2;
03458     break;
03459 
03460   case DFmode:
03461     reg = gen_rtx_REG (DFmode, regno + 32);
03462     regno += 1;
03463     break;
03464 
03465   case VOIDmode:
03466     if (GET_CODE (operands[i]) != CONST_INT)
03467       abort ();
03468     /* FALLTHRU */
03469   case DImode:
03470     reg = gen_rtx_REG (DImode, regno);
03471     regno += 1;
03472     break;
03473 
03474   default:
03475     abort ();
03476   }
03477 
03478       emit_move_insn (reg, operands[i]);
03479       usage = alloc_EXPR_LIST (0, gen_rtx_USE (VOIDmode, reg), usage);
03480     }
03481 
03482   switch (GET_MODE (target))
03483     {
03484     case TFmode:
03485       reg = gen_rtx_REG (TFmode, 16);
03486       break;
03487     case DFmode:
03488       reg = gen_rtx_REG (DFmode, 32);
03489       break;
03490     case DImode:
03491       reg = gen_rtx_REG (DImode, 0);
03492       break;
03493     default:
03494       abort ();
03495     }
03496 
03497   tmp = gen_rtx_MEM (QImode, gen_rtx_SYMBOL_REF (Pmode, (char *) func));
03498   tmp = emit_call_insn (GEN_CALL_VALUE (reg, tmp, const0_rtx,
03499           const0_rtx, const0_rtx));
03500   CALL_INSN_FUNCTION_USAGE (tmp) = usage;
03501 
03502   tmp = get_insns ();
03503   end_sequence ();
03504 
03505   emit_libcall_block (tmp, target, reg, equiv);
03506 }
03507 
03508 /* Emit an X_floating library function call for arithmetic (+,-,*,/).  */
03509 
03510 void
03511 alpha_emit_xfloating_arith (code, operands)
03512      enum rtx_code code;
03513      rtx operands[];
03514 {
03515   const char *func;
03516   int mode;
03517   rtx out_operands[3];
03518 
03519   func = alpha_lookup_xfloating_lib_func (code);
03520   mode = alpha_compute_xfloating_mode_arg (code, alpha_fprm);
03521 
03522   out_operands[0] = operands[1];
03523   out_operands[1] = operands[2];
03524   out_operands[2] = GEN_INT (mode);
03525   alpha_emit_xfloating_libcall (func, operands[0], out_operands, 3,  
03526         gen_rtx_fmt_ee (code, TFmode, operands[1],
03527             operands[2]));
03528 }
03529 
03530 /* Emit an X_floating library function call for a comparison.  */
03531 
03532 static rtx
03533 alpha_emit_xfloating_compare (code, op0, op1)
03534      enum rtx_code code;
03535      rtx op0, op1;
03536 {
03537   const char *func;
03538   rtx out, operands[2];
03539 
03540   func = alpha_lookup_xfloating_lib_func (code);
03541 
03542   operands[0] = op0;
03543   operands[1] = op1;
03544   out = gen_reg_rtx (DImode);
03545 
03546   /* ??? Strange mode for equiv because what's actually returned
03547      is -1,0,1, not a proper boolean value.  */
03548   alpha_emit_xfloating_libcall (func, out, operands, 2,
03549         gen_rtx_fmt_ee (code, CCmode, op0, op1));
03550 
03551   return out;
03552 }
03553 
03554 /* Emit an X_floating library function call for a conversion.  */
03555 
03556 void
03557 alpha_emit_xfloating_cvt (code, operands)
03558      enum rtx_code code;
03559      rtx operands[];
03560 {
03561   int noperands = 1, mode;
03562   rtx out_operands[2];
03563   const char *func;
03564 
03565   func = alpha_lookup_xfloating_lib_func (code);
03566 
03567   out_operands[0] = operands[1];
03568 
03569   switch (code)
03570     {
03571     case FIX:
03572       mode = alpha_compute_xfloating_mode_arg (code, ALPHA_FPRM_CHOP);
03573       out_operands[1] = GEN_INT (mode);
03574       noperands = 2;
03575       break;
03576     case FLOAT_TRUNCATE:
03577       mode = alpha_compute_xfloating_mode_arg (code, alpha_fprm);
03578       out_operands[1] = GEN_INT (mode);
03579       noperands = 2;
03580       break;
03581     default:
03582       break;
03583     }
03584 
03585   alpha_emit_xfloating_libcall (func, operands[0], out_operands, noperands,
03586         gen_rtx_fmt_e (code, GET_MODE (operands[0]),
03587                  operands[1]));
03588 }
03589 
03590 /* Split a TFmode OP[1] into DImode OP[2,3] and likewise for
03591    OP[0] into OP[0,1].  Naturally, output operand ordering is
03592    little-endian.  */
03593 
03594 void
03595 alpha_split_tfmode_pair (operands)
03596      rtx operands[4];
03597 {
03598   if (GET_CODE (operands[1]) == REG)
03599     {
03600       operands[3] = gen_rtx_REG (DImode, REGNO (operands[1]) + 1);
03601       operands[2] = gen_rtx_REG (DImode, REGNO (operands[1]));
03602     }
03603   else if (GET_CODE (operands[1]) == MEM)
03604     {
03605       operands[3] = adjust_address (operands[1], DImode, 8);
03606       operands[2] = adjust_address (operands[1], DImode, 0);
03607     }
03608   else if (operands[1] == CONST0_RTX (TFmode))
03609     operands[2] = operands[3] = const0_rtx;
03610   else
03611     abort ();
03612 
03613   if (GET_CODE (operands[0]) == REG)
03614     {
03615       operands[1] = gen_rtx_REG (DImode, REGNO (operands[0]) + 1);
03616       operands[0] = gen_rtx_REG (DImode, REGNO (operands[0]));
03617     }
03618   else if (GET_CODE (operands[0]) == MEM)
03619     {
03620       operands[1] = adjust_address (operands[0], DImode, 8);
03621       operands[0] = adjust_address (operands[0], DImode, 0);
03622     }
03623   else
03624     abort ();
03625 }
03626 
03627 /* Implement negtf2 or abstf2.  Op0 is destination, op1 is source, 
03628    op2 is a register containing the sign bit, operation is the 
03629    logical operation to be performed.  */
03630 
03631 void
03632 alpha_split_tfmode_frobsign (operands, operation)
03633      rtx operands[3];
03634      rtx (*operation) PARAMS ((rtx, rtx, rtx));
03635 {
03636   rtx high_bit = operands[2];
03637   rtx scratch;
03638   int move;
03639 
03640   alpha_split_tfmode_pair (operands);
03641 
03642   /* Detect three flavours of operand overlap.  */
03643   move = 1;
03644   if (rtx_equal_p (operands[0], operands[2]))
03645     move = 0;
03646   else if (rtx_equal_p (operands[1], operands[2]))
03647     {
03648       if (rtx_equal_p (operands[0], high_bit))
03649   move = 2;
03650       else
03651   move = -1;
03652     }
03653 
03654   if (move < 0)
03655     emit_move_insn (operands[0], operands[2]);
03656 
03657   /* ??? If the destination overlaps both source tf and high_bit, then
03658      assume source tf is dead in its entirety and use the other half
03659      for a scratch register.  Otherwise "scratch" is just the proper
03660      destination register.  */
03661   scratch = operands[move < 2 ? 1 : 3];
03662 
03663   emit_insn ((*operation) (scratch, high_bit, operands[3]));
03664 
03665   if (move > 0)
03666     {
03667       emit_move_insn (operands[0], operands[2]);
03668       if (move > 1)
03669   emit_move_insn (operands[1], scratch);
03670     }
03671 }
03672 
03673 /* Use ext[wlq][lh] as the Architecture Handbook describes for extracting
03674    unaligned data:
03675 
03676            unsigned:                       signed:
03677    word:   ldq_u  r1,X(r11)                ldq_u  r1,X(r11)
03678            ldq_u  r2,X+1(r11)              ldq_u  r2,X+1(r11)
03679            lda    r3,X(r11)                lda    r3,X+2(r11)
03680            extwl  r1,r3,r1                 extql  r1,r3,r1
03681            extwh  r2,r3,r2                 extqh  r2,r3,r2
03682            or     r1.r2.r1                 or     r1,r2,r1
03683                                            sra    r1,48,r1
03684 
03685    long:   ldq_u  r1,X(r11)                ldq_u  r1,X(r11)
03686            ldq_u  r2,X+3(r11)              ldq_u  r2,X+3(r11)
03687            lda    r3,X(r11)                lda    r3,X(r11)
03688            extll  r1,r3,r1                 extll  r1,r3,r1
03689            extlh  r2,r3,r2                 extlh  r2,r3,r2
03690            or     r1.r2.r1                 addl   r1,r2,r1
03691 
03692    quad:   ldq_u  r1,X(r11)
03693            ldq_u  r2,X+7(r11)
03694            lda    r3,X(r11)
03695            extql  r1,r3,r1
03696            extqh  r2,r3,r2
03697            or     r1.r2.r1
03698 */
03699 
03700 void
03701 alpha_expand_unaligned_load (tgt, mem, size, ofs, sign)
03702      rtx tgt, mem;
03703      HOST_WIDE_INT size, ofs;
03704      int sign;
03705 {
03706   rtx meml, memh, addr, extl, exth, tmp, mema;
03707   enum machine_mode mode;
03708 
03709   meml = gen_reg_rtx (DImode);
03710   memh = gen_reg_rtx (DImode);
03711   addr = gen_reg_rtx (DImode);
03712   extl = gen_reg_rtx (DImode);
03713   exth = gen_reg_rtx (DImode);
03714 
03715   mema = XEXP (mem, 0);
03716   if (GET_CODE (mema) == LO_SUM)
03717     mema = force_reg (Pmode, mema);
03718 
03719   /* AND addresses cannot be in any alias set, since they may implicitly
03720      alias surrounding code.  Ideally we'd have some alias set that 
03721      covered all types except those with alignment 8 or higher.  */
03722 
03723   tmp = change_address (mem, DImode,
03724       gen_rtx_AND (DImode, 
03725              plus_constant (mema, ofs),
03726              GEN_INT (-8)));
03727   set_mem_alias_set (tmp, 0);
03728   emit_move_insn (meml, tmp);
03729 
03730   tmp = change_address (mem, DImode,
03731       gen_rtx_AND (DImode, 
03732              plus_constant (mema, ofs + size - 1),
03733              GEN_INT (-8)));
03734   set_mem_alias_set (tmp, 0);
03735   emit_move_insn (memh, tmp);
03736 
03737   if (WORDS_BIG_ENDIAN && sign && (size == 2 || size == 4))
03738     {
03739       emit_move_insn (addr, plus_constant (mema, -1));
03740 
03741       emit_insn (gen_extqh_be (extl, meml, addr));
03742       emit_insn (gen_extxl_be (exth, memh, GEN_INT (64), addr));
03743 
03744       addr = expand_binop (DImode, ior_optab, extl, exth, tgt, 1, OPTAB_WIDEN);
03745       addr = expand_binop (DImode, ashr_optab, addr, GEN_INT (64 - size*8),
03746          addr, 1, OPTAB_WIDEN);
03747     }
03748   else if (sign && size == 2)
03749     {
03750       emit_move_insn (addr, plus_constant (mema, ofs+2));
03751 
03752       emit_insn (gen_extxl_le (extl, meml, GEN_INT (64), addr));
03753       emit_insn (gen_extqh_le (exth, memh, addr));
03754 
03755       /* We must use tgt here for the target.  Alpha-vms port fails if we use
03756    addr for the target, because addr is marked as a pointer and combine
03757    knows that pointers are always sign-extended 32 bit values.  */
03758       addr = expand_binop (DImode, ior_optab, extl, exth, tgt, 1, OPTAB_WIDEN);
03759       addr = expand_binop (DImode, ashr_optab, addr, GEN_INT (48), 
03760          addr, 1, OPTAB_WIDEN);
03761     }
03762   else
03763     {
03764       if (WORDS_BIG_ENDIAN)
03765   {
03766     emit_move_insn (addr, plus_constant (mema, ofs+size-1));
03767     switch ((int) size)
03768       {
03769       case 2:
03770         emit_insn (gen_extwh_be (extl, meml, addr));
03771         mode = HImode;
03772         break;
03773 
03774       case 4:
03775         emit_insn (gen_extlh_be (extl, meml, addr));
03776         mode = SImode;
03777         break;
03778 
03779       case 8:
03780         emit_insn (gen_extqh_be (extl, meml, addr));
03781         mode = DImode;
03782         break;
03783 
03784       default:
03785         abort ();
03786       }
03787     emit_insn (gen_extxl_be (exth, memh, GEN_INT (size*8), addr));
03788   }
03789       else
03790   {
03791     emit_move_insn (addr, plus_constant (mema, ofs));
03792     emit_insn (gen_extxl_le (extl, meml, GEN_INT (size*8), addr));
03793     switch ((int) size)
03794       {
03795       case 2:
03796         emit_insn (gen_extwh_le (exth, memh, addr));
03797         mode = HImode;
03798         break;
03799 
03800       case 4:
03801         emit_insn (gen_extlh_le (exth, memh, addr));
03802         mode = SImode;
03803         break;
03804 
03805       case 8:
03806         emit_insn (gen_extqh_le (exth, memh, addr));
03807         mode = DImode;
03808         break;
03809 
03810       default:
03811         abort();
03812       }
03813   }
03814 
03815       addr = expand_binop (mode, ior_optab, gen_lowpart (mode, extl),
03816          gen_lowpart (mode, exth), gen_lowpart (mode, tgt),
03817          sign, OPTAB_WIDEN);
03818     }
03819 
03820   if (addr != tgt)
03821     emit_move_insn (tgt, gen_lowpart(GET_MODE (tgt), addr));
03822 }
03823 
03824 /* Similarly, use ins and msk instructions to perform unaligned stores.  */
03825 
03826 void
03827 alpha_expand_unaligned_store (dst, src, size, ofs)
03828      rtx dst, src;
03829      HOST_WIDE_INT size, ofs;
03830 {
03831   rtx dstl, dsth, addr, insl, insh, meml, memh, dsta;
03832   
03833   dstl = gen_reg_rtx (DImode);
03834   dsth = gen_reg_rtx (DImode);
03835   insl = gen_reg_rtx (DImode);
03836   insh = gen_reg_rtx (DImode);
03837 
03838   dsta = XEXP (dst, 0);
03839   if (GET_CODE (dsta) == LO_SUM)
03840     dsta = force_reg (Pmode, dsta);
03841 
03842   /* AND addresses cannot be in any alias set, since they may implicitly
03843      alias surrounding code.  Ideally we'd have some alias set that 
03844      covered all types except those with alignment 8 or higher.  */
03845 
03846   meml = change_address (dst, DImode,
03847        gen_rtx_AND (DImode, 
03848               plus_constant (dsta, ofs),
03849               GEN_INT (-8)));
03850   set_mem_alias_set (meml, 0);
03851 
03852   memh = change_address (dst, DImode,
03853        gen_rtx_AND (DImode, 
03854               plus_constant (dsta, ofs + size - 1),
03855               GEN_INT (-8)));
03856   set_mem_alias_set (memh, 0);
03857 
03858   emit_move_insn (dsth, memh);
03859   emit_move_insn (dstl, meml);
03860   if (WORDS_BIG_ENDIAN)
03861     {
03862       addr = copy_addr_to_reg (plus_constant (dsta, ofs+size-1));
03863 
03864       if (src != const0_rtx)
03865   {
03866     switch ((int) size)
03867       {
03868       case 2:
03869         emit_insn (gen_inswl_be (insh, gen_lowpart (HImode,src), addr));
03870         break;
03871       case 4:
03872         emit_insn (gen_insll_be (insh, gen_lowpart (SImode,src), addr));
03873         break;
03874       case 8:
03875         emit_insn (gen_insql_be (insh, gen_lowpart (DImode,src), addr));
03876         break;
03877       }
03878     emit_insn (gen_insxh (insl, gen_lowpart (DImode, src),
03879         GEN_INT (size*8), addr));
03880   }
03881 
03882       switch ((int) size)
03883   {
03884   case 2:
03885     emit_insn (gen_mskxl_be (dsth, dsth, GEN_INT (0xffff), addr));
03886     break;
03887   case 4:
03888     emit_insn (gen_mskxl_be (dsth, dsth, GEN_INT (0xffffffff), addr));
03889     break;
03890   case 8:
03891     {
03892 #if HOST_BITS_PER_WIDE_INT == 32
03893       rtx msk = immed_double_const (0xffffffff, 0xffffffff, DImode);
03894 #else
03895       rtx msk = constm1_rtx;
03896 #endif
03897       emit_insn (gen_mskxl_be (dsth, dsth, msk, addr));
03898     }
03899     break;
03900   }
03901 
03902       emit_insn (gen_mskxh (dstl, dstl, GEN_INT (size*8), addr));
03903     }
03904   else
03905     {
03906       addr = copy_addr_to_reg (plus_constant (dsta, ofs));
03907 
03908       if (src != const0_rtx)
03909   {
03910     emit_insn (gen_insxh (insh, gen_lowpart (DImode, src),
03911         GEN_INT (size*8), addr));
03912 
03913     switch ((int) size)
03914       {
03915       case 2:
03916         emit_insn (gen_inswl_le (insl, gen_lowpart (HImode, src), addr));
03917         break;
03918       case 4:
03919         emit_insn (gen_insll_le (insl, gen_lowpart (SImode, src), addr));
03920         break;
03921       case 8:
03922         emit_insn (gen_insql_le (insl, src, addr));
03923         break;
03924       }
03925   }
03926 
03927       emit_insn (gen_mskxh (dsth, dsth, GEN_INT (size*8), addr));
03928 
03929       switch ((int) size)
03930   {
03931   case 2:
03932     emit_insn (gen_mskxl_le (dstl, dstl, GEN_INT (0xffff), addr));
03933     break;
03934   case 4:
03935     emit_insn (gen_mskxl_le (dstl, dstl, GEN_INT (0xffffffff), addr));
03936     break;
03937   case 8:
03938     {
03939 #if HOST_BITS_PER_WIDE_INT == 32
03940       rtx msk = immed_double_const (0xffffffff, 0xffffffff, DImode);
03941 #else
03942       rtx msk = constm1_rtx;
03943 #endif
03944       emit_insn (gen_mskxl_le (dstl, dstl, msk, addr));
03945     }
03946     break;
03947   }
03948     }
03949 
03950   if (src != const0_rtx)
03951     {
03952       dsth = expand_binop (DImode, ior_optab, insh, dsth, dsth, 0, OPTAB_WIDEN);
03953       dstl = expand_binop (DImode, ior_optab, insl, dstl, dstl, 0, OPTAB_WIDEN);
03954     }
03955  
03956   if (WORDS_BIG_ENDIAN)
03957     {
03958       emit_move_insn (meml, dstl);
03959       emit_move_insn (memh, dsth);
03960     }
03961   else
03962     {
03963       /* Must store high before low for degenerate case of aligned.  */
03964       emit_move_insn (memh, dsth);
03965       emit_move_insn (meml, dstl);
03966     }
03967 }
03968 
03969 /* The block move code tries to maximize speed by separating loads and
03970    stores at the expense of register pressure: we load all of the data
03971    before we store it back out.  There are two secondary effects worth
03972    mentioning, that this speeds copying to/from aligned and unaligned
03973    buffers, and that it makes the code significantly easier to write.  */
03974 
03975 #define MAX_MOVE_WORDS  8
03976 
03977 /* Load an integral number of consecutive unaligned quadwords.  */
03978 
03979 static void
03980 alpha_expand_unaligned_load_words (out_regs, smem, words, ofs)
03981      rtx *out_regs;
03982      rtx smem;
03983      HOST_WIDE_INT words, ofs;
03984 {
03985   rtx const im8 = GEN_INT (-8);
03986   rtx const i64 = GEN_INT (64);
03987   rtx ext_tmps[MAX_MOVE_WORDS], data_regs[MAX_MOVE_WORDS+1];
03988   rtx sreg, areg, tmp, smema;
03989   HOST_WIDE_INT i;
03990 
03991   smema = XEXP (smem, 0);
03992   if (GET_CODE (smema) == LO_SUM)
03993     smema = force_reg (Pmode, smema);
03994 
03995   /* Generate all the tmp registers we need.  */
03996   for (i = 0; i < words; ++i)
03997     {
03998       data_regs[i] = out_regs[i];
03999       ext_tmps[i] = gen_reg_rtx (DImode);
04000     }
04001   data_regs[words] = gen_reg_rtx (DImode);
04002 
04003   if (ofs != 0)
04004     smem = adjust_address (smem, GET_MODE (smem), ofs);
04005   
04006   /* Load up all of the source data.  */
04007   for (i = 0; i < words; ++i)
04008     {
04009       tmp = change_address (smem, DImode,
04010           gen_rtx_AND (DImode,
04011            plus_constant (smema, 8*i),
04012            im8));
04013       set_mem_alias_set (tmp, 0);
04014       emit_move_insn (data_regs[i], tmp);
04015     }
04016 
04017   tmp = change_address (smem, DImode,
04018       gen_rtx_AND (DImode,
04019              plus_constant (smema, 8*words - 1),
04020              im8));
04021   set_mem_alias_set (tmp, 0);
04022   emit_move_insn (data_regs[words], tmp);
04023 
04024   /* Extract the half-word fragments.  Unfortunately DEC decided to make
04025      extxh with offset zero a noop instead of zeroing the register, so 
04026      we must take care of that edge condition ourselves with cmov.  */
04027 
04028   sreg = copy_addr_to_reg (smema);
04029   areg = expand_binop (DImode, and_optab, sreg, GEN_INT (7), NULL, 
04030            1, OPTAB_WIDEN);
04031   if (WORDS_BIG_ENDIAN)
04032     emit_move_insn (sreg, plus_constant (sreg, 7));
04033   for (i = 0; i < words; ++i)
04034     {
04035       if (WORDS_BIG_ENDIAN)
04036   {
04037     emit_insn (gen_extqh_be (data_regs[i], data_regs[i], sreg));
04038     emit_insn (gen_extxl_be (ext_tmps[i], data_regs[i+1], i64, sreg));
04039   }
04040       else
04041   {
04042     emit_insn (gen_extxl_le (data_regs[i], data_regs[i], i64, sreg));
04043     emit_insn (gen_extqh_le (ext_tmps[i], data_regs[i+1], sreg));
04044   }
04045       emit_insn (gen_rtx_SET (VOIDmode, ext_tmps[i],
04046             gen_rtx_IF_THEN_ELSE (DImode,
04047                 gen_rtx_EQ (DImode, areg,
04048                 const0_rtx),
04049                 const0_rtx, ext_tmps[i])));
04050     }
04051 
04052   /* Merge the half-words into whole words.  */
04053   for (i = 0; i < words; ++i)
04054     {
04055       out_regs[i] = expand_binop (DImode, ior_optab, data_regs[i],
04056           ext_tmps[i], data_regs[i], 1, OPTAB_WIDEN);
04057     }
04058 }
04059 
04060 /* Store an integral number of consecutive unaligned quadwords.  DATA_REGS
04061    may be NULL to store zeros.  */
04062 
04063 static void
04064 alpha_expand_unaligned_store_words (data_regs, dmem, words, ofs)
04065      rtx *data_regs;
04066      rtx dmem;
04067      HOST_WIDE_INT words, ofs;
04068 {
04069   rtx const im8 = GEN_INT (-8);
04070   rtx const i64 = GEN_INT (64);
04071 #if HOST_BITS_PER_WIDE_INT == 32
04072   rtx const im1 = immed_double_const (0xffffffff, 0xffffffff, DImode);
04073 #else
04074   rtx const im1 = constm1_rtx;
04075 #endif
04076   rtx ins_tmps[MAX_MOVE_WORDS];
04077   rtx st_tmp_1, st_tmp_2, dreg;
04078   rtx st_addr_1, st_addr_2, dmema;
04079   HOST_WIDE_INT i;
04080 
04081   dmema = XEXP (dmem, 0);
04082   if (GET_CODE (dmema) == LO_SUM)
04083     dmema = force_reg (Pmode, dmema);
04084 
04085   /* Generate all the tmp registers we need.  */
04086   if (data_regs != NULL)
04087     for (i = 0; i < words; ++i)
04088       ins_tmps[i] = gen_reg_rtx(DImode);
04089   st_tmp_1 = gen_reg_rtx(DImode);
04090   st_tmp_2 = gen_reg_rtx(DImode);
04091   
04092   if (ofs != 0)
04093     dmem = adjust_address (dmem, GET_MODE (dmem), ofs);
04094 
04095   st_addr_2 = change_address (dmem, DImode,
04096             gen_rtx_AND (DImode,
04097              plus_constant (dmema, words*8 - 1),
04098                im8));
04099   set_mem_alias_set (st_addr_2, 0);
04100 
04101   st_addr_1 = change_address (dmem, DImode,
04102             gen_rtx_AND (DImode, dmema, im8));
04103   set_mem_alias_set (st_addr_1, 0);
04104 
04105   /* Load up the destination end bits.  */
04106   emit_move_insn (st_tmp_2, st_addr_2);
04107   emit_move_insn (st_tmp_1, st_addr_1);
04108 
04109   /* Shift the input data into place.  */
04110   dreg = copy_addr_to_reg (dmema);
04111   if (WORDS_BIG_ENDIAN)
04112     emit_move_insn (dreg, plus_constant (dreg, 7));
04113   if (data_regs != NULL)
04114     {
04115       for (i = words-1; i >= 0; --i)
04116   {
04117     if (WORDS_BIG_ENDIAN)
04118       {
04119         emit_insn (gen_insql_be (ins_tmps[i], data_regs[i], dreg));
04120         emit_insn (gen_insxh (data_regs[i], data_regs[i], i64, dreg));
04121       }
04122     else
04123       {
04124         emit_insn (gen_insxh (ins_tmps[i], data_regs[i], i64, dreg));
04125         emit_insn (gen_insql_le (data_regs[i], data_regs[i], dreg));
04126       }
04127   }
04128       for (i = words-1; i > 0; --i)
04129   {
04130     ins_tmps[i-1] = expand_binop (DImode, ior_optab, data_regs[i],
04131           ins_tmps[i-1], ins_tmps[i-1], 1,
04132           OPTAB_WIDEN);
04133   }
04134     }
04135 
04136   /* Split and merge the ends with the destination data.  */
04137   if (WORDS_BIG_ENDIAN)
04138     {
04139       emit_insn (gen_mskxl_be (st_tmp_2, st_tmp_2, im1, dreg));
04140       emit_insn (gen_mskxh (st_tmp_1, st_tmp_1, i64, dreg));
04141     }
04142   else
04143     {
04144       emit_insn (gen_mskxh (st_tmp_2, st_tmp_2, i64, dreg));
04145       emit_insn (gen_mskxl_le (st_tmp_1, st_tmp_1, im1, dreg));
04146     }
04147 
04148   if (data_regs != NULL)
04149     {
04150       st_tmp_2 = expand_binop (DImode, ior_optab, st_tmp_2, ins_tmps[words-1],
04151              st_tmp_2, 1, OPTAB_WIDEN);
04152       st_tmp_1 = expand_binop (DImode, ior_optab, st_tmp_1, data_regs[0],
04153              st_tmp_1, 1, OPTAB_WIDEN);
04154     }
04155 
04156   /* Store it all.  */
04157   if (WORDS_BIG_ENDIAN)
04158     emit_move_insn (st_addr_1, st_tmp_1);
04159   else
04160     emit_move_insn (st_addr_2, st_tmp_2);
04161   for (i = words-1; i > 0; --i)
04162     {
04163       rtx tmp = change_address (dmem, DImode,
04164         gen_rtx_AND (DImode,
04165                plus_constant(dmema,
04166                WORDS_BIG_ENDIAN ? i*8-1 : i*8),
04167                im8));
04168       set_mem_alias_set (tmp, 0);
04169       emit_move_insn (tmp, data_regs ? ins_tmps[i-1] : const0_rtx);
04170     }
04171   if (WORDS_BIG_ENDIAN)
04172     emit_move_insn (st_addr_2, st_tmp_2);
04173   else
04174     emit_move_insn (st_addr_1, st_tmp_1);
04175 }
04176 
04177 
04178 /* Expand string/block move operations.
04179 
04180    operands[0] is the pointer to the destination.
04181    operands[1] is the pointer to the source.
04182    operands[2] is the number of bytes to move.
04183    operands[3] is the alignment.  */
04184 
04185 int
04186 alpha_expand_block_move (operands)
04187      rtx operands[];
04188 {
04189   rtx bytes_rtx = operands[2];
04190   rtx align_rtx = operands[3];
04191   HOST_WIDE_INT orig_bytes = INTVAL (bytes_rtx);
04192   HOST_WIDE_INT bytes = orig_bytes;
04193   HOST_WIDE_INT src_align = INTVAL (align_rtx) * BITS_PER_UNIT;
04194   HOST_WIDE_INT dst_align = src_align;
04195   rtx orig_src = operands[1];
04196   rtx orig_dst = operands[0];
04197   rtx data_regs[2 * MAX_MOVE_WORDS + 16];
04198   rtx tmp;
04199   unsigned int i, words, ofs, nregs = 0;
04200   
04201   if (orig_bytes <= 0)
04202     return 1;
04203   else if (orig_bytes > MAX_MOVE_WORDS * UNITS_PER_WORD)
04204     return 0;
04205 
04206   /* Look for additional alignment information from recorded register info.  */
04207 
04208   tmp = XEXP (orig_src, 0);
04209   if (GET_CODE (tmp) == REG)
04210     src_align = MAX (src_align, REGNO_POINTER_ALIGN (REGNO (tmp)));
04211   else if (GET_CODE (tmp) == PLUS
04212      && GET_CODE (XEXP (tmp, 0)) == REG
04213      && GET_CODE (XEXP (tmp, 1)) == CONST_INT)
04214     {
04215       unsigned HOST_WIDE_INT c = INTVAL (XEXP (tmp, 1));
04216       unsigned int a = REGNO_POINTER_ALIGN (REGNO (XEXP (tmp, 0)));
04217 
04218       if (a > src_align)
04219   {
04220           if (a >= 64 && c % 8 == 0)
04221       src_align = 64;
04222           else if (a >= 32 && c % 4 == 0)
04223       src_align = 32;
04224           else if (a >= 16 && c % 2 == 0)
04225       src_align = 16;
04226   }
04227     }
04228   
04229   tmp = XEXP (orig_dst, 0);
04230   if (GET_CODE (tmp) == REG)
04231     dst_align = MAX (dst_align, REGNO_POINTER_ALIGN (REGNO (tmp)));
04232   else if (GET_CODE (tmp) == PLUS
04233      && GET_CODE (XEXP (tmp, 0)) == REG
04234      && GET_CODE (XEXP (tmp, 1)) == CONST_INT)
04235     {
04236       unsigned HOST_WIDE_INT c = INTVAL (XEXP (tmp, 1));
04237       unsigned int a = REGNO_POINTER_ALIGN (REGNO (XEXP (tmp, 0)));
04238 
04239       if (a > dst_align)
04240   {
04241           if (a >= 64 && c % 8 == 0)
04242       dst_align = 64;
04243           else if (a >= 32 && c % 4 == 0)
04244       dst_align = 32;
04245           else if (a >= 16 && c % 2 == 0)
04246       dst_align = 16;
04247   }
04248     }
04249 
04250   /* Load the entire block into registers.  */
04251   if (GET_CODE (XEXP (orig_src, 0)) == ADDRESSOF)
04252     {
04253       enum machine_mode mode;
04254 
04255       tmp = XEXP (XEXP (orig_src, 0), 0);
04256 
04257       /* Don't use the existing register if we're reading more than
04258    is held in the register.  Nor if there is not a mode that
04259    handles the exact size.  */
04260       mode = mode_for_size (bytes * BITS_PER_UNIT, MODE_INT, 1);
04261       if (mode != BLKmode
04262     && GET_MODE_SIZE (GET_MODE (tmp)) >= bytes)
04263   {
04264     if (mode == TImode)
04265       {
04266         data_regs[nregs] = gen_lowpart (DImode, tmp);
04267         data_regs[nregs + 1] = gen_highpart (DImode, tmp);
04268         nregs += 2;
04269       }
04270     else
04271       data_regs[nregs++] = gen_lowpart (mode, tmp);
04272 
04273     goto src_done;
04274   }
04275 
04276       /* No appropriate mode; fall back on memory.  */
04277       orig_src = replace_equiv_address (orig_src,
04278           copy_addr_to_reg (XEXP (orig_src, 0)));
04279       src_align = GET_MODE_BITSIZE (GET_MODE (tmp));
04280     }
04281 
04282   ofs = 0;
04283   if (src_align >= 64 && bytes >= 8)
04284     {
04285       words = bytes / 8;
04286 
04287       for (i = 0; i < words; ++i)
04288   data_regs[nregs + i] = gen_reg_rtx (DImode);
04289 
04290       for (i = 0; i < words; ++i)
04291   emit_move_insn (data_regs[nregs + i],
04292       adjust_address (orig_src, DImode, ofs + i * 8));
04293 
04294       nregs += words;
04295       bytes -= words * 8;
04296       ofs += words * 8;
04297     }
04298 
04299   if (src_align >= 32 && bytes >= 4)
04300     {
04301       words = bytes / 4;
04302 
04303       for (i = 0; i < words; ++i)
04304   data_regs[nregs + i] = gen_reg_rtx (SImode);
04305 
04306       for (i = 0; i < words; ++i)
04307   emit_move_insn (data_regs[nregs + i],
04308       adjust_address (orig_src, SImode, ofs + i * 4));
04309 
04310       nregs += words;
04311       bytes -= words * 4;
04312       ofs += words * 4;
04313     }
04314 
04315   if (bytes >= 8)
04316     {
04317       words = bytes / 8;
04318 
04319       for (i = 0; i < words+1; ++i)
04320   data_regs[nregs + i] = gen_reg_rtx (DImode);
04321 
04322       alpha_expand_unaligned_load_words (data_regs + nregs, orig_src,
04323            words, ofs);
04324 
04325       nregs += words;
04326       bytes -= words * 8;
04327       ofs += words * 8;
04328     }
04329 
04330   if (! TARGET_BWX && bytes >= 4)
04331     {
04332       data_regs[nregs++] = tmp = gen_reg_rtx (SImode);
04333       alpha_expand_unaligned_load (tmp, orig_src, 4, ofs, 0);
04334       bytes -= 4;
04335       ofs += 4;
04336     }
04337 
04338   if (bytes >= 2)
04339     {
04340       if (src_align >= 16)
04341   {
04342     do {
04343       data_regs[nregs++] = tmp = gen_reg_rtx (HImode);
04344       emit_move_insn (tmp, adjust_address (orig_src, HImode, ofs));
04345       bytes -= 2;
04346       ofs += 2;
04347     } while (bytes >= 2);
04348   }
04349       else if (! TARGET_BWX)
04350   {
04351     data_regs[nregs++] = tmp = gen_reg_rtx (HImode);
04352     alpha_expand_unaligned_load (tmp, orig_src, 2, ofs, 0);
04353     bytes -= 2;
04354     ofs += 2;
04355   }
04356     }
04357 
04358   while (bytes > 0)
04359     {
04360       data_regs[nregs++] = tmp = gen_reg_rtx (QImode);
04361       emit_move_insn (tmp, adjust_address (orig_src, QImode, ofs));
04362       bytes -= 1;
04363       ofs += 1;
04364     }
04365 
04366  src_done:
04367 
04368   if (nregs > ARRAY_SIZE (data_regs))
04369     abort ();
04370 
04371   /* Now save it back out again.  */
04372 
04373   i = 0, ofs = 0;
04374 
04375   if (GET_CODE (XEXP (orig_dst, 0)) == ADDRESSOF)
04376     {
04377       enum machine_mode mode;
04378       tmp = XEXP (XEXP (orig_dst, 0), 0);
04379 
04380       mode = mode_for_size (orig_bytes * BITS_PER_UNIT, MODE_INT, 1);
04381       if (GET_MODE (tmp) == mode)
04382   {
04383     if (nregs == 1)
04384       {
04385         emit_move_insn (tmp, data_regs[0]);
04386         i = 1;
04387         goto dst_done;
04388       }
04389 
04390     else if (nregs == 2 && mode == TImode)
04391       {
04392         /* Undo the subregging done above when copying between
04393      two TImode registers.  */
04394         if (GET_CODE (data_regs[0]) == SUBREG
04395       && GET_MODE (SUBREG_REG (data_regs[0])) == TImode)
04396     emit_move_insn (tmp, SUBREG_REG (data_regs[0]));
04397         else
04398     {
04399       rtx seq;
04400 
04401       start_sequence ();
04402       emit_move_insn (gen_lowpart (DImode, tmp), data_regs[0]);
04403       emit_move_insn (gen_highpart (DImode, tmp), data_regs[1]);
04404       seq = get_insns ();
04405       end_sequence ();
04406 
04407       emit_no_conflict_block (seq, tmp, data_regs[0],
04408             data_regs[1], NULL_RTX);
04409     }
04410 
04411         i = 2;
04412         goto dst_done;
04413       }
04414   }
04415 
04416       /* ??? If nregs > 1, consider reconstructing the word in regs.  */
04417       /* ??? Optimize mode < dst_mode with strict_low_part.  */
04418 
04419       /* No appropriate mode; fall back on memory.  We can speed things
04420    up by recognizing extra alignment information.  */
04421       orig_dst = replace_equiv_address (orig_dst,
04422           copy_addr_to_reg (XEXP (orig_dst, 0)));
04423       dst_align = GET_MODE_BITSIZE (GET_MODE (tmp));
04424     }
04425 
04426   /* Write out the data in whatever chunks reading the source allowed.  */
04427   if (dst_align >= 64)
04428     {
04429       while (i < nregs && GET_MODE (data_regs[i]) == DImode)
04430   {
04431     emit_move_insn (adjust_address (orig_dst, DImode, ofs),
04432         data_regs[i]);
04433     ofs += 8;
04434     i++;
04435   }
04436     }
04437 
04438   if (dst_align >= 32)
04439     {
04440       /* If the source has remaining DImode regs, write them out in
04441    two pieces.  */
04442       while (i < nregs && GET_MODE (data_regs[i]) == DImode)
04443   {
04444     tmp = expand_binop (DImode, lshr_optab, data_regs[i], GEN_INT (32),
04445             NULL_RTX, 1, OPTAB_WIDEN);
04446 
04447     emit_move_insn (adjust_address (orig_dst, SImode, ofs),
04448         gen_lowpart (SImode, data_regs[i]));
04449     emit_move_insn (adjust_address (orig_dst, SImode, ofs + 4),
04450         gen_lowpart (SImode, tmp));
04451     ofs += 8;
04452     i++;
04453   }
04454 
04455       while (i < nregs && GET_MODE (data_regs[i]) == SImode)
04456   {
04457     emit_move_insn (adjust_address (orig_dst, SImode, ofs),
04458         data_regs[i]);
04459     ofs += 4;
04460     i++;
04461   }
04462     }
04463 
04464   if (i < nregs && GET_MODE (data_regs[i]) == DImode)
04465     {
04466       /* Write out a remaining block of words using unaligned methods.  */
04467 
04468       for (words = 1; i + words < nregs; words++)
04469   if (GET_MODE (data_regs[i + words]) != DImode)
04470     break;
04471 
04472       if (words == 1)
04473   alpha_expand_unaligned_store (orig_dst, data_regs[i], 8, ofs);
04474       else
04475         alpha_expand_unaligned_store_words (data_regs + i, orig_dst,
04476               words, ofs);
04477      
04478       i += words;
04479       ofs += words * 8;
04480     }
04481 
04482   /* Due to the above, this won't be aligned.  */
04483   /* ??? If we have more than one of these, consider constructing full
04484      words in registers and using alpha_expand_unaligned_store_words.  */
04485   while (i < nregs && GET_MODE (data_regs[i]) == SImode)
04486     {
04487       alpha_expand_unaligned_store (orig_dst, data_regs[i], 4, ofs);
04488       ofs += 4;
04489       i++;
04490     }
04491 
04492   if (dst_align >= 16)
04493     while (i < nregs && GET_MODE (data_regs[i]) == HImode)
04494       {
04495   emit_move_insn (adjust_address (orig_dst, HImode, ofs), data_regs[i]);
04496   i++;
04497   ofs += 2;
04498       }
04499   else
04500     while (i < nregs && GET_MODE (data_regs[i]) == HImode)
04501       {
04502   alpha_expand_unaligned_store (orig_dst, data_regs[i], 2, ofs);
04503   i++;
04504   ofs += 2;
04505       }
04506 
04507   while (i < nregs && GET_MODE (data_regs[i]) == QImode)
04508     {
04509       emit_move_insn (adjust_address (orig_dst, QImode, ofs), data_regs[i]);
04510       i++;
04511       ofs += 1;
04512     }
04513 
04514  dst_done:
04515 
04516   if (i != nregs)
04517     abort ();
04518 
04519   return 1;
04520 }
04521 
04522 int
04523 alpha_expand_block_clear (operands)
04524      rtx operands[];
04525 {
04526   rtx bytes_rtx = operands[1];
04527   rtx align_rtx = operands[2];
04528   HOST_WIDE_INT orig_bytes = INTVAL (bytes_rtx);
04529   HOST_WIDE_INT bytes = orig_bytes;
04530   HOST_WIDE_INT align = INTVAL (align_rtx) * BITS_PER_UNIT;
04531   HOST_WIDE_INT alignofs = 0;
04532   rtx orig_dst = operands[0];
04533   rtx tmp;
04534   int i, words, ofs = 0;
04535   
04536   if (orig_bytes <= 0)
04537     return 1;
04538   if (orig_bytes > MAX_MOVE_WORDS * UNITS_PER_WORD)
04539     return 0;
04540 
04541   /* Look for stricter alignment.  */
04542   tmp = XEXP (orig_dst, 0);
04543   if (GET_CODE (tmp) == REG)
04544     align = MAX (align, REGNO_POINTER_ALIGN (REGNO (tmp)));
04545   else if (GET_CODE (tmp) == PLUS
04546      && GET_CODE (XEXP (tmp, 0)) == REG
04547      && GET_CODE (XEXP (tmp, 1)) == CONST_INT)
04548     {
04549       HOST_WIDE_INT c = INTVAL (XEXP (tmp, 1));
04550       int a = REGNO_POINTER_ALIGN (REGNO (XEXP (tmp, 0)));
04551 
04552       if (a > align)
04553   {
04554           if (a >= 64)
04555       align = a, alignofs = 8 - c % 8;
04556           else if (a >= 32)
04557       align = a, alignofs = 4 - c % 4;
04558           else if (a >= 16)
04559       align = a, alignofs = 2 - c % 2;
04560   }
04561     }
04562   else if (GET_CODE (tmp) == ADDRESSOF)
04563     {
04564       enum machine_mode mode;
04565 
04566       mode = mode_for_size (bytes * BITS_PER_UNIT, MODE_INT, 1);
04567       if (GET_MODE (XEXP (tmp, 0)) == mode)
04568   {
04569     emit_move_insn (XEXP (tmp, 0), const0_rtx);
04570     return 1;
04571   }
04572 
04573       /* No appropriate mode; fall back on memory.  */
04574       orig_dst = replace_equiv_address (orig_dst, copy_addr_to_reg (tmp));
04575       align = GET_MODE_BITSIZE (GET_MODE (XEXP (tmp, 0)));
04576     }
04577 
04578   /* Handle an unaligned prefix first.  */
04579 
04580   if (alignofs > 0)
04581     {
04582 #if HOST_BITS_PER_WIDE_INT >= 64
04583       /* Given that alignofs is bounded by align, the only time BWX could
04584    generate three stores is for a 7 byte fill.  Prefer two individual
04585    stores over a load/mask/store sequence.  */
04586       if ((!TARGET_BWX || alignofs == 7)
04587          && align >= 32
04588          && !(alignofs == 4 && bytes >= 4))
04589   {
04590     enum machine_mode mode = (align >= 64 ? DImode : SImode);
04591     int inv_alignofs = (align >= 64 ? 8 : 4) - alignofs;
04592     rtx mem, tmp;
04593     HOST_WIDE_INT mask;
04594 
04595     mem = adjust_address (orig_dst, mode, ofs - inv_alignofs);
04596     set_mem_alias_set (mem, 0);
04597 
04598     mask = ~(~(HOST_WIDE_INT)0 << (inv_alignofs * 8));
04599     if (bytes < alignofs)
04600       {
04601         mask |= ~(HOST_WIDE_INT)0 << ((inv_alignofs + bytes) * 8);
04602         ofs += bytes;
04603         bytes = 0;
04604       }
04605     else
04606       {
04607         bytes -= alignofs;
04608         ofs += alignofs;
04609       }
04610     alignofs = 0;
04611 
04612     tmp = expand_binop (mode, and_optab, mem, GEN_INT (mask),
04613             NULL_RTX, 1, OPTAB_WIDEN);
04614 
04615     emit_move_insn (mem, tmp);
04616   }
04617 #endif
04618 
04619       if (TARGET_BWX && (alignofs & 1) && bytes >= 1)
04620   {
04621     emit_move_insn (adjust_address (orig_dst, QImode, ofs), const0_rtx);
04622     bytes -= 1;
04623     ofs += 1;
04624     alignofs -= 1;
04625   }
04626       if (TARGET_BWX && align >= 16 && (alignofs & 3) == 2 && bytes >= 2)
04627   {
04628     emit_move_insn (adjust_address (orig_dst, HImode, ofs), const0_rtx);
04629     bytes -= 2;
04630     ofs += 2;
04631     alignofs -= 2;
04632   }
04633       if (alignofs == 4 && bytes >= 4)
04634   {
04635     emit_move_insn (adjust_address (orig_dst, SImode, ofs), const0_rtx);
04636     bytes -= 4;
04637     ofs += 4;
04638     alignofs = 0;
04639   }
04640 
04641       /* If we've not used the extra lead alignment information by now,
04642    we won't be able to.  Downgrade align to match what's left over.  */
04643       if (alignofs > 0)
04644   {
04645     alignofs = alignofs & -alignofs;
04646     align = MIN (align, alignofs * BITS_PER_UNIT);
04647   }
04648     }
04649 
04650   /* Handle a block of contiguous long-words.  */
04651 
04652   if (align >= 64 && bytes >= 8)
04653     {
04654       words = bytes / 8;
04655 
04656       for (i = 0; i < words; ++i)
04657   emit_move_insn (adjust_address (orig_dst, DImode, ofs + i * 8),
04658       const0_rtx);
04659 
04660       bytes -= words * 8;
04661       ofs += words * 8;
04662     }
04663 
04664   /* If the block is large and appropriately aligned, emit a single
04665      store followed by a sequence of stq_u insns.  */
04666 
04667   if (align >= 32 && bytes > 16)
04668     {
04669       rtx orig_dsta;
04670 
04671       emit_move_insn (adjust_address (orig_dst, SImode, ofs), const0_rtx);
04672       bytes -= 4;
04673       ofs += 4;
04674 
04675       orig_dsta = XEXP (orig_dst, 0);
04676       if (GET_CODE (orig_dsta) == LO_SUM)
04677   orig_dsta = force_reg (Pmode, orig_dsta);
04678 
04679       words = bytes / 8;
04680       for (i = 0; i < words; ++i)
04681   {
04682     rtx mem
04683       = change_address (orig_dst, DImode,
04684             gen_rtx_AND (DImode,
04685              plus_constant (orig_dsta, ofs + i*8),
04686              GEN_INT (-8)));
04687     set_mem_alias_set (mem, 0);
04688     emit_move_insn (mem, const0_rtx);
04689   }
04690 
04691       /* Depending on the alignment, the first stq_u may have overlapped
04692    with the initial stl, which means that the last stq_u didn't
04693    write as much as it would appear.  Leave those questionable bytes
04694    unaccounted for.  */
04695       bytes -= words * 8 - 4;
04696       ofs += words * 8 - 4;
04697     }
04698 
04699   /* Handle a smaller block of aligned words.  */
04700 
04701   if ((align >= 64 && bytes == 4)
04702       || (align == 32 && bytes >= 4))
04703     {
04704       words = bytes / 4;
04705 
04706       for (i = 0; i < words; ++i)
04707   emit_move_insn (adjust_address (orig_dst, SImode, ofs + i * 4),
04708       const0_rtx);
04709 
04710       bytes -= words * 4;
04711       ofs += words * 4;
04712     }
04713 
04714   /* An unaligned block uses stq_u stores for as many as possible.  */
04715 
04716   if (bytes >= 8)
04717     {
04718       words = bytes / 8;
04719 
04720       alpha_expand_unaligned_store_words (NULL, orig_dst, words, ofs);
04721 
04722       bytes -= words * 8;
04723       ofs += words * 8;
04724     }
04725 
04726   /* Next clean up any trailing pieces.  */
04727 
04728 #if HOST_BITS_PER_WIDE_INT >= 64
04729   /* Count the number of bits in BYTES for which aligned stores could
04730      be emitted.  */
04731   words = 0;
04732   for (i = (TARGET_BWX ? 1 : 4); i * BITS_PER_UNIT <= align ; i <<= 1)
04733     if (bytes & i)
04734       words += 1;
04735 
04736   /* If we have appropriate alignment (and it wouldn't take too many
04737      instructions otherwise), mask out the bytes we need.  */
04738   if (TARGET_BWX ? words > 2 : bytes > 0)
04739     {
04740       if (align >= 64)
04741   {
04742     rtx mem, tmp;
04743     HOST_WIDE_INT mask;
04744 
04745     mem = adjust_address (orig_dst, DImode, ofs);
04746     set_mem_alias_set (mem, 0);
04747 
04748     mask = ~(HOST_WIDE_INT)0 << (bytes * 8);
04749 
04750     tmp = expand_binop (DImode, and_optab, mem, GEN_INT (mask),
04751             NULL_RTX, 1, OPTAB_WIDEN);
04752 
04753     emit_move_insn (mem, tmp);
04754     return 1;
04755   }
04756       else if (align >= 32 && bytes < 4)
04757   {
04758     rtx mem, tmp;
04759     HOST_WIDE_INT mask;
04760 
04761     mem = adjust_address (orig_dst, SImode, ofs);
04762     set_mem_alias_set (mem, 0);
04763 
04764     mask = ~(HOST_WIDE_INT)0 << (bytes * 8);
04765 
04766     tmp = expand_binop (SImode, and_optab, mem, GEN_INT (mask),
04767             NULL_RTX, 1, OPTAB_WIDEN);
04768 
04769     emit_move_insn (mem, tmp);
04770     return 1;
04771   }
04772     }
04773 #endif
04774 
04775   if (!TARGET_BWX && bytes >= 4)
04776     {
04777       alpha_expand_unaligned_store (orig_dst, const0_rtx, 4, ofs);
04778       bytes -= 4;
04779       ofs += 4;
04780     }
04781 
04782   if (bytes >= 2)
04783     {
04784       if (align >= 16)
04785   {
04786     do {
04787       emit_move_insn (adjust_address (orig_dst, HImode, ofs),
04788           const0_rtx);
04789       bytes -= 2;
04790       ofs += 2;
04791     } while (bytes >= 2);
04792   }
04793       else if (! TARGET_BWX)
04794   {
04795     alpha_expand_unaligned_store (orig_dst, const0_rtx, 2, ofs);
04796     bytes -= 2;
04797     ofs += 2;
04798   }
04799     }
04800 
04801   while (bytes > 0)
04802     {
04803       emit_move_insn (adjust_address (orig_dst, QImode, ofs), const0_rtx);
04804       bytes -= 1;
04805       ofs += 1;
04806     }
04807 
04808   return 1;
04809 }
04810 
04811 /* Adjust the cost of a scheduling dependency.  Return the new cost of
04812    a dependency LINK or INSN on DEP_INSN.  COST is the current cost.  */
04813 
04814 static int
04815 alpha_adjust_cost (insn, link, dep_insn, cost)
04816      rtx insn;
04817      rtx link;
04818      rtx dep_insn;
04819      int cost;
04820 {
04821   rtx set, set_src;
04822   enum attr_type insn_type, dep_insn_type;
04823 
04824   /* If the dependence is an anti-dependence, there is no cost.  For an
04825      output dependence, there is sometimes a cost, but it doesn't seem
04826      worth handling those few cases.  */
04827 
04828   if (REG_NOTE_KIND (link) != 0)
04829     return 0;
04830 
04831   /* If we can't recognize the insns, we can't really do anything.  */
04832   if (recog_memoized (insn) < 0 || recog_memoized (dep_insn) < 0)
04833     return cost;
04834 
04835   insn_type = get_attr_type (insn);
04836   dep_insn_type = get_attr_type (dep_insn);
04837 
04838   /* Bring in the user-defined memory latency.  */
04839   if (dep_insn_type == TYPE_ILD
04840       || dep_insn_type == TYPE_FLD
04841       || dep_insn_type == TYPE_LDSYM)
04842     cost += alpha_memory_latency-1;
04843 
04844   switch (alpha_cpu)
04845     {
04846     case PROCESSOR_EV4:
04847       /* On EV4, if INSN is a store insn and DEP_INSN is setting the data
04848    being stored, we can sometimes lower the cost.  */
04849 
04850       if ((insn_type == TYPE_IST || insn_type == TYPE_FST)
04851     && (set = single_set (dep_insn)) != 0
04852     && GET_CODE (PATTERN (insn)) == SET
04853     && rtx_equal_p (SET_DEST (set), SET_SRC (PATTERN (insn))))
04854   {
04855     switch (dep_insn_type)
04856       {
04857       case TYPE_ILD:
04858       case TYPE_FLD:
04859         /* No savings here.  */
04860         return cost;
04861 
04862       case TYPE_IMUL:
04863         /* In these cases, we save one cycle.  */
04864         return cost - 1;
04865 
04866       default:
04867         /* In all other cases, we save two cycles.  */
04868         return MAX (0, cost - 2);
04869       }
04870   }
04871 
04872       /* Another case that needs adjustment is an arithmetic or logical
04873    operation.  It's cost is usually one cycle, but we default it to
04874    two in the MD file.  The only case that it is actually two is
04875    for the address in loads, stores, and jumps.  */
04876 
04877       if (dep_insn_type == TYPE_IADD || dep_insn_type == TYPE_ILOG)
04878   {
04879     switch (insn_type)
04880       {
04881       case TYPE_ILD:
04882       case TYPE_IST:
04883       case TYPE_FLD:
04884       case TYPE_FST:
04885       case TYPE_JSR:
04886         return cost;
04887       default:
04888         return 1;
04889       }
04890   }
04891 
04892       /* The final case is when a compare feeds into an integer branch;
04893    the cost is only one cycle in that case.  */
04894 
04895       if (dep_insn_type == TYPE_ICMP && insn_type == TYPE_IBR)
04896   return 1;
04897       break;
04898 
04899     case PROCESSOR_EV5:
04900       /* And the lord DEC saith:  "A special bypass provides an effective
04901    latency of 0 cycles for an ICMP or ILOG insn producing the test
04902    operand of an IBR or ICMOV insn." */
04903 
04904       if ((dep_insn_type == TYPE_ICMP || dep_insn_type == TYPE_ILOG)
04905     && (set = single_set (dep_insn)) != 0)
04906   {
04907     /* A branch only has one input.  This must be it.  */
04908     if (insn_type == TYPE_IBR)
04909       return 0;
04910     /* A conditional move has three, make sure it is the test.  */
04911     if (insn_type == TYPE_ICMOV
04912         && GET_CODE (set_src = PATTERN (insn)) == SET
04913         && GET_CODE (set_src = SET_SRC (set_src)) == IF_THEN_ELSE
04914         && rtx_equal_p (SET_DEST (set), XEXP (set_src, 0)))
04915       return 0;
04916   }
04917 
04918       /* "The multiplier is unable to receive data from IEU bypass paths.
04919    The instruction issues at the expected time, but its latency is
04920    increased by the time it takes for the input data to become
04921    available to the multiplier" -- which happens in pipeline stage
04922    six, when results are comitted to the register file.  */
04923 
04924       if (insn_type == TYPE_IMUL)
04925   {
04926     switch (dep_insn_type)
04927       {
04928       /* These insns produce their results in pipeline stage five.  */
04929       case TYPE_ILD:
04930       case TYPE_ICMOV:
04931       case TYPE_IMUL:
04932       case TYPE_MVI:
04933         return cost + 1;
04934 
04935       /* Other integer insns produce results in pipeline stage four.  */
04936       default:
04937         return cost + 2;
04938       }
04939   }
04940       break;
04941 
04942     case PROCESSOR_EV6:
04943       /* There is additional latency to move the result of (most) FP 
04944          operations anywhere but the FP register file.  */
04945 
04946       if ((insn_type == TYPE_FST || insn_type == TYPE_FTOI)
04947     && (dep_insn_type == TYPE_FADD ||
04948         dep_insn_type == TYPE_FMUL ||
04949         dep_insn_type == TYPE_FCMOV))
04950         return cost + 2;
04951 
04952       break;
04953     }
04954 
04955   /* Otherwise, return the default cost.  */
04956   return cost;
04957 }
04958 
04959 /* Function to initialize the issue rate used by the scheduler.  */
04960 static int
04961 alpha_issue_rate ()
04962 {
04963   return (alpha_cpu == PROCESSOR_EV4 ? 2 : 4);
04964 }
04965 
04966 static int
04967 alpha_variable_issue (dump, verbose, insn, cim)
04968      FILE *dump ATTRIBUTE_UNUSED;
04969      int verbose ATTRIBUTE_UNUSED;
04970      rtx insn;
04971      int cim;
04972 {
04973     if (recog_memoized (insn) < 0 || get_attr_type (insn) == TYPE_MULTI)
04974       return 0;
04975 
04976     return cim - 1;
04977 }
04978 
04979 
04980 /* Register global variables and machine-specific functions with the
04981    garbage collector.  */
04982 
04983 #if TARGET_ABI_UNICOSMK
04984 static void
04985 alpha_init_machine_status (p)
04986      struct function *p;
04987 {
04988   p->machine =
04989     (struct machine_function *) xcalloc (1, sizeof (struct machine_function));
04990 
04991   p->machine->first_ciw = NULL_RTX;
04992   p->machine->last_ciw = NULL_RTX;
04993   p->machine->ciw_count = 0;
04994   p->machine->addr_list = NULL_RTX;
04995 }
04996 
04997 static void
04998 alpha_mark_machine_status (p)
04999      struct function *p;
05000 {
05001   struct machine_function *machine = p->machine;
05002 
05003   if (machine)
05004     {
05005       ggc_mark_rtx (machine->first_ciw);
05006       ggc_mark_rtx (machine->addr_list);
05007     }
05008 }
05009 
05010 static void
05011 alpha_free_machine_status (p)
05012      struct function *p;
05013 {
05014   free (p->machine);
05015   p->machine = NULL;
05016 }
05017 #endif /* TARGET_ABI_UNICOSMK */
05018 
05019 /* Functions to save and restore alpha_return_addr_rtx.  */
05020 
05021 /* Start the ball rolling with RETURN_ADDR_RTX.  */
05022 
05023 rtx
05024 alpha_return_addr (count, frame)
05025      int count;
05026      rtx frame ATTRIBUTE_UNUSED;
05027 {
05028   if (count != 0)
05029     return const0_rtx;
05030 
05031   return get_hard_reg_initial_val (Pmode, REG_RA);
05032 }
05033 
05034 /* Return or create a pseudo containing the gp value for the current
05035    function.  Needed only if TARGET_LD_BUGGY_LDGP.  */
05036 
05037 rtx
05038 alpha_gp_save_rtx ()
05039 {
05040   rtx r = get_hard_reg_initial_val (DImode, 29);
05041   if (GET_CODE (r) != MEM)
05042     r = gen_mem_addressof (r, NULL_TREE);
05043   return r;
05044 }
05045 
05046 static int
05047 alpha_ra_ever_killed ()
05048 {
05049   rtx top;
05050 
05051   if (!has_hard_reg_initial_val (Pmode, REG_RA))
05052     return regs_ever_live[REG_RA];
05053 
05054   push_topmost_sequence ();
05055   top = get_insns ();
05056   pop_topmost_sequence ();
05057 
05058   return reg_set_between_p (gen_rtx_REG (Pmode, REG_RA), top, NULL_RTX);
05059 }
05060 
05061 
05062 /* Return the trap mode suffix applicable to the current
05063    instruction, or NULL.  */
05064 
05065 static const char *
05066 get_trap_mode_suffix ()
05067 {
05068   enum attr_trap_suffix s = get_attr_trap_suffix (current_output_insn);
05069 
05070   switch (s)
05071     {
05072     case TRAP_SUFFIX_NONE:
05073       return NULL;
05074 
05075     case TRAP_SUFFIX_SU:
05076       if (alpha_fptm >= ALPHA_FPTM_SU)
05077   return "su";
05078       return NULL;
05079 
05080     case TRAP_SUFFIX_SUI:
05081       if (alpha_fptm >= ALPHA_FPTM_SUI)
05082   return "sui";
05083       return NULL;
05084 
05085     case TRAP_SUFFIX_V_SV:
05086       switch (alpha_fptm)
05087   {
05088   case ALPHA_FPTM_N:
05089     return NULL;
05090   case ALPHA_FPTM_U:
05091     return "v";
05092   case ALPHA_FPTM_SU:
05093   case ALPHA_FPTM_SUI:
05094     return "sv";
05095   }
05096       break;
05097 
05098     case TRAP_SUFFIX_V_SV_SVI:
05099       switch (alpha_fptm)
05100   {
05101   case ALPHA_FPTM_N:
05102     return NULL;
05103   case ALPHA_FPTM_U:
05104     return "v";
05105   case ALPHA_FPTM_SU:
05106     return "sv";
05107   case ALPHA_FPTM_SUI:
05108     return "svi";
05109   }
05110       break;
05111 
05112     case TRAP_SUFFIX_U_SU_SUI:
05113       switch (alpha_fptm)
05114   {
05115   case ALPHA_FPTM_N:
05116     return NULL;
05117   case ALPHA_FPTM_U:
05118     return "u";
05119   case ALPHA_FPTM_SU:
05120     return "su";
05121   case ALPHA_FPTM_SUI:
05122     return "sui";
05123   }
05124       break;
05125     }
05126   abort ();
05127 }
05128 
05129 /* Return the rounding mode suffix applicable to the current
05130    instruction, or NULL.  */
05131 
05132 static const char *
05133 get_round_mode_suffix ()
05134 {
05135   enum attr_round_suffix s = get_attr_round_suffix (current_output_insn);
05136 
05137   switch (s)
05138     {
05139     case ROUND_SUFFIX_NONE:
05140       return NULL;
05141     case ROUND_SUFFIX_NORMAL:
05142       switch (alpha_fprm)
05143   {
05144   case ALPHA_FPRM_NORM:
05145     return NULL;
05146   case ALPHA_FPRM_MINF: 
05147     return "m";
05148   case ALPHA_FPRM_CHOP:
05149     return "c";
05150   case ALPHA_FPRM_DYN:
05151     return "d";
05152   }
05153       break;
05154 
05155     case ROUND_SUFFIX_C:
05156       return "c";
05157     }
05158   abort ();
05159 }
05160 
05161 /* Print an operand.  Recognize special options, documented below.  */
05162 
05163 void
05164 print_operand (file, x, code)
05165     FILE *file;
05166     rtx x;
05167     int code;
05168 {
05169   int i;
05170 
05171   switch (code)
05172     {
05173     case '~':
05174       /* Print the assembler name of the current function.  */
05175       assemble_name (file, alpha_fnname);
05176       break;
05177 
05178     case '/':
05179       {
05180   const char *trap = get_trap_mode_suffix ();
05181   const char *round = get_round_mode_suffix ();
05182 
05183   if (trap || round)
05184     fprintf (file, (TARGET_AS_SLASH_BEFORE_SUFFIX ? "/%s%s" : "%s%s"),
05185        (trap ? trap : ""), (round ? round : ""));
05186   break;
05187       }
05188 
05189     case ',':
05190       /* Generates single precision instruction suffix.  */
05191       fputc ((TARGET_FLOAT_VAX ? 'f' : 's'), file);
05192       break;
05193 
05194     case '-':
05195       /* Generates double precision instruction suffix.  */
05196       fputc ((TARGET_FLOAT_VAX ? 'g' : 't'), file);
05197       break;
05198 
05199     case '#':
05200       if (alpha_this_literal_sequence_number == 0)
05201   alpha_this_literal_sequence_number = alpha_next_sequence_number++;
05202       fprintf (file, "%d", alpha_this_literal_sequence_number);
05203       break;
05204 
05205     case '*':
05206       if (alpha_this_gpdisp_sequence_number == 0)
05207   alpha_this_gpdisp_sequence_number = alpha_next_sequence_number++;
05208       fprintf (file, "%d", alpha_this_gpdisp_sequence_number);
05209       break;
05210 
05211     case 'H':
05212       if (GET_CODE (x) == HIGH)
05213   output_addr_const (file, XEXP (x, 0));
05214       else
05215   output_operand_lossage ("invalid %%H value");
05216       break;
05217 
05218     case 'J':
05219       if (GET_CODE (x) == CONST_INT)
05220   {
05221     if (INTVAL (x) != 0)
05222       fprintf (file, "\t\t!lituse_jsr!%d", (int) INTVAL (x));
05223   }
05224       else
05225   output_operand_lossage ("invalid %%J value");
05226       break;
05227 
05228     case 'r':
05229       /* If this operand is the constant zero, write it as "$31".  */
05230       if (GET_CODE (x) == REG)
05231   fprintf (file, "%s", reg_names[REGNO (x)]);
05232       else if (x == CONST0_RTX (GET_MODE (x)))
05233   fprintf (file, "$31");
05234       else
05235   output_operand_lossage ("invalid %%r value");
05236       break;
05237 
05238     case 'R':
05239       /* Similar, but for floating-point.  */
05240       if (GET_CODE (x) == REG)
05241   fprintf (file, "%s", reg_names[REGNO (x)]);
05242       else if (x == CONST0_RTX (GET_MODE (x)))
05243   fprintf (file, "$f31");
05244       else
05245   output_operand_lossage ("invalid %%R value");
05246       break;
05247 
05248     case 'N':
05249       /* Write the 1's complement of a constant.  */
05250       if (GET_CODE (x) != CONST_INT)
05251   output_operand_lossage ("invalid %%N value");
05252 
05253       fprintf (file, HOST_WIDE_INT_PRINT_DEC, ~ INTVAL (x));
05254       break;
05255 
05256     case 'P':
05257       /* Write 1 << C, for a constant C.  */
05258       if (GET_CODE (x) != CONST_INT)
05259   output_operand_lossage ("invalid %%P value");
05260 
05261       fprintf (file, HOST_WIDE_INT_PRINT_DEC, (HOST_WIDE_INT) 1 << INTVAL (x));
05262       break;
05263 
05264     case 'h':
05265       /* Write the high-order 16 bits of a constant, sign-extended.  */
05266       if (GET_CODE (x) != CONST_INT)
05267   output_operand_lossage ("invalid %%h value");
05268 
05269       fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x) >> 16);
05270       break;
05271 
05272     case 'L':
05273       /* Write the low-order 16 bits of a constant, sign-extended.  */
05274       if (GET_CODE (x) != CONST_INT)
05275   output_operand_lossage ("invalid %%L value");
05276 
05277       fprintf (file, HOST_WIDE_INT_PRINT_DEC,
05278          (INTVAL (x) & 0xffff) - 2 * (INTVAL (x) & 0x8000));
05279       break;
05280 
05281     case 'm':
05282       /* Write mask for ZAP insn.  */
05283       if (GET_CODE (x) == CONST_DOUBLE)
05284   {
05285     HOST_WIDE_INT mask = 0;
05286     HOST_WIDE_INT value;
05287 
05288     value = CONST_DOUBLE_LOW (x);
05289     for (i = 0; i < HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR;
05290          i++, value >>= 8)
05291       if (value & 0xff)
05292         mask |= (1 << i);
05293 
05294     value = CONST_DOUBLE_HIGH (x);
05295     for (i = 0; i < HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR;
05296          i++, value >>= 8)
05297       if (value & 0xff)
05298         mask |= (1 << (i + sizeof (int)));
05299 
05300     fprintf (file, HOST_WIDE_INT_PRINT_DEC, mask & 0xff);
05301   }
05302 
05303       else if (GET_CODE (x) == CONST_INT)
05304   {
05305     HOST_WIDE_INT mask = 0, value = INTVAL (x);
05306 
05307     for (i = 0; i < 8; i++, value >>= 8)
05308       if (value & 0xff)
05309         mask |= (1 << i);
05310 
05311     fprintf (file, HOST_WIDE_INT_PRINT_DEC, mask);
05312   }
05313       else
05314   output_operand_lossage ("invalid %%m value");
05315       break;
05316 
05317     case 'M':
05318       /* 'b', 'w', 'l', or 'q' as the value of the constant.  */
05319       if (GET_CODE (x) != CONST_INT
05320     || (INTVAL (x) != 8 && INTVAL (x) != 16
05321         && INTVAL (x) != 32 && INTVAL (x) != 64))
05322   output_operand_lossage ("invalid %%M value");
05323 
05324       fprintf (file, "%s",
05325          (INTVAL (x) == 8 ? "b"
05326     : INTVAL (x) == 16 ? "w"
05327     : INTVAL (x) == 32 ? "l"
05328     : "q"));
05329       break;
05330 
05331     case 'U':
05332       /* Similar, except do it from the mask.  */
05333       if (GET_CODE (x) == CONST_INT && INTVAL (x) == 0xff)
05334   fprintf (file, "b");
05335       else if (GET_CODE (x) == CONST_INT && INTVAL (x) == 0xffff)
05336   fprintf (file, "w");
05337       else if (GET_CODE (x) == CONST_INT && INTVAL (x) == 0xffffffff)
05338   fprintf (file, "l");
05339 #if HOST_BITS_PER_WIDE_INT == 32
05340       else if (GET_CODE (x) == CONST_DOUBLE
05341          && CONST_DOUBLE_HIGH (x) == 0
05342          && CONST_DOUBLE_LOW (x) == -1)
05343   fprintf (file, "l");
05344       else if (GET_CODE (x) == CONST_DOUBLE
05345          && CONST_DOUBLE_HIGH (x) == -1
05346          && CONST_DOUBLE_LOW (x) == -1)
05347   fprintf (file, "q");
05348 #else
05349       else if (GET_CODE (x) == CONST_INT && INTVAL (x) == -1)
05350   fprintf (file, "q");
05351       else if (GET_CODE (x) == CONST_DOUBLE
05352          && CONST_DOUBLE_HIGH (x) == 0
05353          && CONST_DOUBLE_LOW (x) == -1)
05354   fprintf (file, "q");
05355 #endif
05356       else
05357   output_operand_lossage ("invalid %%U value");
05358       break;
05359 
05360     case 's':
05361       /* Write the constant value divided by 8 for little-endian mode or
05362    (56 - value) / 8 for big-endian mode.  */
05363 
05364       if (GET_CODE (x) != CONST_INT
05365     || (unsigned HOST_WIDE_INT) INTVAL (x) >= (WORDS_BIG_ENDIAN
05366                  ? 56
05367                  : 64)  
05368     || (INTVAL (x) & 7) != 0)
05369   output_operand_lossage ("invalid %%s value");
05370 
05371       fprintf (file, HOST_WIDE_INT_PRINT_DEC,
05372          WORDS_BIG_ENDIAN
05373          ? (56 - INTVAL (x)) / 8
05374          : INTVAL (x) / 8);
05375       break;
05376 
05377     case 'S':
05378       /* Same, except compute (64 - c) / 8 */
05379 
05380       if (GET_CODE (x) != CONST_INT
05381     && (unsigned HOST_WIDE_INT) INTVAL (x) >= 64
05382     && (INTVAL (x) & 7) != 8)
05383   output_operand_lossage ("invalid %%s value");
05384 
05385       fprintf (file, HOST_WIDE_INT_PRINT_DEC, (64 - INTVAL (x)) / 8);
05386       break;
05387 
05388     case 't':
05389       {
05390         /* On Unicos/Mk systems: use a DEX expression if the symbol
05391      clashes with a register name.  */
05392   int dex = unicosmk_need_dex (x);
05393   if (dex)
05394     fprintf (file, "DEX(%d)", dex);
05395   else
05396     output_addr_const (file, x);
05397       }
05398       break;
05399 
05400     case 'C': case 'D': case 'c': case 'd':
05401       /* Write out comparison name.  */
05402       {
05403   enum rtx_code c = GET_CODE (x);
05404 
05405         if (GET_RTX_CLASS (c) != '<')
05406     output_operand_lossage ("invalid %%C value");
05407 
05408   else if (code == 'D')
05409     c = reverse_condition (c);
05410   else if (code == 'c')
05411     c = swap_condition (c);
05412   else if (code == 'd')
05413     c = swap_condition (reverse_condition (c));
05414 
05415         if (c == LEU)
05416     fprintf (file, "ule");
05417         else if (c == LTU)
05418     fprintf (file, "ult");
05419   else if (c == UNORDERED)
05420     fprintf (file, "un");
05421         else
05422     fprintf (file, "%s", GET_RTX_NAME (c));
05423       }
05424       break;
05425 
05426     case 'E':
05427       /* Write the divide or modulus operator.  */
05428       switch (GET_CODE (x))
05429   {
05430   case DIV:
05431     fprintf (file, "div%s", GET_MODE (x) == SImode ? "l" : "q");
05432     break;
05433   case UDIV:
05434     fprintf (file, "div%su", GET_MODE (x) == SImode ? "l" : "q");
05435     break;
05436   case MOD:
05437     fprintf (file, "rem%s", GET_MODE (x) == SImode ? "l" : "q");
05438     break;
05439   case UMOD:
05440     fprintf (file, "rem%su", GET_MODE (x) == SImode ? "l" : "q");
05441     break;
05442   default:
05443     output_operand_lossage ("invalid %%E value");
05444     break;
05445   }
05446       break;
05447 
05448     case 'A':
05449       /* Write "_u" for unaligned access.  */
05450       if (GET_CODE (x) == MEM && GET_CODE (XEXP (x, 0)) == AND)
05451   fprintf (file, "_u");
05452       break;
05453 
05454     case 0:
05455       if (GET_CODE (x) == REG)
05456   fprintf (file, "%s", reg_names[REGNO (x)]);
05457       else if (GET_CODE (x) == MEM)
05458   output_address (XEXP (x, 0));
05459       else
05460   output_addr_const (file, x);
05461       break;
05462 
05463     default:
05464       output_operand_lossage ("invalid %%xn code");
05465     }
05466 }
05467 
05468 void
05469 print_operand_address (file, addr)
05470     FILE *file;
05471      rtx addr;
05472 {
05473   int basereg = 31;
05474   HOST_WIDE_INT offset = 0;
05475 
05476   if (GET_CODE (addr) == AND)
05477     addr = XEXP (addr, 0);
05478 
05479   if (GET_CODE (addr) == PLUS
05480       && GET_CODE (XEXP (addr, 1)) == CONST_INT)
05481     {
05482       offset = INTVAL (XEXP (addr, 1));
05483       addr = XEXP (addr, 0);
05484     }
05485 
05486   if (GET_CODE (addr) == LO_SUM)
05487     {
05488       output_addr_const (file, XEXP (addr, 1));
05489       if (offset)
05490   {
05491     fputc ('+', file);
05492     fprintf (file, HOST_WIDE_INT_PRINT_DEC, offset);
05493   }
05494       
05495       addr = XEXP (addr, 0);
05496       if (GET_CODE (addr) == REG)
05497   basereg = REGNO (addr);
05498       else if (GET_CODE (addr) == SUBREG
05499          && GET_CODE (SUBREG_REG (addr)) == REG)
05500   basereg = subreg_regno (addr);
05501       else
05502   abort ();
05503 
05504       fprintf (file, "($%d)\t\t!%s", basereg,
05505          (basereg == 29 ? "gprel" : "gprellow"));
05506       return;
05507     }
05508 
05509   if (GET_CODE (addr) == REG)
05510     basereg = REGNO (addr);
05511   else if (GET_CODE (addr) == SUBREG
05512      && GET_CODE (SUBREG_REG (addr)) == REG)
05513     basereg = subreg_regno (addr);
05514   else if (GET_CODE (addr) == CONST_INT)
05515     offset = INTVAL (addr);
05516   else
05517     abort ();
05518 
05519   fprintf (file, HOST_WIDE_INT_PRINT_DEC, offset);
05520   fprintf (file, "($%d)", basereg);
05521 }
05522 
05523 /* Emit RTL insns to initialize the variable parts of a trampoline at
05524    TRAMP. FNADDR is an RTX for the address of the function's pure
05525    code.  CXT is an RTX for the static chain value for the function.
05526 
05527    The three offset parameters are for the individual template's
05528    layout.  A JMPOFS < 0 indicates that the trampoline does not 
05529    contain instructions at all.
05530 
05531    We assume here that a function will be called many more times than
05532    its address is taken (e.g., it might be passed to qsort), so we
05533    take the trouble to initialize the "hint" field in the JMP insn.
05534    Note that the hint field is PC (new) + 4 * bits 13:0.  */
05535 
05536 void
05537 alpha_initialize_trampoline (tramp, fnaddr, cxt, fnofs, cxtofs, jmpofs)
05538      rtx tramp, fnaddr, cxt;
05539      int fnofs, cxtofs, jmpofs;
05540 {
05541   rtx temp, temp1, addr;
05542   /* VMS really uses DImode pointers in memory at this point.  */
05543   enum machine_mode mode = TARGET_ABI_OPEN_VMS ? Pmode : ptr_mode;
05544 
05545 #ifdef POINTERS_EXTEND_UNSIGNED
05546   fnaddr = convert_memory_address (mode, fnaddr);
05547   cxt = convert_memory_address (mode, cxt);
05548 #endif
05549 
05550   /* Store function address and CXT.  */
05551   addr = memory_address (mode, plus_constant (tramp, fnofs));
05552   emit_move_insn (gen_rtx_MEM (mode, addr), fnaddr);
05553   addr = memory_address (mode, plus_constant (tramp, cxtofs));
05554   emit_move_insn (gen_rtx_MEM (mode, addr), cxt);
05555 
05556   /* This has been disabled since the hint only has a 32k range, and in
05557      no existing OS is the stack within 32k of the text segment.  */
05558   if (0 && jmpofs >= 0)
05559     {
05560       /* Compute hint value.  */
05561       temp = force_operand (plus_constant (tramp, jmpofs+4), NULL_RTX);
05562       temp = expand_binop (DImode, sub_optab, fnaddr, temp, temp, 1,
05563          OPTAB_WIDEN);
05564       temp = expand_shift (RSHIFT_EXPR, Pmode, temp,
05565                build_int_2 (2, 0), NULL_RTX, 1);
05566       temp = expand_and (SImode, gen_lowpart (SImode, temp),
05567        GEN_INT (0x3fff), 0);
05568 
05569       /* Merge in the hint.  */
05570       addr = memory_address (SImode, plus_constant (tramp, jmpofs));
05571       temp1 = force_reg (SImode, gen_rtx_MEM (SImode, addr));
05572       temp1 = expand_and (SImode, temp1, GEN_INT (0xffffc000), NULL_RTX);
05573       temp1 = expand_binop (SImode, ior_optab, temp1, temp, temp1, 1,
05574           OPTAB_WIDEN);
05575       emit_move_insn (gen_rtx_MEM (SImode, addr), temp1);
05576     }
05577 
05578 #ifdef TRANSFER_FROM_TRAMPOLINE
05579   emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__enable_execute_stack"),
05580          0, VOIDmode, 1, addr, Pmode);
05581 #endif
05582 
05583   if (jmpofs >= 0)
05584     emit_insn (gen_imb ());
05585 }
05586 
05587 /* Determine where to put an argument to a function.
05588    Value is zero to push the argument on the stack,
05589    or a hard register in which to store the argument.
05590 
05591    MODE is the argument's machine mode.
05592    TYPE is the data type of the argument (as a tree).
05593     This is null for libcalls where that information may
05594     not be available.
05595    CUM is a variable of type CUMULATIVE_ARGS which gives info about
05596     the preceding args and about the function being called.
05597    NAMED is nonzero if this argument is a named parameter
05598     (otherwise it is an extra parameter matching an ellipsis).
05599 
05600    On Alpha the first 6 words of args are normally in registers
05601    and the rest are pushed.  */
05602 
05603 rtx
05604 function_arg (cum, mode, type, named)
05605      CUMULATIVE_ARGS cum;
05606      enum machine_mode mode;
05607      tree type;
05608      int named ATTRIBUTE_UNUSED;
05609 {
05610   int basereg;
05611   int num_args;
05612 
05613   /* Set up defaults for FP operands passed in FP registers, and
05614      integral operands passed in integer registers.  */
05615   if (TARGET_FPREGS
05616       && (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT
05617     || GET_MODE_CLASS (mode) == MODE_FLOAT))
05618     basereg = 32 + 16;
05619   else
05620     basereg = 16;
05621 
05622   /* ??? Irritatingly, the definition of CUMULATIVE_ARGS is different for
05623      the three platforms, so we can't avoid conditional compilation.  */
05624 #if TARGET_ABI_OPEN_VMS
05625     {
05626       if (mode == VOIDmode)
05627   return alpha_arg_info_reg_val (cum);
05628 
05629       num_args = cum.num_args;
05630       if (num_args >= 6 || MUST_PASS_IN_STACK (mode, type))
05631   return NULL_RTX;
05632     }
05633 #else
05634 #if TARGET_ABI_UNICOSMK
05635     {
05636       int size;
05637 
05638       /* If this is the last argument, generate the call info word (CIW).  */
05639       /* ??? We don't include the caller's line number in the CIW because
05640    I don't know how to determine it if debug infos are turned off.  */
05641       if (mode == VOIDmode)
05642   {
05643     int i;
05644     HOST_WIDE_INT lo;
05645     HOST_WIDE_INT hi;
05646     rtx ciw;
05647 
05648     lo = 0;
05649 
05650     for (i = 0; i < cum.num_reg_words && i < 5; i++)
05651       if (cum.reg_args_type[i])
05652         lo |= (1 << (7 - i));
05653 
05654     if (cum.num_reg_words == 6 && cum.reg_args_type[5])
05655       lo |= 7;
05656     else
05657       lo |= cum.num_reg_words;
05658 
05659 #if HOST_BITS_PER_WIDE_INT == 32
05660     hi = (cum.num_args << 20) | cum.num_arg_words;
05661 #else
05662     lo = lo | ((HOST_WIDE_INT) cum.num_args << 52)
05663       | ((HOST_WIDE_INT) cum.num_arg_words << 32);
05664     hi = 0;
05665 #endif
05666     ciw = immed_double_const (lo, hi, DImode);
05667 
05668     return gen_rtx_UNSPEC (DImode, gen_rtvec (1, ciw),
05669          UNSPEC_UMK_LOAD_CIW);
05670   }
05671 
05672       size = ALPHA_ARG_SIZE (mode, type, named);
05673       num_args = cum.num_reg_words;
05674       if (MUST_PASS_IN_STACK (mode, type)
05675     || cum.num_reg_words + size > 6 || cum.force_stack)
05676   return NULL_RTX;
05677       else if (type && TYPE_MODE (type) == BLKmode)
05678   {
05679     rtx reg1, reg2;
05680 
05681     reg1 = gen_rtx_REG (DImode, num_args + 16);
05682     reg1 = gen_rtx_EXPR_LIST (DImode, reg1, const0_rtx);
05683 
05684     /* The argument fits in two registers. Note that we still need to
05685        reserve a register for empty structures.  */
05686     if (size == 0)
05687       return NULL_RTX;
05688     else if (size == 1)
05689       return gen_rtx_PARALLEL (mode, gen_rtvec (1, reg1));
05690     else
05691       {
05692         reg2 = gen_rtx_REG (DImode, num_args + 17);
05693         reg2 = gen_rtx_EXPR_LIST (DImode, reg2, GEN_INT (8));
05694         return gen_rtx_PARALLEL (mode, gen_rtvec (2, reg1, reg2));
05695       }
05696   }
05697     }
05698 #else
05699     {
05700       if (cum >= 6)
05701   return NULL_RTX;
05702       num_args = cum;
05703 
05704       /* VOID is passed as a special flag for "last argument".  */
05705       if (type == void_type_node)
05706   basereg = 16;
05707       else if (MUST_PASS_IN_STACK (mode, type))
05708   return NULL_RTX;
05709       else if (FUNCTION_ARG_PASS_BY_REFERENCE (cum, mode, type, named))
05710   basereg = 16;
05711     }
05712 #endif /* TARGET_ABI_UNICOSMK */
05713 #endif /* TARGET_ABI_OPEN_VMS */
05714 
05715   return gen_rtx_REG (mode, num_args + basereg);
05716 }
05717 
05718 tree
05719 alpha_build_va_list ()
05720 {
05721   tree base, ofs, record, type_decl;
05722 
05723   if (TARGET_ABI_OPEN_VMS || TARGET_ABI_UNICOSMK)
05724     return ptr_type_node;
05725 
05726   record = make_lang_type (RECORD_TYPE);
05727   type_decl = build_decl (TYPE_DECL, get_identifier ("__va_list_tag"), record);
05728   TREE_CHAIN (record) = type_decl;
05729   TYPE_NAME (record) = type_decl;
05730 
05731   /* C++? SET_IS_AGGR_TYPE (record, 1); */
05732 
05733   ofs = build_decl (FIELD_DECL, get_identifier ("__offset"),
05734         integer_type_node);
05735   DECL_FIELD_CONTEXT (ofs) = record;
05736 
05737   base = build_decl (FIELD_DECL, get_identifier ("__base"),
05738          ptr_type_node);
05739   DECL_FIELD_CONTEXT (base) = record;
05740   TREE_CHAIN (base) = ofs;
05741 
05742   TYPE_FIELDS (record) = base;
05743   layout_type (record);
05744 
05745   return record;
05746 }
05747 
05748 void
05749 alpha_va_start (stdarg_p, valist, nextarg)
05750      int stdarg_p;
05751      tree valist;
05752      rtx nextarg ATTRIBUTE_UNUSED;
05753 {
05754   HOST_WIDE_INT offset;
05755   tree t, offset_field, base_field;
05756 
05757   if (TREE_CODE (TREE_TYPE (valist)) == ERROR_MARK)
05758     return;
05759 
05760   if (TARGET_ABI_UNICOSMK)
05761     std_expand_builtin_va_start (stdarg_p, valist, nextarg);
05762 
05763   /* For Unix, SETUP_INCOMING_VARARGS moves the starting address base
05764      up by 48, storing fp arg registers in the first 48 bytes, and the
05765      integer arg registers in the next 48 bytes.  This is only done,
05766      however, if any integer registers need to be stored.
05767 
05768      If no integer registers need be stored, then we must subtract 48
05769      in order to account for the integer arg registers which are counted
05770      in argsize above, but which are not actually stored on the stack.  */
05771 
05772   if (NUM_ARGS <= 5 + stdarg_p)
05773     offset = TARGET_ABI_OPEN_VMS ? UNITS_PER_WORD : 6 * UNITS_PER_WORD;
05774   else
05775     offset = -6 * UNITS_PER_WORD;
05776 
05777   if (TARGET_ABI_OPEN_VMS)
05778     {
05779       nextarg = plus_constant (nextarg, offset);
05780       nextarg = plus_constant (nextarg, NUM_ARGS * UNITS_PER_WORD);
05781       t = build (MODIFY_EXPR, TREE_TYPE (valist), valist,
05782      make_tree (ptr_type_node, nextarg));
05783       TREE_SIDE_EFFECTS (t) = 1;
05784 
05785       expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
05786     }
05787   else
05788     {
05789       base_field = TYPE_FIELDS (TREE_TYPE (valist));
05790       offset_field = TREE_CHAIN (base_field);
05791 
05792       base_field = build (COMPONENT_REF, TREE_TYPE (base_field),
05793         valist, base_field);
05794       offset_field = build (COMPONENT_REF, TREE_TYPE (offset_field),
05795           valist, offset_field);
05796 
05797       t = make_tree (ptr_type_node, virtual_incoming_args_rtx);
05798       t = build (PLUS_EXPR, ptr_type_node, t, build_int_2 (offset, 0));
05799       t = build (MODIFY_EXPR, TREE_TYPE (base_field), base_field, t);
05800       TREE_SIDE_EFFECTS (t) = 1;
05801       expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
05802 
05803       t = build_int_2 (NUM_ARGS * UNITS_PER_WORD, 0);
05804       t = build (MODIFY_EXPR, TREE_TYPE (offset_field), offset_field, t);
05805       TREE_SIDE_EFFECTS (t) = 1;
05806       expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
05807     }
05808 }
05809 
05810 rtx
05811 alpha_va_arg (valist, type)
05812      tree valist, type;
05813 {
05814   rtx addr;
05815   tree t, type_size, rounded_size;
05816   tree offset_field, base_field, addr_tree, addend;
05817   tree wide_type, wide_ofs;
05818   int indirect = 0;
05819 
05820   if (TARGET_ABI_OPEN_VMS || TARGET_ABI_UNICOSMK)
05821     return std_expand_builtin_va_arg (valist, type);
05822 
05823   if (type == error_mark_node
05824       || (type_size = TYPE_SIZE_UNIT (TYPE_MAIN_VARIANT (type))) == NULL
05825       || TREE_OVERFLOW (type_size))
05826     rounded_size = size_zero_node;
05827   else
05828     rounded_size = fold (build (MULT_EXPR, sizetype,
05829         fold (build (TRUNC_DIV_EXPR, sizetype,
05830                fold (build (PLUS_EXPR, sizetype,
05831                 type_size,
05832                 size_int (7))),
05833                size_int (8))),
05834         size_int (8)));
05835 
05836   base_field = TYPE_FIELDS (TREE_TYPE (valist));
05837   offset_field = TREE_CHAIN (base_field);
05838 
05839   base_field = build (COMPONENT_REF, TREE_TYPE (base_field),
05840           valist, base_field);
05841   offset_field = build (COMPONENT_REF, TREE_TYPE (offset_field),
05842       valist, offset_field);
05843 
05844   /* If the type could not be passed in registers, skip the block
05845      reserved for the registers.  */
05846   if (MUST_PASS_IN_STACK (TYPE_MODE (type), type))
05847     {
05848       t = build (MODIFY_EXPR, TREE_TYPE (offset_field), offset_field,
05849      build (MAX_EXPR, TREE_TYPE (offset_field), 
05850       offset_field, build_int_2 (6*8, 0)));
05851       TREE_SIDE_EFFECTS (t) = 1;
05852       expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
05853     }
05854 
05855   wide_type = make_signed_type (64);
05856   wide_ofs = save_expr (build1 (CONVERT_EXPR, wide_type, offset_field));
05857 
05858   addend = wide_ofs;
05859 
05860   if (TYPE_MODE (type) == TFmode || TYPE_MODE (type) == TCmode)
05861     {
05862       indirect = 1;
05863       rounded_size = size_int (UNITS_PER_WORD);
05864     }
05865   else if (FLOAT_TYPE_P (type))
05866     {
05867       tree fpaddend, cond;
05868 
05869       fpaddend = fold (build (PLUS_EXPR, TREE_TYPE (addend),
05870             addend, build_int_2 (-6*8, 0)));
05871 
05872       cond = fold (build (LT_EXPR, integer_type_node,
05873         wide_ofs, build_int_2 (6*8, 0)));
05874 
05875       addend = fold (build (COND_EXPR, TREE_TYPE (addend), cond,
05876           fpaddend, addend));
05877     }
05878 
05879   addr_tree = build (PLUS_EXPR, TREE_TYPE (base_field),
05880          base_field, addend);
05881 
05882   addr = expand_expr (addr_tree, NULL_RTX, Pmode, EXPAND_NORMAL);
05883   addr = copy_to_reg (addr);
05884 
05885   t = build (MODIFY_EXPR, TREE_TYPE (offset_field), offset_field,
05886        build (PLUS_EXPR, TREE_TYPE (offset_field), 
05887         offset_field, rounded_size));
05888   TREE_SIDE_EFFECTS (t) = 1;
05889   expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
05890 
05891   if (indirect)
05892     {
05893       addr = force_reg (Pmode, addr);
05894       addr = gen_rtx_MEM (Pmode, addr);
05895     }
05896 
05897   return addr;
05898 }
05899 
05900 /* This page contains routines that are used to determine what the function
05901    prologue and epilogue code will do and write them out.  */
05902 
05903 /* Compute the size of the save area in the stack.  */
05904 
05905 /* These variables are used for communication between the following functions.
05906    They indicate various things about the current function being compiled
05907    that are used to tell what kind of prologue, epilogue and procedure
05908    descriptior to generate.  */
05909 
05910 /* Nonzero if we need a stack procedure.  */
05911 enum alpha_procedure_types {PT_NULL = 0, PT_REGISTER = 1, PT_STACK = 2};
05912 static enum alpha_procedure_types alpha_procedure_type;
05913 
05914 /* Register number (either FP or SP) that is used to unwind the frame.  */
05915 static int vms_unwind_regno;
05916 
05917 /* Register number used to save FP.  We need not have one for RA since
05918    we don't modify it for register procedures.  This is only defined
05919    for register frame procedures.  */
05920 static int vms_save_fp_regno;
05921 
05922 /* Register number used to reference objects off our PV.  */
05923 static int vms_base_regno;
05924 
05925 /* Compute register masks for saved registers.  */
05926 
05927 static void
05928 alpha_sa_mask (imaskP, fmaskP)
05929     unsigned long *imaskP;
05930     unsigned long *fmaskP;
05931 {
05932   unsigned long imask = 0;
05933   unsigned long fmask = 0;
05934   unsigned int i;
05935 
05936   /* Irritatingly, there are two kinds of thunks -- those created with
05937      ASM_OUTPUT_MI_THUNK and those with DECL_THUNK_P that go through
05938      the regular part of the compiler.  In the ASM_OUTPUT_MI_THUNK case
05939      we don't have valid register life info, but assemble_start_function
05940      wants to output .frame and .mask directives.  */
05941   if (current_function_is_thunk && !no_new_pseudos)
05942     {
05943       *imaskP = 0;
05944       *fmaskP = 0;
05945       return;
05946     }
05947 
05948   if (TARGET_ABI_OPEN_VMS && alpha_procedure_type == PT_STACK)
05949     imask |= (1L << HARD_FRAME_POINTER_REGNUM);
05950 
05951   /* One for every register we have to save.  */
05952   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
05953     if (! fixed_regs[i] && ! call_used_regs[i]
05954   && regs_ever_live[i] && i != REG_RA
05955   && (!TARGET_ABI_UNICOSMK || i != HARD_FRAME_POINTER_REGNUM))
05956       {
05957   if (i < 32)
05958     imask |= (1L << i);
05959   else
05960     fmask |= (1L << (i - 32));
05961       }
05962 
05963   /* We need to restore these for the handler.  */
05964   if (current_function_calls_eh_return)
05965     for (i = 0; ; ++i)
05966       {
05967   unsigned regno = EH_RETURN_DATA_REGNO (i);
05968   if (regno == INVALID_REGNUM)
05969     break;
05970   imask |= 1L << regno;
05971       }
05972      
05973   /* If any register spilled, then spill the return address also.  */
05974   /* ??? This is required by the Digital stack unwind specification
05975      and isn't needed if we're doing Dwarf2 unwinding.  */
05976   if (imask || fmask || alpha_ra_ever_killed ())
05977     imask |= (1L << REG_RA);
05978 
05979   *imaskP = imask;
05980   *fmaskP = fmask;
05981 }
05982 
05983 int
05984 alpha_sa_size ()
05985 {
05986   unsigned long mask[2];
05987   int sa_size = 0;
05988   int i, j;
05989 
05990   alpha_sa_mask (&mask[0], &mask[1]);
05991 
05992   if (TARGET_ABI_UNICOSMK)
05993     {
05994       if (mask[0] || mask[1])
05995   sa_size = 14;
05996     }
05997   else
05998     {
05999       for (j = 0; j < 2; ++j)
06000   for (i = 0; i < 32; ++i)
06001     if ((mask[j] >> i) & 1)
06002       sa_size++;
06003     }
06004 
06005   if (TARGET_ABI_UNICOSMK)
06006     {
06007       /* We might not need to generate a frame if we don't make any calls
06008    (including calls to __T3E_MISMATCH if this is a vararg function),
06009    don't have any local variables which require stack slots, don't
06010    use alloca and have not determined that we need a frame for other
06011    reasons.  */
06012 
06013       alpha_procedure_type
06014   = (sa_size || get_frame_size() != 0
06015      || current_function_outgoing_args_size || current_function_varargs
06016      || current_function_stdarg || current_function_calls_alloca
06017      || frame_pointer_needed)
06018     ? PT_STACK : PT_REGISTER;
06019 
06020       /* Always reserve space for saving callee-saved registers if we
06021    need a frame as required by the calling convention.  */
06022       if (alpha_procedure_type == PT_STACK)
06023         sa_size = 14;
06024     }
06025   else if (TARGET_ABI_OPEN_VMS)
06026     {
06027       /* Start by assuming we can use a register procedure if we don't
06028    make any calls (REG_RA not used) or need to save any
06029    registers and a stack procedure if we do.  */
06030       if ((mask[0] >> REG_RA) & 1)
06031   alpha_procedure_type = PT_STACK;
06032       else if (get_frame_size() != 0)
06033   alpha_procedure_type = PT_REGISTER;
06034       else
06035   alpha_procedure_type = PT_NULL;
06036 
06037       /* Don't reserve space for saving FP & RA yet.  Do that later after we've
06038    made the final decision on stack procedure vs register procedure.  */
06039       if (alpha_procedure_type == PT_STACK)
06040   sa_size -= 2;
06041 
06042       /* Decide whether to refer to objects off our PV via FP or PV.
06043    If we need FP for something else or if we receive a nonlocal
06044    goto (which expects PV to contain the value), we must use PV.
06045    Otherwise, start by assuming we can use FP.  */
06046 
06047       vms_base_regno
06048   = (frame_pointer_needed
06049      || current_function_has_nonlocal_label
06050      || alpha_procedure_type == PT_STACK
06051      || current_function_outgoing_args_size)
06052     ? REG_PV : HARD_FRAME_POINTER_REGNUM;
06053 
06054       /* If we want to copy PV into FP, we need to find some register
06055    in which to save FP.  */
06056 
06057       vms_save_fp_regno = -1;
06058       if (vms_base_regno == HARD_FRAME_POINTER_REGNUM)
06059   for (i = 0; i < 32; i++)
06060     if (! fixed_regs[i] && call_used_regs[i] && ! regs_ever_live[i])
06061       vms_save_fp_regno = i;
06062 
06063       if (vms_save_fp_regno == -1 && alpha_procedure_type == PT_REGISTER)
06064   vms_base_regno = REG_PV, alpha_procedure_type = PT_STACK;
06065       else if (alpha_procedure_type == PT_NULL)
06066   vms_base_regno = REG_PV;
06067 
06068       /* Stack unwinding should be done via FP unless we use it for PV.  */
06069       vms_unwind_regno = (vms_base_regno == REG_PV
06070         ? HARD_FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM);
06071 
06072       /* If this is a stack procedure, allow space for saving FP and RA.  */
06073       if (alpha_procedure_type == PT_STACK)
06074   sa_size += 2;
06075     }
06076   else
06077     {
06078       /* Our size must be even (multiple of 16 bytes).  */
06079       if (sa_size & 1)
06080   sa_size++;
06081     }
06082 
06083   return sa_size * 8;
06084 }
06085 
06086 int
06087 alpha_pv_save_size ()
06088 {
06089   alpha_sa_size ();
06090   return alpha_procedure_type == PT_STACK ? 8 : 0;
06091 }
06092 
06093 int
06094 alpha_using_fp ()
06095 {
06096   alpha_sa_size ();
06097   return vms_unwind_regno == HARD_FRAME_POINTER_REGNUM;
06098 }
06099 
06100 #if TARGET_ABI_OPEN_VMS
06101 
06102 const struct attribute_spec vms_attribute_table[] =
06103 {
06104   /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
06105   { "overlaid",   0, 0, true,  false, false, NULL },
06106   { "global",     0, 0, true,  false, false, NULL },
06107   { "initialize", 0, 0, true,  false, false, NULL },
06108   { NULL,         0, 0, false, false, false, NULL }
06109 };
06110 
06111 #endif
06112 
06113 static int
06114 find_lo_sum (px, data)
06115      rtx *px;
06116      void *data ATTRIBUTE_UNUSED;
06117 {
06118   return GET_CODE (*px) == LO_SUM;
06119 }
06120 
06121 static int
06122 alpha_does_function_need_gp ()
06123 {
06124   rtx insn;
06125 
06126   /* The GP being variable is an OSF abi thing.  */
06127   if (! TARGET_ABI_OSF)
06128     return 0;
06129 
06130   if (TARGET_PROFILING_NEEDS_GP && current_function_profile)
06131     return 1;
06132 
06133   if (current_function_is_thunk)
06134     return 1;
06135 
06136   /* If we need a GP (we have a LDSYM insn or a CALL_INSN), load it first. 
06137      Even if we are a static function, we still need to do this in case
06138      our address is taken and passed to something like qsort.  */
06139 
06140   push_topmost_sequence ();
06141   insn = get_insns ();
06142   pop_topmost_sequence ();
06143 
06144   for (; insn; insn = NEXT_INSN (insn))
06145     if (INSN_P (insn)
06146   && GET_CODE (PATTERN (insn)) != USE
06147   && GET_CODE (PATTERN (insn)) != CLOBBER)
06148       {
06149   enum attr_type type = get_attr_type (insn);
06150   if (type == TYPE_LDSYM || type == TYPE_JSR)
06151     return 1;
06152   if (TARGET_EXPLICIT_RELOCS
06153       && for_each_rtx (&PATTERN (insn), find_lo_sum, NULL) > 0)
06154     return 1;
06155       }
06156 
06157   return 0;
06158 }
06159 
06160 /* Write a version stamp.  Don't write anything if we are running as a
06161    cross-compiler.  Otherwise, use the versions in /usr/include/stamp.h.  */
06162 
06163 #ifdef HAVE_STAMP_H
06164 #include <stamp.h>
06165 #endif
06166 
06167 void
06168 alpha_write_verstamp (file)
06169      FILE *file ATTRIBUTE_UNUSED;
06170 {
06171 #ifdef MS_STAMP
06172   fprintf (file, "\t.verstamp %d %d\n", MS_STAMP, LS_STAMP);
06173 #endif
06174 }
06175 
06176 /* Helper function to set RTX_FRAME_RELATED_P on instructions, including
06177    sequences.  */
06178 
06179 static rtx
06180 set_frame_related_p ()
06181 {
06182   rtx seq = gen_sequence ();
06183   end_sequence ();
06184 
06185   if (GET_CODE (seq) == SEQUENCE)
06186     {
06187       int i = XVECLEN (seq, 0);
06188       while (--i >= 0)
06189   RTX_FRAME_RELATED_P (XVECEXP (seq, 0, i)) = 1;
06190      return emit_insn (seq);
06191     }
06192   else
06193     {
06194       seq = emit_insn (seq);
06195       RTX_FRAME_RELATED_P (seq) = 1;
06196       return seq;
06197     }
06198 }
06199 
06200 #define FRP(exp)  (start_sequence (), exp, set_frame_related_p ())
06201 
06202 /* Write function prologue.  */
06203 
06204 /* On vms we have two kinds of functions:
06205 
06206    - stack frame (PROC_STACK)
06207   these are 'normal' functions with local vars and which are
06208   calling other functions
06209    - register frame (PROC_REGISTER)
06210   keeps all data in registers, needs no stack
06211 
06212    We must pass this to the assembler so it can generate the
06213    proper pdsc (procedure descriptor)
06214    This is done with the '.pdesc' command.
06215 
06216    On not-vms, we don't really differentiate between the two, as we can
06217    simply allocate stack without saving registers.  */
06218 
06219 void
06220 alpha_expand_prologue ()
06221 {
06222   /* Registers to save.  */
06223   unsigned long imask = 0;
06224   unsigned long fmask = 0;
06225   /* Stack space needed for pushing registers clobbered by us.  */
06226   HOST_WIDE_INT sa_size;
06227   /* Complete stack size needed.  */
06228   HOST_WIDE_INT frame_size;
06229   /* Offset from base reg to register save area.  */
06230   HOST_WIDE_INT reg_offset;
06231   rtx sa_reg, mem;
06232   int i;
06233 
06234   sa_size = alpha_sa_size ();
06235 
06236   frame_size = get_frame_size ();
06237   if (TARGET_ABI_OPEN_VMS)
06238     frame_size = ALPHA_ROUND (sa_size 
06239             + (alpha_procedure_type == PT_STACK ? 8 : 0)
06240             + frame_size
06241             + current_function_pretend_args_size);
06242   else if (TARGET_ABI_UNICOSMK)
06243     /* We have to allocate space for the DSIB if we generate a frame.  */
06244     frame_size = ALPHA_ROUND (sa_size
06245             + (alpha_procedure_type == PT_STACK ? 48 : 0))
06246      + ALPHA_ROUND (frame_size
06247         + current_function_outgoing_args_size);
06248   else
06249     frame_size = (ALPHA_ROUND (current_function_outgoing_args_size)
06250       + sa_size
06251       + ALPHA_ROUND (frame_size
06252          + current_function_pretend_args_size));
06253 
06254   if (TARGET_ABI_OPEN_VMS)
06255     reg_offset = 8;
06256   else
06257     reg_offset = ALPHA_ROUND (current_function_outgoing_args_size);
06258 
06259   alpha_sa_mask (&imask, &fmask);
06260 
06261   /* Emit an insn to reload GP, if needed.  */
06262   if (TARGET_ABI_OSF)
06263     {
06264       alpha_function_needs_gp = alpha_does_function_need_gp ();
06265       if (alpha_function_needs_gp)
06266   emit_insn (gen_prologue_ldgp ());
06267     }
06268 
06269   /* TARGET_PROFILING_NEEDS_GP actually implies that we need to insert
06270      the call to mcount ourselves, rather than having the linker do it
06271      magically in response to -pg.  Since _mcount has special linkage,
06272      don't represent the call as a call.  */
06273   if (TARGET_PROFILING_NEEDS_GP && current_function_profile)
06274     emit_insn (gen_prologue_mcount ());
06275 
06276   if (TARGET_ABI_UNICOSMK)
06277     unicosmk_gen_dsib (&imask);
06278 
06279   /* Adjust the stack by the frame size.  If the frame size is > 4096
06280      bytes, we need to be sure we probe somewhere in the first and last
06281      4096 bytes (we can probably get away without the latter test) and
06282      every 8192 bytes in between.  If the frame size is > 32768, we
06283      do this in a loop.  Otherwise, we generate the explicit probe
06284      instructions. 
06285 
06286      Note that we are only allowed to adjust sp once in the prologue.  */
06287 
06288   if (frame_size <= 32768)
06289     {
06290       if (frame_size > 4096)
06291   {
06292     int probed = 4096;
06293 
06294     do
06295       emit_insn (gen_probe_stack (GEN_INT (TARGET_ABI_UNICOSMK
06296              ? -probed + 64
06297              : -probed)));
06298     while ((probed += 8192) < frame_size);
06299 
06300     /* We only have to do this probe if we aren't saving registers.  */
06301     if (sa_size == 0 && probed + 4096 < frame_size)
06302       emit_insn (gen_probe_stack (GEN_INT (-frame_size)));
06303   }
06304 
06305       if (frame_size != 0)
06306   FRP (emit_insn (gen_adddi3 (stack_pointer_rtx, stack_pointer_rtx,
06307             GEN_INT (TARGET_ABI_UNICOSMK
06308                ? -frame_size + 64
06309                : -frame_size))));
06310     }
06311   else
06312     {
06313       /* Here we generate code to set R22 to SP + 4096 and set R23 to the
06314    number of 8192 byte blocks to probe.  We then probe each block
06315    in the loop and then set SP to the proper location.  If the
06316    amount remaining is > 4096, we have to do one more probe if we
06317    are not saving any registers.  */
06318 
06319       HOST_WIDE_INT blocks = (frame_size + 4096) / 8192;
06320       HOST_WIDE_INT leftover = frame_size + 4096 - blocks * 8192;
06321       rtx ptr = gen_rtx_REG (DImode, 22);
06322       rtx count = gen_rtx_REG (DImode, 23);
06323       rtx seq;
06324 
06325       emit_move_insn (count, GEN_INT (blocks));
06326       emit_insn (gen_adddi3 (ptr, stack_pointer_rtx,
06327            GEN_INT (TARGET_ABI_UNICOSMK ? 4096 - 64 : 4096)));
06328 
06329       /* Because of the difficulty in emitting a new basic block this
06330    late in the compilation, generate the loop as a single insn.  */
06331       emit_insn (gen_prologue_stack_probe_loop (count, ptr));
06332 
06333       if (leftover > 4096 && sa_size == 0)
06334   {
06335     rtx last = gen_rtx_MEM (DImode, plus_constant (ptr, -leftover));
06336     MEM_VOLATILE_P (last) = 1;
06337     emit_move_insn (last, const0_rtx);
06338   }
06339 
06340       if (TARGET_ABI_WINDOWS_NT)
06341   {
06342     /* For NT stack unwind (done by 'reverse execution'), it's
06343        not OK to take the result of a loop, even though the value
06344        is already in ptr, so we reload it via a single operation
06345        and subtract it to sp. 
06346 
06347        Yes, that's correct -- we have to reload the whole constant
06348        into a temporary via ldah+lda then subtract from sp.  To
06349        ensure we get ldah+lda, we use a special pattern.  */
06350 
06351     HOST_WIDE_INT lo, hi;
06352     lo = ((frame_size & 0xffff) ^ 0x8000) - 0x8000;
06353     hi = frame_size - lo;
06354 
06355     emit_move_insn (ptr, GEN_INT (hi));
06356     emit_insn (gen_nt_lda (ptr, GEN_INT (lo)));
06357     seq = emit_insn (gen_subdi3 (stack_pointer_rtx, stack_pointer_rtx,
06358                ptr));
06359   }
06360       else
06361   {
06362     seq = emit_insn (gen_adddi3 (stack_pointer_rtx, ptr,
06363                GEN_INT (-leftover)));
06364   }
06365 
06366       /* This alternative is special, because the DWARF code cannot
06367          possibly intuit through the loop above.  So we invent this
06368          note it looks at instead.  */
06369       RTX_FRAME_RELATED_P (seq) = 1;
06370       REG_NOTES (seq)
06371         = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
06372            gen_rtx_SET (VOIDmode, stack_pointer_rtx,
06373              gen_rtx_PLUS (Pmode, stack_pointer_rtx,
06374                GEN_INT (TARGET_ABI_UNICOSMK
06375                   ? -frame_size + 64
06376                   : -frame_size))),
06377            REG_NOTES (seq));
06378     }
06379 
06380   if (!TARGET_ABI_UNICOSMK)
06381     {
06382       /* Cope with very large offsets to the register save area.  */
06383       sa_reg = stack_pointer_rtx;
06384       if (reg_offset + sa_size > 0x8000)
06385   {
06386     int low = ((reg_offset & 0xffff) ^ 0x8000) - 0x8000;
06387     HOST_WIDE_INT bias;
06388 
06389     if (low + sa_size <= 0x8000)
06390       bias = reg_offset - low, reg_offset = low;
06391     else 
06392       bias = reg_offset, reg_offset = 0;
06393 
06394     sa_reg = gen_rtx_REG (DImode, 24);
06395     FRP (emit_insn (gen_adddi3 (sa_reg, stack_pointer_rtx,
06396               GEN_INT (bias))));
06397   }
06398     
06399       /* Save regs in stack order.  Beginning with VMS PV.  */
06400       if (TARGET_ABI_OPEN_VMS && alpha_procedure_type == PT_STACK)
06401   {
06402     mem = gen_rtx_MEM (DImode, stack_pointer_rtx);
06403     set_mem_alias_set (mem, alpha_sr_alias_set);
06404     FRP (emit_move_insn (mem, gen_rtx_REG (DImode, REG_PV)));
06405   }
06406 
06407       /* Save register RA next.  */
06408       if (imask & (1L << REG_RA))
06409   {
06410     mem = gen_rtx_MEM (DImode, plus_constant (sa_reg, reg_offset));
06411     set_mem_alias_set (mem, alpha_sr_alias_set);
06412     FRP (emit_move_insn (mem, gen_rtx_REG (DImode, REG_RA)));
06413     imask &= ~(1L << REG_RA);
06414     reg_offset += 8;
06415   }
06416 
06417       /* Now save any other registers required to be saved.  */
06418       for (i = 0; i < 32; i++)
06419   if (imask & (1L << i))
06420     {
06421       mem = gen_rtx_MEM (DImode, plus_constant (sa_reg, reg_offset));
06422       set_mem_alias_set (mem, alpha_sr_alias_set);
06423       FRP (emit_move_insn (mem, gen_rtx_REG (DImode, i)));
06424       reg_offset += 8;
06425     }
06426 
06427       for (i = 0; i < 32; i++)
06428   if (fmask & (1L << i))
06429     {
06430       mem = gen_rtx_MEM (DFmode, plus_constant (sa_reg, reg_offset));
06431       set_mem_alias_set (mem, alpha_sr_alias_set);
06432       FRP (emit_move_insn (mem, gen_rtx_REG (DFmode, i+32)));
06433       reg_offset += 8;
06434     }
06435     }
06436   else if (TARGET_ABI_UNICOSMK && alpha_procedure_type == PT_STACK)
06437     {
06438       /* The standard frame on the T3E includes space for saving registers.
06439    We just have to use it. We don't have to save the return address and
06440    the old frame pointer here - they are saved in the DSIB.  */
06441 
06442       reg_offset = -56;
06443       for (i = 9; i < 15; i++)
06444   if (imask & (1L << i))
06445     {
06446       mem = gen_rtx_MEM (DImode, plus_constant(hard_frame_pointer_rtx,
06447                  reg_offset));
06448       set_mem_alias_set (mem, alpha_sr_alias_set);
06449       FRP (emit_move_insn (mem, gen_rtx_REG (DImode, i)));
06450       reg_offset -= 8;
06451     }
06452       for (i = 2; i < 10; i++)
06453   if (fmask & (1L << i))
06454     {
06455       mem = gen_rtx_MEM (DFmode, plus_constant (hard_frame_pointer_rtx,
06456                   reg_offset));
06457       set_mem_alias_set (mem, alpha_sr_alias_set);
06458       FRP (emit_move_insn (mem, gen_rtx_REG (DFmode, i+32)));
06459       reg_offset -= 8;
06460     }
06461     }
06462 
06463   if (TARGET_ABI_OPEN_VMS)
06464     {
06465       if (alpha_procedure_type == PT_REGISTER)
06466   /* Register frame procedures save the fp.
06467      ?? Ought to have a dwarf2 save for this.  */
06468   emit_move_insn (gen_rtx_REG (DImode, vms_save_fp_regno),
06469       hard_frame_pointer_rtx);
06470 
06471       if (alpha_procedure_type != PT_NULL && vms_base_regno != REG_PV)
06472   emit_insn (gen_force_movdi (gen_rtx_REG (DImode, vms_base_regno),
06473             gen_rtx_REG (DImode, REG_PV)));
06474 
06475       if (alpha_procedure_type != PT_NULL
06476     && vms_unwind_regno == HARD_FRAME_POINTER_REGNUM)
06477   FRP (emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx));
06478 
06479       /* If we have to allocate space for outgoing args, do it now.  */
06480       if (current_function_outgoing_args_size != 0)
06481   FRP (emit_move_insn
06482        (stack_pointer_rtx, 
06483         plus_constant (hard_frame_pointer_rtx,
06484            - (ALPHA_ROUND
06485         (current_function_outgoing_args_size)))));
06486     }
06487   else if (!TARGET_ABI_UNICOSMK)
06488     {
06489       /* If we need a frame pointer, set it from the stack pointer.  */
06490       if (frame_pointer_needed)
06491   {
06492     if (TARGET_CAN_FAULT_IN_PROLOGUE)
06493       FRP (emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx));
06494     else
06495       /* This must always be the last instruction in the
06496          prologue, thus we emit a special move + clobber.  */
06497         FRP (emit_insn (gen_init_fp (hard_frame_pointer_rtx,
06498                    stack_pointer_rtx, sa_reg)));
06499   }
06500     }
06501 
06502   /* The ABIs for VMS and OSF/1 say that while we can schedule insns into
06503      the prologue, for exception handling reasons, we cannot do this for
06504      any insn that might fault.  We could prevent this for mems with a
06505      (clobber:BLK (scratch)), but this doesn't work for fp insns.  So we
06506      have to prevent all such scheduling with a blockage.
06507 
06508      Linux, on the other hand, never bothered to implement OSF/1's 
06509      exception handling, and so doesn't care about such things.  Anyone
06510      planning to use dwarf2 frame-unwind info can also omit the blockage.  */
06511 
06512   if (! TARGET_CAN_FAULT_IN_PROLOGUE)
06513     emit_insn (gen_blockage ());
06514 }
06515 
06516 /* Output the textual info surrounding the prologue.  */
06517 
06518 void
06519 alpha_start_function (file, fnname, decl)
06520      FILE *file;
06521      const char *fnname;
06522      tree decl ATTRIBUTE_UNUSED;
06523 {
06524   unsigned long imask = 0;
06525   unsigned long fmask = 0;
06526   /* Stack space needed for pushing registers clobbered by us.  */
06527   HOST_WIDE_INT sa_size;
06528   /* Complete stack size needed.  */
06529   HOST_WIDE_INT frame_size;
06530   /* Offset from base reg to register save area.  */
06531   HOST_WIDE_INT reg_offset;
06532   char *entry_label = (char *) alloca (strlen (fnname) + 6);
06533   int i;
06534 
06535   /* Don't emit an extern directive for functions defined in the same file.  */
06536   if (TARGET_ABI_UNICOSMK)
06537     {
06538       tree name_tree;
06539       name_tree = get_identifier (fnname);
06540       TREE_ASM_WRITTEN (name_tree) = 1;
06541     }
06542 
06543   alpha_fnname = fnname;
06544   sa_size = alpha_sa_size ();
06545 
06546   frame_size = get_frame_size ();
06547   if (TARGET_ABI_OPEN_VMS)
06548     frame_size = ALPHA_ROUND (sa_size 
06549             + (alpha_procedure_type == PT_STACK ? 8 : 0)
06550             + frame_size
06551             + current_function_pretend_args_size);
06552   else if (TARGET_ABI_UNICOSMK)
06553     frame_size = ALPHA_ROUND (sa_size
06554             + (alpha_procedure_type == PT_STACK ? 48 : 0))
06555      + ALPHA_ROUND (frame_size
06556             + current_function_outgoing_args_size);
06557   else
06558     frame_size = (ALPHA_ROUND (current_function_outgoing_args_size)
06559       + sa_size
06560       + ALPHA_ROUND (frame_size
06561          + current_function_pretend_args_size));
06562 
06563   if (TARGET_ABI_OPEN_VMS)
06564     reg_offset = 8;
06565   else
06566     reg_offset = ALPHA_ROUND (current_function_outgoing_args_size);
06567 
06568   alpha_sa_mask (&imask, &fmask);
06569 
06570   /* Ecoff can handle multiple .file directives, so put out file and lineno.
06571      We have to do that before the .ent directive as we cannot switch
06572      files within procedures with native ecoff because line numbers are
06573      linked to procedure descriptors.
06574      Outputting the lineno helps debugging of one line functions as they
06575      would otherwise get no line number at all. Please note that we would
06576      like to put out last_linenum from final.c, but it is not accessible.  */
06577 
06578   if (write_symbols == SDB_DEBUG)
06579     {
06580 #ifdef ASM_OUTPUT_SOURCE_FILENAME
06581       ASM_OUTPUT_SOURCE_FILENAME (file,
06582           DECL_SOURCE_FILE (current_function_decl));
06583 #endif
06584 #ifdef ASM_OUTPUT_SOURCE_LINE
06585       if (debug_info_level != DINFO_LEVEL_TERSE)
06586         ASM_OUTPUT_SOURCE_LINE (file,
06587         DECL_SOURCE_LINE (current_function_decl));
06588 #endif
06589     }
06590 
06591   /* Issue function start and label.  */
06592   if (TARGET_ABI_OPEN_VMS
06593       || (!TARGET_ABI_UNICOSMK && !flag_inhibit_size_directive))
06594     {
06595       fputs ("\t.ent ", file);
06596       assemble_name (file, fnname);
06597       putc ('\n', file);
06598 
06599       /* If the function needs GP, we'll write the "..ng" label there.
06600    Otherwise, do it here.  */
06601       if (TARGET_ABI_OSF
06602           && ! alpha_function_needs_gp
06603     && ! current_function_is_thunk)
06604   {
06605     putc ('$', file);
06606     assemble_name (file, fnname);
06607     fputs ("..ng:\n", file);
06608   }
06609     }
06610 
06611   strcpy (entry_label, fnname);
06612   if (TARGET_ABI_OPEN_VMS)
06613     strcat (entry_label, "..en");
06614 
06615   /* For public functions, the label must be globalized by appending an
06616      additional colon.  */
06617   if (TARGET_ABI_UNICOSMK && TREE_PUBLIC (decl))
06618     strcat (entry_label, ":");
06619 
06620   ASM_OUTPUT_LABEL (file, entry_label);
06621   inside_function = TRUE;
06622 
06623   if (TARGET_ABI_OPEN_VMS)
06624     fprintf (file, "\t.base $%d\n", vms_base_regno);
06625 
06626   if (!TARGET_ABI_OPEN_VMS && !TARGET_ABI_UNICOSMK && TARGET_IEEE_CONFORMANT
06627       && !flag_inhibit_size_directive)
06628     {
06629       /* Set flags in procedure descriptor to request IEEE-conformant
06630    math-library routines.  The value we set it to is PDSC_EXC_IEEE
06631    (/usr/include/pdsc.h).  */
06632       fputs ("\t.eflag 48\n", file);
06633     }
06634 
06635   /* Set up offsets to alpha virtual arg/local debugging pointer.  */
06636   alpha_auto_offset = -frame_size + current_function_pretend_args_size;
06637   alpha_arg_offset = -frame_size + 48;
06638 
06639   /* Describe our frame.  If the frame size is larger than an integer,
06640      print it as zero to avoid an assembler error.  We won't be
06641      properly describing such a frame, but that's the best we can do.  */
06642   if (TARGET_ABI_UNICOSMK)
06643     ;
06644   else if (TARGET_ABI_OPEN_VMS)
06645     {
06646       fprintf (file, "\t.frame $%d,", vms_unwind_regno);
06647       fprintf (file, HOST_WIDE_INT_PRINT_DEC,
06648          frame_size >= ((HOST_WIDE_INT) 1 << 31) ? 0 : frame_size);
06649       fputs (",$26,", file);
06650       fprintf (file, HOST_WIDE_INT_PRINT_DEC, reg_offset);
06651       fputs ("\n", file);
06652     }
06653   else if (!flag_inhibit_size_directive)
06654     {
06655       fprintf (file, "\t.frame $%d,",
06656          (frame_pointer_needed
06657     ? HARD_FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM));
06658       fprintf (file, HOST_WIDE_INT_PRINT_DEC,
06659          frame_size >= (1l << 31) ? 0 : frame_size);
06660       fprintf (file, ",$26,%d\n", current_function_pretend_args_size);
06661     }
06662 
06663   /* Describe which registers were spilled.  */
06664   if (TARGET_ABI_UNICOSMK)
06665     ;
06666   else if (TARGET_ABI_OPEN_VMS)
06667     {
06668       if (imask)
06669         /* ??? Does VMS care if mask contains ra?  The old code didn't
06670            set it, so I don't here.  */
06671   fprintf (file, "\t.mask 0x%lx,0\n", imask & ~(1L << REG_RA));
06672       if (fmask)
06673   fprintf (file, "\t.fmask 0x%lx,0\n", fmask);
06674       if (alpha_procedure_type == PT_REGISTER)
06675   fprintf (file, "\t.fp_save $%d\n", vms_save_fp_regno);
06676     }
06677   else if (!flag_inhibit_size_directive)
06678     {
06679       if (imask)
06680   {
06681     fprintf (file, "\t.mask 0x%lx,", imask);
06682     fprintf (file, HOST_WIDE_INT_PRINT_DEC,
06683        frame_size >= (1l << 31) ? 0 : reg_offset - frame_size);
06684     putc ('\n', file);
06685 
06686     for (i = 0; i < 32; ++i)
06687       if (imask & (1L << i))
06688         reg_offset += 8;
06689   }
06690 
06691       if (fmask)
06692   {
06693     fprintf (file, "\t.fmask 0x%lx,", fmask);
06694     fprintf (file, HOST_WIDE_INT_PRINT_DEC,
06695        frame_size >= (1l << 31) ? 0 : reg_offset - frame_size);
06696     putc ('\n', file);
06697   }
06698     }
06699 
06700 #if TARGET_ABI_OPEN_VMS
06701   /* Ifdef'ed cause readonly_section and link_section are only
06702      available then.  */
06703   readonly_section ();
06704   fprintf (file, "\t.align 3\n");
06705   assemble_name (file, fnname); fputs ("..na:\n", file);
06706   fputs ("\t.ascii \"", file);
06707   assemble_name (file, fnname);
06708   fputs ("\\0\"\n", file);
06709       
06710   link_section ();
06711   fprintf (file, "\t.align 3\n");
06712   fputs ("\t.name ", file);
06713   assemble_name (file, fnname);
06714   fputs ("..na\n", file);
06715   ASM_OUTPUT_LABEL (file, fnname);
06716   fprintf (file, "\t.pdesc ");
06717   assemble_name (file, fnname);
06718   fprintf (file, "..en,%s\n",
06719      alpha_procedure_type == PT_STACK ? "stack"
06720      : alpha_procedure_type == PT_REGISTER ? "reg" : "null");
06721   alpha_need_linkage (fnname, 1);
06722   text_section ();
06723 #endif
06724 }
06725 
06726 /* Emit the .prologue note at the scheduled end of the prologue.  */
06727 
06728 static void
06729 alpha_output_function_end_prologue (file)
06730      FILE *file;
06731 {
06732   if (TARGET_ABI_UNICOSMK)
06733     ;
06734   else if (TARGET_ABI_OPEN_VMS)
06735     fputs ("\t.prologue\n", file);
06736   else if (TARGET_ABI_WINDOWS_NT)
06737     fputs ("\t.prologue 0\n", file);
06738   else if (!flag_inhibit_size_directive)
06739     fprintf (file, "\t.prologue %d\n",
06740        alpha_function_needs_gp || current_function_is_thunk);
06741 }
06742 
06743 /* Write function epilogue.  */
06744 
06745 /* ??? At some point we will want to support full unwind, and so will 
06746    need to mark the epilogue as well.  At the moment, we just confuse
06747    dwarf2out.  */
06748 #undef FRP
06749 #define FRP(exp) exp
06750 
06751 void
06752 alpha_expand_epilogue ()
06753 {
06754   /* Registers to save.  */
06755   unsigned long imask = 0;
06756   unsigned long fmask = 0;
06757   /* Stack space needed for pushing registers clobbered by us.  */
06758   HOST_WIDE_INT sa_size;
06759   /* Complete stack size needed.  */
06760   HOST_WIDE_INT frame_size;
06761   /* Offset from base reg to register save area.  */
06762   HOST_WIDE_INT reg_offset;
06763   int fp_is_frame_pointer, fp_offset;
06764   rtx sa_reg, sa_reg_exp = NULL;
06765   rtx sp_adj1, sp_adj2, mem;
06766   rtx eh_ofs;
06767   int i;
06768 
06769   sa_size = alpha_sa_size ();
06770 
06771   frame_size = get_frame_size ();
06772   if (TARGET_ABI_OPEN_VMS)
06773     frame_size = ALPHA_ROUND (sa_size 
06774             + (alpha_procedure_type == PT_STACK ? 8 : 0)
06775             + frame_size
06776             + current_function_pretend_args_size);
06777   else if (TARGET_ABI_UNICOSMK)
06778     frame_size = ALPHA_ROUND (sa_size
06779             + (alpha_procedure_type == PT_STACK ? 48 : 0))
06780      + ALPHA_ROUND (frame_size
06781             + current_function_outgoing_args_size);
06782   else
06783     frame_size = (ALPHA_ROUND (current_function_outgoing_args_size)
06784       + sa_size
06785       + ALPHA_ROUND (frame_size
06786          + current_function_pretend_args_size));
06787 
06788   if (TARGET_ABI_OPEN_VMS)
06789     {
06790        if (alpha_procedure_type == PT_STACK)
06791           reg_offset = 8;
06792        else
06793           reg_offset = 0;
06794     }
06795   else
06796     reg_offset = ALPHA_ROUND (current_function_outgoing_args_size);
06797 
06798   alpha_sa_mask (&imask, &fmask);
06799 
06800   fp_is_frame_pointer
06801     = ((TARGET_ABI_OPEN_VMS && alpha_procedure_type == PT_STACK)
06802        || (!TARGET_ABI_OPEN_VMS && frame_pointer_needed));
06803   fp_offset = 0;
06804   sa_reg = stack_pointer_rtx;
06805 
06806   if (current_function_calls_eh_return)
06807     eh_ofs = EH_RETURN_STACKADJ_RTX;
06808   else
06809     eh_ofs = NULL_RTX;
06810 
06811   if (!TARGET_ABI_UNICOSMK && sa_size)
06812     {
06813       /* If we have a frame pointer, restore SP from it.  */
06814       if ((TARGET_ABI_OPEN_VMS
06815      && vms_unwind_regno == HARD_FRAME_POINTER_REGNUM)
06816     || (!TARGET_ABI_OPEN_VMS && frame_pointer_needed))
06817   FRP (emit_move_insn (stack_pointer_rtx, hard_frame_pointer_rtx));
06818 
06819       /* Cope with very large offsets to the register save area.  */
06820       if (reg_offset + sa_size > 0x8000)
06821   {
06822     int low = ((reg_offset & 0xffff) ^ 0x8000) - 0x8000;
06823     HOST_WIDE_INT bias;
06824 
06825     if (low + sa_size <= 0x8000)
06826       bias = reg_offset - low, reg_offset = low;
06827     else 
06828       bias = reg_offset, reg_offset = 0;
06829 
06830     sa_reg = gen_rtx_REG (DImode, 22);
06831     sa_reg_exp = plus_constant (stack_pointer_rtx, bias);
06832 
06833     FRP (emit_move_insn (sa_reg, sa_reg_exp));
06834   }
06835     
06836       /* Restore registers in order, excepting a true frame pointer.  */
06837 
06838       mem = gen_rtx_MEM (DImode, plus_constant (sa_reg, reg_offset));
06839       if (! eh_ofs)
06840         set_mem_alias_set (mem, alpha_sr_alias_set);
06841       FRP (emit_move_insn (gen_rtx_REG (DImode, REG_RA), mem));
06842 
06843       reg_offset += 8;
06844       imask &= ~(1L << REG_RA);
06845 
06846       for (i = 0; i < 32; ++i)
06847   if (imask & (1L << i))
06848     {
06849       if (i == HARD_FRAME_POINTER_REGNUM && fp_is_frame_pointer)
06850         fp_offset = reg_offset;
06851       else
06852         {
06853     mem = gen_rtx_MEM (DImode, plus_constant(sa_reg, reg_offset));
06854     set_mem_alias_set (mem, alpha_sr_alias_set);
06855     FRP (emit_move_insn (gen_rtx_REG (DImode, i), mem));
06856         }
06857       reg_offset += 8;
06858     }
06859 
06860       for (i = 0; i < 32; ++i)
06861   if (fmask & (1L << i))
06862     {
06863       mem = gen_rtx_MEM (DFmode, plus_constant(sa_reg, reg_offset));
06864       set_mem_alias_set (mem, alpha_sr_alias_set);
06865       FRP (emit_move_insn (gen_rtx_REG (DFmode, i+32), mem));
06866       reg_offset += 8;
06867     }
06868     }
06869   else if (TARGET_ABI_UNICOSMK && alpha_procedure_type == PT_STACK)
06870     {
06871       /* Restore callee-saved general-purpose registers.  */
06872 
06873       reg_offset = -56;
06874 
06875       for (i = 9; i < 15; i++)
06876   if (imask & (1L << i))
06877     {
06878       mem = gen_rtx_MEM (DImode, plus_constant(hard_frame_pointer_rtx,
06879                  reg_offset));
06880       set_mem_alias_set (mem, alpha_sr_alias_set);
06881       FRP (emit_move_insn (gen_rtx_REG (DImode, i), mem));
06882       reg_offset -= 8;
06883     }
06884 
06885       for (i = 2; i < 10; i++)
06886   if (fmask & (1L << i))
06887     {
06888       mem = gen_rtx_MEM (DFmode, plus_constant(hard_frame_pointer_rtx,
06889                  reg_offset));
06890       set_mem_alias_set (mem, alpha_sr_alias_set);
06891       FRP (emit_move_insn (gen_rtx_REG (DFmode, i+32), mem));
06892       reg_offset -= 8;
06893     }
06894 
06895       /* Restore the return address from the DSIB.  */
06896 
06897       mem = gen_rtx_MEM (DImode, plus_constant(hard_frame_pointer_rtx, -8));
06898       set_mem_alias_set (mem, alpha_sr_alias_set);
06899       FRP (emit_move_insn (gen_rtx_REG (DImode, REG_RA), mem));
06900     }
06901 
06902   if (frame_size || eh_ofs)
06903     {
06904       sp_adj1 = stack_pointer_rtx;
06905 
06906       if (eh_ofs)
06907   {
06908     sp_adj1 = gen_rtx_REG (DImode, 23);
06909     emit_move_insn (sp_adj1,
06910         gen_rtx_PLUS (Pmode, stack_pointer_rtx, eh_ofs));
06911   }
06912 
06913       /* If the stack size is large, begin computation into a temporary
06914    register so as not to interfere with a potential fp restore,
06915    which must be consecutive with an SP restore.  */
06916       if (frame_size < 32768
06917     && ! (TARGET_ABI_UNICOSMK && current_function_calls_alloca))
06918   sp_adj2 = GEN_INT (frame_size);
06919       else if (TARGET_ABI_UNICOSMK)
06920   {
06921     sp_adj1 = gen_rtx_REG (DImode, 23);
06922     FRP (emit_move_insn (sp_adj1, hard_frame_pointer_rtx));
06923     sp_adj2 = const0_rtx;
06924   }
06925       else if (frame_size < 0x40007fffL)
06926   {
06927     int low = ((frame_size & 0xffff) ^ 0x8000) - 0x8000;
06928 
06929     sp_adj2 = plus_constant (sp_adj1, frame_size - low);
06930     if (sa_reg_exp && rtx_equal_p (sa_reg_exp, sp_adj2))
06931       sp_adj1 = sa_reg;
06932     else
06933       {
06934         sp_adj1 = gen_rtx_REG (DImode, 23);
06935         FRP (emit_move_insn (sp_adj1, sp_adj2));
06936       }
06937     sp_adj2 = GEN_INT (low);
06938   }
06939       else
06940   {
06941     rtx tmp = gen_rtx_REG (DImode, 23);
06942     FRP (sp_adj2 = alpha_emit_set_const (tmp, DImode, frame_size, 3));
06943     if (!sp_adj2)
06944       {
06945         /* We can't drop new things to memory this late, afaik,
06946      so build it up by pieces.  */
06947         FRP (sp_adj2 = alpha_emit_set_long_const (tmp, frame_size,
06948               -(frame_size < 0)));
06949         if (!sp_adj2)
06950     abort ();
06951       }
06952   }
06953 
06954       /* From now on, things must be in order.  So emit blockages.  */
06955 
06956       /* Restore the frame pointer.  */
06957       if (TARGET_ABI_UNICOSMK)
06958   {
06959     emit_insn (gen_blockage ());
06960     mem = gen_rtx_MEM (DImode,
06961            plus_constant (hard_frame_pointer_rtx, -16));
06962     set_mem_alias_set (mem, alpha_sr_alias_set);
06963     FRP (emit_move_insn (hard_frame_pointer_rtx, mem));
06964   }
06965       else if (fp_is_frame_pointer)
06966   {
06967     emit_insn (gen_blockage ());
06968     mem = gen_rtx_MEM (DImode, plus_constant (sa_reg, fp_offset));
06969     set_mem_alias_set (mem, alpha_sr_alias_set);
06970     FRP (emit_move_insn (hard_frame_pointer_rtx, mem));
06971   }
06972       else if (TARGET_ABI_OPEN_VMS)
06973   {
06974     emit_insn (gen_blockage ());
06975     FRP (emit_move_insn (hard_frame_pointer_rtx,
06976              gen_rtx_REG (DImode, vms_save_fp_regno)));
06977   }
06978 
06979       /* Restore the stack pointer.  */
06980       emit_insn (gen_blockage ());
06981       if (sp_adj2 == const0_rtx)
06982   FRP (emit_move_insn (stack_pointer_rtx, sp_adj1));
06983       else
06984   FRP (emit_move_insn (stack_pointer_rtx,
06985            gen_rtx_PLUS (DImode, sp_adj1, sp_adj2)));
06986     }
06987   else 
06988     {
06989       if (TARGET_ABI_OPEN_VMS && alpha_procedure_type == PT_REGISTER)
06990         {
06991           emit_insn (gen_blockage ());
06992           FRP (emit_move_insn (hard_frame_pointer_rtx,
06993              gen_rtx_REG (DImode, vms_save_fp_regno)));
06994         }
06995       else if (TARGET_ABI_UNICOSMK && alpha_procedure_type != PT_STACK)
06996   {
06997     /* Decrement the frame pointer if the function does not have a
06998        frame.  */
06999 
07000     emit_insn (gen_blockage ());
07001     FRP (emit_insn (gen_adddi3 (hard_frame_pointer_rtx,
07002               hard_frame_pointer_rtx, GEN_INT (-1))));
07003         }
07004     }
07005 }
07006 
07007 /* Output the rest of the textual info surrounding the epilogue.  */
07008 
07009 void
07010 alpha_end_function (file, fnname, decl)
07011      FILE *file;
07012      const char *fnname;
07013      tree decl ATTRIBUTE_UNUSED;
07014 {
07015   /* End the function.  */
07016   if (!TARGET_ABI_UNICOSMK && !flag_inhibit_size_directive)
07017     {
07018       fputs ("\t.end ", file);
07019       assemble_name (file, fnname);
07020       putc ('\n', file);
07021     }
07022   inside_function = FALSE;
07023 
07024   /* Show that we know this function if it is called again. 
07025 
07026      Don't do this for global functions in object files destined for a
07027      shared library because the function may be overridden by the application
07028      or other libraries.  Similarly, don't do this for weak functions.
07029 
07030      Don't do this for functions not defined in the .text section, as
07031      otherwise it's not unlikely that the destination is out of range
07032      for a direct branch.  */
07033 
07034   if (!DECL_WEAK (current_function_decl)
07035       && (!flag_pic || !TREE_PUBLIC (current_function_decl))
07036       && decl_in_text_section (current_function_decl))
07037     SYMBOL_REF_FLAG (XEXP (DECL_RTL (current_function_decl), 0)) = 1;
07038 
07039   /* Output jump tables and the static subroutine information block.  */
07040   if (TARGET_ABI_UNICOSMK)
07041     {
07042       unicosmk_output_ssib (file, fnname);
07043       unicosmk_output_deferred_case_vectors (file);
07044     }
07045 }
07046 
07047 /* Emit a tail call to FUNCTION after adjusting THIS by DELTA. 
07048 
07049    In order to avoid the hordes of differences between generated code
07050    with and without TARGET_EXPLICIT_RELOCS, and to avoid duplicating
07051    lots of code loading up large constants, generate rtl and emit it
07052    instead of going straight to text.
07053 
07054    Not sure why this idea hasn't been explored before...  */
07055 
07056 void
07057 alpha_output_mi_thunk_osf (file, thunk_fndecl, delta, function)
07058      FILE *file;
07059      tree thunk_fndecl ATTRIBUTE_UNUSED;
07060      HOST_WIDE_INT delta;
07061      tree function;
07062 {
07063   HOST_WIDE_INT hi, lo;
07064   rtx this, insn, funexp;
07065 
07066   /* We always require a valid GP.  */
07067   emit_insn (gen_prologue_ldgp ());
07068   emit_note (NULL, NOTE_INSN_PROLOGUE_END);
07069 
07070   /* Find the "this" pointer.  If the function returns a structure,
07071      the structure return pointer is in $16.  */
07072   if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function))))
07073     this = gen_rtx_REG (Pmode, 17);
07074   else
07075     this = gen_rtx_REG (Pmode, 16);
07076 
07077   /* Add DELTA.  When possible we use ldah+lda.  Otherwise load the
07078      entire constant for the add.  */
07079   lo = ((delta & 0xffff) ^ 0x8000) - 0x8000;
07080   hi = (((delta - lo) & 0xffffffff) ^ 0x80000000) - 0x80000000;
07081   if (hi + lo == delta)
07082     {
07083       if (hi)
07084   emit_insn (gen_adddi3 (this, this, GEN_INT (hi)));
07085       if (lo)
07086   emit_insn (gen_adddi3 (this, this, GEN_INT (lo)));
07087     }
07088   else
07089     {
07090       rtx tmp = alpha_emit_set_long_const (gen_rtx_REG (Pmode, 0),
07091              delta, -(delta < 0));
07092       emit_insn (gen_adddi3 (this, this, tmp));
07093     }
07094 
07095   /* Generate a tail call to the target function.  */
07096   if (! TREE_USED (function))
07097     {
07098       assemble_external (function);
07099       TREE_USED (function) = 1;
07100     }
07101   funexp = XEXP (DECL_RTL (function), 0);
07102   funexp = gen_rtx_MEM (FUNCTION_MODE, funexp);
07103   insn = emit_call_insn (gen_sibcall (funexp, const0_rtx));
07104   SIBLING_CALL_P (insn) = 1;
07105 
07106   /* Run just enough of rest_of_compilation to get the insns emitted.
07107      There's not really enough bulk here to make other passes such as
07108      instruction scheduling worth while.  Note that use_thunk calls
07109      assemble_start_function and assemble_end_function.  */
07110   insn = get_insns ();
07111   shorten_branches (insn);
07112   final_start_function (insn, file, 1);
07113   final (insn, file, 1, 0);
07114   final_end_function ();
07115 }
07116 
07117 /* Debugging support.  */
07118 
07119 #include "gstab.h"
07120 
07121 /* Count the number of sdb related labels are generated (to find block
07122    start and end boundaries).  */
07123 
07124 int sdb_label_count = 0;
07125 
07126 /* Next label # for each statement.  */
07127 
07128 static int sym_lineno = 0;
07129 
07130 /* Count the number of .file directives, so that .loc is up to date.  */
07131 
07132 static int num_source_filenames = 0;
07133 
07134 /* Name of the file containing the current function.  */
07135 
07136 static const char *current_function_file = "";
07137 
07138 /* Offsets to alpha virtual arg/local debugging pointers.  */
07139 
07140 long alpha_arg_offset;
07141 long alpha_auto_offset;
07142 
07143 /* Emit a new filename to a stream.  */
07144 
07145 void
07146 alpha_output_filename (stream, name)
07147      FILE *stream;
07148      const char *name;
07149 {
07150   static int first_time = TRUE;
07151   char ltext_label_name[100];
07152 
07153   if (first_time)
07154     {
07155       first_time = FALSE;
07156       ++num_source_filenames;
07157       current_function_file = name;
07158       fprintf (stream, "\t.file\t%d ", num_source_filenames);
07159       output_quoted_string (stream, name);
07160       fprintf (stream, "\n");
07161       if (!TARGET_GAS && write_symbols == DBX_DEBUG)
07162   fprintf (stream, "\t#@stabs\n");
07163     }
07164 
07165   else if (write_symbols == DBX_DEBUG)
07166     {
07167       ASM_GENERATE_INTERNAL_LABEL (ltext_label_name, "Ltext", 0);
07168       fprintf (stream, "%s", ASM_STABS_OP);
07169       output_quoted_string (stream, name);
07170       fprintf (stream, ",%d,0,0,%s\n", N_SOL, &ltext_label_name[1]);
07171     }
07172 
07173   else if (name != current_function_file
07174      && strcmp (name, current_function_file) != 0)
07175     {
07176       if (inside_function && ! TARGET_GAS)
07177   fprintf (stream, "\t#.file\t%d ", num_source_filenames);
07178       else
07179   {
07180     ++num_source_filenames;
07181     current_function_file = name;
07182     fprintf (stream, "\t.file\t%d ", num_source_filenames);
07183   }
07184 
07185       output_quoted_string (stream, name);
07186       fprintf (stream, "\n");
07187     }
07188 }
07189 
07190 /* Emit a linenumber to a stream.  */
07191 
07192 void
07193 alpha_output_lineno (stream, line)
07194      FILE *stream;
07195      int line;
07196 {
07197   if (write_symbols == DBX_DEBUG)
07198     {
07199       /* mips-tfile doesn't understand .stabd directives.  */
07200       ++sym_lineno;
07201       fprintf (stream, "$LM%d:\n%s%d,0,%d,$LM%d\n",
07202          sym_lineno, ASM_STABN_OP, N_SLINE, line, sym_lineno);
07203     }
07204   else
07205     fprintf (stream, "\n\t.loc\t%d %d\n", num_source_filenames, line);
07206 }
07207 
07208 /* Structure to show the current status of registers and memory.  */
07209 
07210 struct shadow_summary
07211 {
07212   struct {
07213     unsigned int i     : 31;  /* Mask of int regs */
07214     unsigned int fp    : 31;  /* Mask of fp regs */
07215     unsigned int mem   :  1;  /* mem == imem | fpmem */
07216   } used, defd;
07217 };
07218 
07219 static void summarize_insn PARAMS ((rtx, struct shadow_summary *, int));
07220 static void alpha_handle_trap_shadows PARAMS ((rtx));
07221 
07222 /* Summary the effects of expression X on the machine.  Update SUM, a pointer
07223    to the summary structure.  SET is nonzero if the insn is setting the
07224    object, otherwise zero.  */
07225 
07226 static void
07227 summarize_insn (x, sum, set)
07228      rtx x;
07229      struct shadow_summary *sum;
07230      int set;
07231 {
07232   const char *format_ptr;
07233   int i, j;
07234 
07235   if (x == 0)
07236     return;
07237 
07238   switch (GET_CODE (x))
07239     {
07240       /* ??? Note that this case would be incorrect if the Alpha had a
07241    ZERO_EXTRACT in SET_DEST.  */
07242     case SET:
07243       summarize_insn (SET_SRC (x), sum, 0);
07244       summarize_insn (SET_DEST (x), sum, 1);
07245       break;
07246 
07247     case CLOBBER:
07248       summarize_insn (XEXP (x, 0), sum, 1);
07249       break;
07250 
07251     case USE:
07252       summarize_insn (XEXP (x, 0), sum, 0);
07253       break;
07254 
07255     case ASM_OPERANDS:
07256       for (i = ASM_OPERANDS_INPUT_LENGTH (x) - 1; i >= 0; i--)
07257   summarize_insn (ASM_OPERANDS_INPUT (x, i), sum, 0);
07258       break;
07259 
07260     case PARALLEL:
07261       for (i = XVECLEN (x, 0) - 1; i >= 0; i--)
07262   summarize_insn (XVECEXP (x, 0, i), sum, 0);
07263       break;
07264 
07265     case SUBREG:
07266       summarize_insn (SUBREG_REG (x), sum, 0);
07267       break;
07268 
07269     case REG:
07270       {
07271   int regno = REGNO (x);
07272   unsigned long mask = ((unsigned long) 1) << (regno % 32);
07273 
07274   if (regno == 31 || regno == 63)
07275     break;
07276 
07277   if (set)
07278     {
07279       if (regno < 32)
07280         sum->defd.i |= mask;
07281       else
07282         sum->defd.fp |= mask;
07283     }
07284   else
07285     {
07286       if (regno < 32)
07287         sum->used.i  |= mask;
07288       else
07289         sum->used.fp |= mask;
07290     }
07291   }
07292       break;
07293 
07294     case MEM:
07295       if (set)
07296   sum->defd.mem = 1;
07297       else
07298   sum->used.mem = 1;
07299 
07300       /* Find the regs used in memory address computation: */
07301       summarize_insn (XEXP (x, 0), sum, 0);
07302       break;
07303 
07304     case CONST_INT:   case CONST_DOUBLE:
07305     case SYMBOL_REF:  case LABEL_REF:     case CONST:
07306     case SCRATCH:     case ASM_INPUT:
07307       break;
07308 
07309       /* Handle common unary and binary ops for efficiency.  */
07310     case COMPARE:  case PLUS:    case MINUS:   case MULT:      case DIV:
07311     case MOD:      case UDIV:    case UMOD:    case AND:       case IOR:
07312     case XOR:      case ASHIFT:  case ROTATE:  case ASHIFTRT:  case LSHIFTRT:
07313     case ROTATERT: case SMIN:    case SMAX:    case UMIN:      case UMAX:
07314     case NE:       case EQ:      case GE:      case GT:        case LE:
07315     case LT:       case GEU:     case GTU:     case LEU:       case LTU:
07316       summarize_insn (XEXP (x, 0), sum, 0);
07317       summarize_insn (XEXP (x, 1), sum, 0);
07318       break;
07319 
07320     case NEG:  case NOT:  case SIGN_EXTEND:  case ZERO_EXTEND:
07321     case TRUNCATE:  case FLOAT_EXTEND:  case FLOAT_TRUNCATE:  case FLOAT:
07322     case FIX:  case UNSIGNED_FLOAT:  case UNSIGNED_FIX:  case ABS:
07323     case SQRT:  case FFS: 
07324       summarize_insn (XEXP (x, 0), sum, 0);
07325       break;
07326 
07327     default:
07328       format_ptr = GET_RTX_FORMAT (GET_CODE (x));
07329       for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
07330   switch (format_ptr[i])
07331     {
07332     case 'e':
07333       summarize_insn (XEXP (x, i), sum, 0);
07334       break;
07335 
07336     case 'E':
07337       for (j = XVECLEN (x, i) - 1; j >= 0; j--)
07338         summarize_insn (XVECEXP (x, i, j), sum, 0);
07339       break;
07340 
07341     case 'i':
07342       break;
07343 
07344     default:
07345       abort ();
07346     }
07347     }
07348 }
07349 
07350 /* Ensure a sufficient number of `trapb' insns are in the code when
07351    the user requests code with a trap precision of functions or
07352    instructions.
07353 
07354    In naive mode, when the user requests a trap-precision of
07355    "instruction", a trapb is needed after every instruction that may
07356    generate a trap.  This ensures that the code is resumption safe but
07357    it is also slow.
07358 
07359    When optimizations are turned on, we delay issuing a trapb as long
07360    as possible.  In this context, a trap shadow is the sequence of
07361    instructions that starts with a (potentially) trap generating
07362    instruction and extends to the next trapb or call_pal instruction
07363    (but GCC never generates call_pal by itself).  We can delay (and
07364    therefore sometimes omit) a trapb subject to the following
07365    conditions:
07366 
07367    (a) On entry to the trap shadow, if any Alpha register or memory
07368    location contains a value that is used as an operand value by some
07369    instruction in the trap shadow (live on entry), then no instruc