OSDN Git Service

* config/alpha/osf5.h (TARGET_LD_BUGGY_LDGP): New.
[pf3gnuchains/gcc-fork.git] / gcc / config / alpha / alpha.c
1 /* Subroutines used for code generation on the DEC Alpha.
2    Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
3    2000, 2001 Free Software Foundation, Inc. 
4    Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
5
6 This file is part of GNU CC.
7
8 GNU CC is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
11 any later version.
12
13 GNU CC is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with GNU CC; see the file COPYING.  If not, write to
20 the Free Software Foundation, 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA.  */
22
23
24 #include "config.h"
25 #include "system.h"
26 #include "rtl.h"
27 #include "regs.h"
28 #include "hard-reg-set.h"
29 #include "real.h"
30 #include "insn-config.h"
31 #include "conditions.h"
32 #include "output.h"
33 #include "insn-attr.h"
34 #include "flags.h"
35 #include "recog.h"
36 #include "reload.h"
37 #include "tree.h"
38 #include "expr.h"
39 #include "obstack.h"
40 #include "except.h"
41 #include "function.h"
42 #include "toplev.h"
43 #include "ggc.h"
44 #include "tm_p.h"
45
46 /* External data.  */
47 extern int rtx_equal_function_value_matters;
48
49 /* Specify which cpu to schedule for. */
50
51 enum processor_type alpha_cpu;
52 static const char * const alpha_cpu_name[] = 
53 {
54   "ev4", "ev5", "ev6"
55 };
56
57 /* Specify how accurate floating-point traps need to be.  */
58
59 enum alpha_trap_precision alpha_tp;
60
61 /* Specify the floating-point rounding mode.  */
62
63 enum alpha_fp_rounding_mode alpha_fprm;
64
65 /* Specify which things cause traps.  */
66
67 enum alpha_fp_trap_mode alpha_fptm;
68
69 /* Strings decoded into the above options.  */
70
71 const char *alpha_cpu_string;   /* -mcpu= */
72 const char *alpha_tune_string;  /* -mtune= */
73 const char *alpha_tp_string;    /* -mtrap-precision=[p|s|i] */
74 const char *alpha_fprm_string;  /* -mfp-rounding-mode=[n|m|c|d] */
75 const char *alpha_fptm_string;  /* -mfp-trap-mode=[n|u|su|sui] */
76 const char *alpha_mlat_string;  /* -mmemory-latency= */
77
78 /* Save information from a "cmpxx" operation until the branch or scc is
79    emitted.  */
80
81 struct alpha_compare alpha_compare;
82
83 /* Non-zero if inside of a function, because the Alpha asm can't
84    handle .files inside of functions.  */
85
86 static int inside_function = FALSE;
87
88 /* The number of cycles of latency we should assume on memory reads.  */
89
90 int alpha_memory_latency = 3;
91
92 /* Whether the function needs the GP.  */
93
94 static int alpha_function_needs_gp;
95
96 /* The alias set for prologue/epilogue register save/restore.  */
97
98 static int alpha_sr_alias_set;
99
100 /* The assembler name of the current function.  */
101
102 static const char *alpha_fnname;
103
104 /* Declarations of static functions.  */
105 static void alpha_set_memflags_1
106   PARAMS ((rtx, int, int, int));
107 static rtx alpha_emit_set_const_1
108   PARAMS ((rtx, enum machine_mode, HOST_WIDE_INT, int));
109 static void alpha_expand_unaligned_load_words
110   PARAMS ((rtx *out_regs, rtx smem, HOST_WIDE_INT words, HOST_WIDE_INT ofs));
111 static void alpha_expand_unaligned_store_words
112   PARAMS ((rtx *out_regs, rtx smem, HOST_WIDE_INT words, HOST_WIDE_INT ofs));
113 static void alpha_sa_mask
114   PARAMS ((unsigned long *imaskP, unsigned long *fmaskP));
115 static int alpha_does_function_need_gp
116   PARAMS ((void));
117 static void alpha_init_machine_status
118   PARAMS ((struct function *p));
119 static void alpha_mark_machine_status
120   PARAMS ((struct function *p));
121 static void alpha_free_machine_status
122   PARAMS ((struct function *p));
123 static int alpha_ra_ever_killed
124   PARAMS ((void));
125 static rtx set_frame_related_p
126   PARAMS ((void));
127 static const char *alpha_lookup_xfloating_lib_func
128   PARAMS ((enum rtx_code));
129 static int alpha_compute_xfloating_mode_arg
130   PARAMS ((enum rtx_code, enum alpha_fp_rounding_mode));
131 static void alpha_emit_xfloating_libcall
132   PARAMS ((const char *, rtx, rtx[], int, rtx));
133 static rtx alpha_emit_xfloating_compare
134   PARAMS ((enum rtx_code, rtx, rtx));
135
136 /* Get the number of args of a function in one of two ways.  */
137 #ifdef OPEN_VMS
138 #define NUM_ARGS current_function_args_info.num_args
139 #else
140 #define NUM_ARGS current_function_args_info
141 #endif
142
143 #define REG_PV 27
144 #define REG_RA 26
145 \f
146 /* Parse target option strings. */
147
148 void
149 override_options ()
150 {
151   int i;
152   static struct cpu_table {
153     const char *name;
154     enum processor_type processor;
155     int flags;
156   } cpu_table[] = {
157 #define EV5_MASK (MASK_CPU_EV5)
158 #define EV6_MASK (MASK_CPU_EV6|MASK_BWX|MASK_MAX|MASK_FIX)
159     { "ev4",    PROCESSOR_EV4, 0 },
160     { "ev45",   PROCESSOR_EV4, 0 },
161     { "21064",  PROCESSOR_EV4, 0 },
162     { "ev5",    PROCESSOR_EV5, EV5_MASK },
163     { "21164",  PROCESSOR_EV5, EV5_MASK },
164     { "ev56",   PROCESSOR_EV5, EV5_MASK|MASK_BWX },
165     { "21164a", PROCESSOR_EV5, EV5_MASK|MASK_BWX },
166     { "pca56",  PROCESSOR_EV5, EV5_MASK|MASK_BWX|MASK_MAX },
167     { "21164PC",PROCESSOR_EV5, EV5_MASK|MASK_BWX|MASK_MAX },
168     { "21164pc",PROCESSOR_EV5, EV5_MASK|MASK_BWX|MASK_MAX },
169     { "ev6",    PROCESSOR_EV6, EV6_MASK },
170     { "21264",  PROCESSOR_EV6, EV6_MASK },
171     { "ev67",   PROCESSOR_EV6, EV6_MASK|MASK_CIX },
172     { "21264a", PROCESSOR_EV6, EV6_MASK|MASK_CIX },
173     { 0, 0, 0 }
174   };
175                   
176   alpha_tp = ALPHA_TP_PROG;
177   alpha_fprm = ALPHA_FPRM_NORM;
178   alpha_fptm = ALPHA_FPTM_N;
179
180   if (TARGET_IEEE)
181     {
182       alpha_tp = ALPHA_TP_INSN;
183       alpha_fptm = ALPHA_FPTM_SU;
184     }
185
186   if (TARGET_IEEE_WITH_INEXACT)
187     {
188       alpha_tp = ALPHA_TP_INSN;
189       alpha_fptm = ALPHA_FPTM_SUI;
190     }
191
192   if (alpha_tp_string)
193     {
194       if (! strcmp (alpha_tp_string, "p"))
195         alpha_tp = ALPHA_TP_PROG;
196       else if (! strcmp (alpha_tp_string, "f"))
197         alpha_tp = ALPHA_TP_FUNC;
198       else if (! strcmp (alpha_tp_string, "i"))
199         alpha_tp = ALPHA_TP_INSN;
200       else
201         error ("bad value `%s' for -mtrap-precision switch", alpha_tp_string);
202     }
203
204   if (alpha_fprm_string)
205     {
206       if (! strcmp (alpha_fprm_string, "n"))
207         alpha_fprm = ALPHA_FPRM_NORM;
208       else if (! strcmp (alpha_fprm_string, "m"))
209         alpha_fprm = ALPHA_FPRM_MINF;
210       else if (! strcmp (alpha_fprm_string, "c"))
211         alpha_fprm = ALPHA_FPRM_CHOP;
212       else if (! strcmp (alpha_fprm_string,"d"))
213         alpha_fprm = ALPHA_FPRM_DYN;
214       else
215         error ("bad value `%s' for -mfp-rounding-mode switch",
216                alpha_fprm_string);
217     }
218
219   if (alpha_fptm_string)
220     {
221       if (strcmp (alpha_fptm_string, "n") == 0)
222         alpha_fptm = ALPHA_FPTM_N;
223       else if (strcmp (alpha_fptm_string, "u") == 0)
224         alpha_fptm = ALPHA_FPTM_U;
225       else if (strcmp (alpha_fptm_string, "su") == 0)
226         alpha_fptm = ALPHA_FPTM_SU;
227       else if (strcmp (alpha_fptm_string, "sui") == 0)
228         alpha_fptm = ALPHA_FPTM_SUI;
229       else
230         error ("bad value `%s' for -mfp-trap-mode switch", alpha_fptm_string);
231     }
232
233   alpha_cpu
234     = TARGET_CPU_DEFAULT & MASK_CPU_EV6 ? PROCESSOR_EV6
235       : (TARGET_CPU_DEFAULT & MASK_CPU_EV5 ? PROCESSOR_EV5 : PROCESSOR_EV4);
236
237   if (alpha_cpu_string)
238     {
239       for (i = 0; cpu_table [i].name; i++)
240         if (! strcmp (alpha_cpu_string, cpu_table [i].name))
241           {
242             alpha_cpu = cpu_table [i].processor;
243             target_flags &= ~ (MASK_BWX | MASK_MAX | MASK_FIX | MASK_CIX
244                                | MASK_CPU_EV5 | MASK_CPU_EV6);
245             target_flags |= cpu_table [i].flags;
246             break;
247           }
248       if (! cpu_table [i].name)
249         error ("bad value `%s' for -mcpu switch", alpha_cpu_string);
250     }
251
252   if (alpha_tune_string)
253     {
254       for (i = 0; cpu_table [i].name; i++)
255         if (! strcmp (alpha_tune_string, cpu_table [i].name))
256           {
257             alpha_cpu = cpu_table [i].processor;
258             break;
259           }
260       if (! cpu_table [i].name)
261         error ("bad value `%s' for -mcpu switch", alpha_tune_string);
262     }
263
264   /* Do some sanity checks on the above options. */
265
266   if ((alpha_fptm == ALPHA_FPTM_SU || alpha_fptm == ALPHA_FPTM_SUI)
267       && alpha_tp != ALPHA_TP_INSN && ! TARGET_CPU_EV6)
268     {
269       warning ("fp software completion requires -mtrap-precision=i");
270       alpha_tp = ALPHA_TP_INSN;
271     }
272
273   if (TARGET_CPU_EV6)
274     {
275       /* Except for EV6 pass 1 (not released), we always have precise
276          arithmetic traps.  Which means we can do software completion
277          without minding trap shadows.  */
278       alpha_tp = ALPHA_TP_PROG;
279     }
280
281   if (TARGET_FLOAT_VAX)
282     {
283       if (alpha_fprm == ALPHA_FPRM_MINF || alpha_fprm == ALPHA_FPRM_DYN)
284         {
285           warning ("rounding mode not supported for VAX floats");
286           alpha_fprm = ALPHA_FPRM_NORM;
287         }
288       if (alpha_fptm == ALPHA_FPTM_SUI)
289         {
290           warning ("trap mode not supported for VAX floats");
291           alpha_fptm = ALPHA_FPTM_SU;
292         }
293     }
294
295   {
296     char *end;
297     int lat;
298
299     if (!alpha_mlat_string)
300       alpha_mlat_string = "L1";
301
302     if (ISDIGIT ((unsigned char)alpha_mlat_string[0])
303         && (lat = strtol (alpha_mlat_string, &end, 10), *end == '\0'))
304       ;
305     else if ((alpha_mlat_string[0] == 'L' || alpha_mlat_string[0] == 'l')
306              && ISDIGIT ((unsigned char)alpha_mlat_string[1])
307              && alpha_mlat_string[2] == '\0')
308       {
309         static int const cache_latency[][4] = 
310         {
311           { 3, 30, -1 },        /* ev4 -- Bcache is a guess */
312           { 2, 12, 38 },        /* ev5 -- Bcache from PC164 LMbench numbers */
313           { 3, 12, 30 },        /* ev6 -- Bcache from DS20 LMbench. */
314         };
315
316         lat = alpha_mlat_string[1] - '0';
317         if (lat <= 0 || lat > 3 || cache_latency[alpha_cpu][lat-1] == -1)
318           {
319             warning ("L%d cache latency unknown for %s",
320                      lat, alpha_cpu_name[alpha_cpu]);
321             lat = 3;
322           }
323         else
324           lat = cache_latency[alpha_cpu][lat-1];
325       }
326     else if (! strcmp (alpha_mlat_string, "main"))
327       {
328         /* Most current memories have about 370ns latency.  This is
329            a reasonable guess for a fast cpu.  */
330         lat = 150;
331       }
332     else
333       {
334         warning ("bad value `%s' for -mmemory-latency", alpha_mlat_string);
335         lat = 3;
336       }
337
338     alpha_memory_latency = lat;
339   }
340
341   /* Default the definition of "small data" to 8 bytes.  */
342   if (!g_switch_set)
343     g_switch_value = 8;
344
345   /* Align labels and loops for optimal branching.  */
346   /* ??? Kludge these by not doing anything if we don't optimize and also if
347      we are writing ECOFF symbols to work around a bug in DEC's assembler. */
348   if (optimize > 0 && write_symbols != SDB_DEBUG)
349     {
350       if (align_loops <= 0)
351         align_loops = 16;
352       if (align_jumps <= 0)
353         align_jumps = 16;
354     }
355   if (align_functions <= 0)
356     align_functions = 16;
357
358   /* Acquire a unique set number for our register saves and restores.  */
359   alpha_sr_alias_set = new_alias_set ();
360
361   /* Set up function hooks.  */
362   init_machine_status = alpha_init_machine_status;
363   mark_machine_status = alpha_mark_machine_status;
364   free_machine_status = alpha_free_machine_status;
365 }
366 \f
367 /* Returns 1 if VALUE is a mask that contains full bytes of zero or ones.  */
368
369 int
370 zap_mask (value)
371      HOST_WIDE_INT value;
372 {
373   int i;
374
375   for (i = 0; i < HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR;
376        i++, value >>= 8)
377     if ((value & 0xff) != 0 && (value & 0xff) != 0xff)
378       return 0;
379
380   return 1;
381 }
382
383 /* Returns 1 if OP is either the constant zero or a register.  If a
384    register, it must be in the proper mode unless MODE is VOIDmode.  */
385
386 int
387 reg_or_0_operand (op, mode)
388       register rtx op;
389       enum machine_mode mode;
390 {
391   return op == const0_rtx || register_operand (op, mode);
392 }
393
394 /* Return 1 if OP is a constant in the range of 0-63 (for a shift) or
395    any register.  */
396
397 int
398 reg_or_6bit_operand (op, mode)
399      register rtx op;
400      enum machine_mode mode;
401 {
402   return ((GET_CODE (op) == CONST_INT
403            && (unsigned HOST_WIDE_INT) INTVAL (op) < 64)
404           || register_operand (op, mode));
405 }
406
407
408 /* Return 1 if OP is an 8-bit constant or any register.  */
409
410 int
411 reg_or_8bit_operand (op, mode)
412      register rtx op;
413      enum machine_mode mode;
414 {
415   return ((GET_CODE (op) == CONST_INT
416            && (unsigned HOST_WIDE_INT) INTVAL (op) < 0x100)
417           || register_operand (op, mode));
418 }
419
420 /* Return 1 if OP is an 8-bit constant.  */
421
422 int
423 cint8_operand (op, mode)
424      register rtx op;
425      enum machine_mode mode ATTRIBUTE_UNUSED;
426 {
427   return ((GET_CODE (op) == CONST_INT
428            && (unsigned HOST_WIDE_INT) INTVAL (op) < 0x100));
429 }
430
431 /* Return 1 if the operand is a valid second operand to an add insn.  */
432
433 int
434 add_operand (op, mode)
435      register rtx op;
436      enum machine_mode mode;
437 {
438   if (GET_CODE (op) == CONST_INT)
439     /* Constraints I, J, O and P are covered by K.  */
440     return (CONST_OK_FOR_LETTER_P (INTVAL (op), 'K')
441             || CONST_OK_FOR_LETTER_P (INTVAL (op), 'L'));
442
443   return register_operand (op, mode);
444 }
445
446 /* Return 1 if the operand is a valid second operand to a sign-extending
447    add insn.  */
448
449 int
450 sext_add_operand (op, mode)
451      register rtx op;
452      enum machine_mode mode;
453 {
454   if (GET_CODE (op) == CONST_INT)
455     return (CONST_OK_FOR_LETTER_P (INTVAL (op), 'I')
456             || CONST_OK_FOR_LETTER_P (INTVAL (op), 'O'));
457
458   return reg_not_elim_operand (op, mode);
459 }
460
461 /* Return 1 if OP is the constant 4 or 8.  */
462
463 int
464 const48_operand (op, mode)
465      register rtx op;
466      enum machine_mode mode ATTRIBUTE_UNUSED;
467 {
468   return (GET_CODE (op) == CONST_INT
469           && (INTVAL (op) == 4 || INTVAL (op) == 8));
470 }
471
472 /* Return 1 if OP is a valid first operand to an AND insn.  */
473
474 int
475 and_operand (op, mode)
476      register rtx op;
477      enum machine_mode mode;
478 {
479   if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == VOIDmode)
480     return (zap_mask (CONST_DOUBLE_LOW (op))
481             && zap_mask (CONST_DOUBLE_HIGH (op)));
482
483   if (GET_CODE (op) == CONST_INT)
484     return ((unsigned HOST_WIDE_INT) INTVAL (op) < 0x100
485             || (unsigned HOST_WIDE_INT) ~ INTVAL (op) < 0x100
486             || zap_mask (INTVAL (op)));
487
488   return register_operand (op, mode);
489 }
490
491 /* Return 1 if OP is a valid first operand to an IOR or XOR insn.  */
492
493 int
494 or_operand (op, mode)
495      register rtx op;
496      enum machine_mode mode;
497 {
498   if (GET_CODE (op) == CONST_INT)
499     return ((unsigned HOST_WIDE_INT) INTVAL (op) < 0x100
500             || (unsigned HOST_WIDE_INT) ~ INTVAL (op) < 0x100);
501
502   return register_operand (op, mode);
503 }
504
505 /* Return 1 if OP is a constant that is the width, in bits, of an integral
506    mode smaller than DImode.  */
507
508 int
509 mode_width_operand (op, mode)
510      register rtx op;
511      enum machine_mode mode ATTRIBUTE_UNUSED;
512 {
513   return (GET_CODE (op) == CONST_INT
514           && (INTVAL (op) == 8 || INTVAL (op) == 16
515               || INTVAL (op) == 32 || INTVAL (op) == 64));
516 }
517
518 /* Return 1 if OP is a constant that is the width of an integral machine mode
519    smaller than an integer.  */
520
521 int
522 mode_mask_operand (op, mode)
523      register rtx op;
524      enum machine_mode mode ATTRIBUTE_UNUSED;
525 {
526 #if HOST_BITS_PER_WIDE_INT == 32
527   if (GET_CODE (op) == CONST_DOUBLE)
528     return (CONST_DOUBLE_LOW (op) == -1
529             && (CONST_DOUBLE_HIGH (op) == -1
530                 || CONST_DOUBLE_HIGH (op) == 0));
531 #else
532   if (GET_CODE (op) == CONST_DOUBLE)
533     return (CONST_DOUBLE_LOW (op) == -1 && CONST_DOUBLE_HIGH (op) == 0);
534 #endif
535
536   return (GET_CODE (op) == CONST_INT
537           && (INTVAL (op) == 0xff
538               || INTVAL (op) == 0xffff
539               || INTVAL (op) == (HOST_WIDE_INT)0xffffffff
540 #if HOST_BITS_PER_WIDE_INT == 64
541               || INTVAL (op) == -1
542 #endif
543               ));
544 }
545
546 /* Return 1 if OP is a multiple of 8 less than 64.  */
547
548 int
549 mul8_operand (op, mode)
550      register rtx op;
551      enum machine_mode mode ATTRIBUTE_UNUSED;
552 {
553   return (GET_CODE (op) == CONST_INT
554           && (unsigned HOST_WIDE_INT) INTVAL (op) < 64
555           && (INTVAL (op) & 7) == 0);
556 }
557
558 /* Return 1 if OP is the constant zero in floating-point.  */
559
560 int
561 fp0_operand (op, mode)
562      register rtx op;
563      enum machine_mode mode;
564 {
565   return (GET_MODE (op) == mode
566           && GET_MODE_CLASS (mode) == MODE_FLOAT && op == CONST0_RTX (mode));
567 }
568
569 /* Return 1 if OP is the floating-point constant zero or a register.  */
570
571 int
572 reg_or_fp0_operand (op, mode)
573      register rtx op;
574      enum machine_mode mode;
575 {
576   return fp0_operand (op, mode) || register_operand (op, mode);
577 }
578
579 /* Return 1 if OP is a hard floating-point register.  */
580
581 int
582 hard_fp_register_operand (op, mode)
583      register rtx op;
584      enum machine_mode mode;
585 {
586   if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op))
587     return 0;
588
589   if (GET_CODE (op) == SUBREG)
590     op = SUBREG_REG (op);
591   return GET_CODE (op) == REG && REGNO_REG_CLASS (REGNO (op)) == FLOAT_REGS;
592 }
593
594 /* Return 1 if OP is a hard general register.  */
595
596 int
597 hard_int_register_operand (op, mode)
598      register rtx op;
599      enum machine_mode mode;
600 {
601   if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op))
602     return 0;
603
604   if (GET_CODE (op) == SUBREG)
605     op = SUBREG_REG (op);
606   return GET_CODE (op) == REG && REGNO_REG_CLASS (REGNO (op)) == GENERAL_REGS;
607 }
608
609 /* Return 1 if OP is a register or a constant integer.  */
610
611
612 int
613 reg_or_cint_operand (op, mode)
614     register rtx op;
615     enum machine_mode mode;
616 {
617      return (GET_CODE (op) == CONST_INT
618              || register_operand (op, mode));
619 }
620
621 /* Return 1 if OP is something that can be reloaded into a register;
622    if it is a MEM, it need not be valid.  */
623
624 int
625 some_operand (op, mode)
626      register rtx op;
627      enum machine_mode mode;
628 {
629   if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op))
630     return 0;
631
632   switch (GET_CODE (op))
633     {
634     case REG:  case MEM:  case CONST_DOUBLE:  case CONST_INT:  case LABEL_REF:
635     case SYMBOL_REF:  case CONST:
636       return 1;
637
638     case SUBREG:
639       return some_operand (SUBREG_REG (op), VOIDmode);
640
641     default:
642       break;
643     }
644
645   return 0;
646 }
647
648 /* Likewise, but don't accept constants.  */
649
650 int
651 some_ni_operand (op, mode)
652      register rtx op;
653      enum machine_mode mode;
654 {
655   if (GET_MODE (op) != mode && mode != VOIDmode)
656     return 0;
657
658   if (GET_CODE (op) == SUBREG)
659     op = SUBREG_REG (op);
660
661   return (GET_CODE (op) == REG || GET_CODE (op) == MEM);
662 }
663
664 /* Return 1 if OP is a valid operand for the source of a move insn.  */
665
666 int
667 input_operand (op, mode)
668      register rtx op;
669      enum machine_mode mode;
670 {
671   if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op))
672     return 0;
673
674   if (GET_MODE_CLASS (mode) == MODE_FLOAT && GET_MODE (op) != mode)
675     return 0;
676
677   switch (GET_CODE (op))
678     {
679     case LABEL_REF:
680     case SYMBOL_REF:
681     case CONST:
682       /* This handles both the Windows/NT and OSF cases.  */
683       return mode == ptr_mode || mode == DImode;
684
685     case REG:
686     case ADDRESSOF:
687       return 1;
688
689     case SUBREG:
690       if (register_operand (op, mode))
691         return 1;
692       /* ... fall through ... */
693     case MEM:
694       return ((TARGET_BWX || (mode != HImode && mode != QImode))
695               && general_operand (op, mode));
696
697     case CONST_DOUBLE:
698       return GET_MODE_CLASS (mode) == MODE_FLOAT && op == CONST0_RTX (mode);
699
700     case CONST_INT:
701       return mode == QImode || mode == HImode || add_operand (op, mode);
702
703     case CONSTANT_P_RTX:
704       return 1;
705
706     default:
707       break;
708     }
709
710   return 0;
711 }
712
713 /* Return 1 if OP is a SYMBOL_REF for a function known to be in this
714    file.  */
715
716 int
717 current_file_function_operand (op, mode)
718      rtx op;
719      enum machine_mode mode ATTRIBUTE_UNUSED;
720 {
721   return (GET_CODE (op) == SYMBOL_REF
722           && ! profile_flag && ! profile_block_flag
723           && (SYMBOL_REF_FLAG (op)
724               || op == XEXP (DECL_RTL (current_function_decl), 0)));
725 }
726
727 /* Return 1 if OP is a valid operand for the MEM of a CALL insn.  */
728
729 int
730 call_operand (op, mode)
731      rtx op;
732      enum machine_mode mode;
733 {
734   if (mode != Pmode)
735     return 0;
736
737   return (GET_CODE (op) == SYMBOL_REF
738           || (GET_CODE (op) == REG
739               && (TARGET_OPEN_VMS || TARGET_WINDOWS_NT || REGNO (op) == 27)));
740 }
741
742 /* Return 1 if OP is a valid Alpha comparison operator.  Here we know which
743    comparisons are valid in which insn.  */
744
745 int
746 alpha_comparison_operator (op, mode)
747      register rtx op;
748      enum machine_mode mode;
749 {
750   enum rtx_code code = GET_CODE (op);
751
752   if (mode != GET_MODE (op) && mode != VOIDmode)
753     return 0;
754
755   return (code == EQ || code == LE || code == LT
756           || code == LEU || code == LTU);
757 }
758
759 /* Return 1 if OP is a valid Alpha comparison operator against zero. 
760    Here we know which comparisons are valid in which insn.  */
761
762 int
763 alpha_zero_comparison_operator (op, mode)
764      register rtx op;
765      enum machine_mode mode;
766 {
767   enum rtx_code code = GET_CODE (op);
768
769   if (mode != GET_MODE (op) && mode != VOIDmode)
770     return 0;
771
772   return (code == EQ || code == NE || code == LE || code == LT
773           || code == LEU || code == LTU);
774 }
775
776 /* Return 1 if OP is a valid Alpha swapped comparison operator.  */
777
778 int
779 alpha_swapped_comparison_operator (op, mode)
780      register rtx op;
781      enum machine_mode mode;
782 {
783   enum rtx_code code = GET_CODE (op);
784
785   if ((mode != GET_MODE (op) && mode != VOIDmode)
786       || GET_RTX_CLASS (code) != '<')
787     return 0;
788
789   code = swap_condition (code);
790   return (code == EQ || code == LE || code == LT
791           || code == LEU || code == LTU);
792 }
793
794 /* Return 1 if OP is a signed comparison operation.  */
795
796 int
797 signed_comparison_operator (op, mode)
798      register rtx op;
799      enum machine_mode mode ATTRIBUTE_UNUSED;
800 {
801   enum rtx_code code = GET_CODE (op);
802
803   if (mode != GET_MODE (op) && mode != VOIDmode)
804     return 0;
805
806   return (code == EQ || code == NE
807           || code == LE || code == LT
808           || code == GE || code == GT);
809 }
810
811 /* Return 1 if OP is a valid Alpha floating point comparison operator.
812    Here we know which comparisons are valid in which insn.  */
813
814 int
815 alpha_fp_comparison_operator (op, mode)
816      register rtx op;
817      enum machine_mode mode;
818 {
819   enum rtx_code code = GET_CODE (op);
820
821   if (mode != GET_MODE (op) && mode != VOIDmode)
822     return 0;
823
824   return (code == EQ || code == LE || code == LT || code == UNORDERED);
825 }
826
827 /* Return 1 if this is a divide or modulus operator.  */
828
829 int
830 divmod_operator (op, mode)
831      register rtx op;
832      enum machine_mode mode ATTRIBUTE_UNUSED;
833 {
834   switch (GET_CODE (op))
835     {
836     case DIV:  case MOD:  case UDIV:  case UMOD:
837       return 1;
838
839     default:
840       break;
841     }
842
843   return 0;
844 }
845
846 /* Return 1 if this memory address is a known aligned register plus
847    a constant.  It must be a valid address.  This means that we can do
848    this as an aligned reference plus some offset.
849
850    Take into account what reload will do.  */
851
852 int
853 aligned_memory_operand (op, mode)
854      register rtx op;
855      enum machine_mode mode;
856 {
857   rtx base;
858
859   if (reload_in_progress)
860     {
861       rtx tmp = op;
862       if (GET_CODE (tmp) == SUBREG)
863         tmp = SUBREG_REG (tmp);
864       if (GET_CODE (tmp) == REG
865           && REGNO (tmp) >= FIRST_PSEUDO_REGISTER)
866         {
867           op = reg_equiv_memory_loc[REGNO (tmp)];
868           if (op == 0)
869             return 0;
870         }
871     }
872
873   if (GET_CODE (op) != MEM
874       || GET_MODE (op) != mode)
875     return 0;
876   op = XEXP (op, 0);
877
878   /* LEGITIMIZE_RELOAD_ADDRESS creates (plus (plus reg const_hi) const_lo)
879      sorts of constructs.  Dig for the real base register.  */
880   if (reload_in_progress
881       && GET_CODE (op) == PLUS
882       && GET_CODE (XEXP (op, 0)) == PLUS)
883     base = XEXP (XEXP (op, 0), 0);
884   else
885     {
886       if (! memory_address_p (mode, op))
887         return 0;
888       base = (GET_CODE (op) == PLUS ? XEXP (op, 0) : op);
889     }
890
891   return (GET_CODE (base) == REG && REGNO_POINTER_ALIGN (REGNO (base)) >= 32);
892 }
893
894 /* Similar, but return 1 if OP is a MEM which is not alignable.  */
895
896 int
897 unaligned_memory_operand (op, mode)
898      register rtx op;
899      enum machine_mode mode;
900 {
901   rtx base;
902
903   if (reload_in_progress)
904     {
905       rtx tmp = op;
906       if (GET_CODE (tmp) == SUBREG)
907         tmp = SUBREG_REG (tmp);
908       if (GET_CODE (tmp) == REG
909           && REGNO (tmp) >= FIRST_PSEUDO_REGISTER)
910         {
911           op = reg_equiv_memory_loc[REGNO (tmp)];
912           if (op == 0)
913             return 0;
914         }
915     }
916
917   if (GET_CODE (op) != MEM
918       || GET_MODE (op) != mode)
919     return 0;
920   op = XEXP (op, 0);
921
922   /* LEGITIMIZE_RELOAD_ADDRESS creates (plus (plus reg const_hi) const_lo)
923      sorts of constructs.  Dig for the real base register.  */
924   if (reload_in_progress
925       && GET_CODE (op) == PLUS
926       && GET_CODE (XEXP (op, 0)) == PLUS)
927     base = XEXP (XEXP (op, 0), 0);
928   else
929     {
930       if (! memory_address_p (mode, op))
931         return 0;
932       base = (GET_CODE (op) == PLUS ? XEXP (op, 0) : op);
933     }
934
935   return (GET_CODE (base) == REG && REGNO_POINTER_ALIGN (REGNO (base)) < 32);
936 }
937
938 /* Return 1 if OP is either a register or an unaligned memory location.  */
939
940 int
941 reg_or_unaligned_mem_operand (op, mode)
942      rtx op;
943      enum machine_mode mode;
944 {
945   return register_operand (op, mode) || unaligned_memory_operand (op, mode);
946 }
947
948 /* Return 1 if OP is any memory location.  During reload a pseudo matches.  */
949
950 int
951 any_memory_operand (op, mode)
952      register rtx op;
953      enum machine_mode mode ATTRIBUTE_UNUSED;
954 {
955   return (GET_CODE (op) == MEM
956           || (GET_CODE (op) == SUBREG && GET_CODE (SUBREG_REG (op)) == REG)
957           || (reload_in_progress && GET_CODE (op) == REG
958               && REGNO (op) >= FIRST_PSEUDO_REGISTER)
959           || (reload_in_progress && GET_CODE (op) == SUBREG
960               && GET_CODE (SUBREG_REG (op)) == REG
961               && REGNO (SUBREG_REG (op)) >= FIRST_PSEUDO_REGISTER));
962 }
963
964 /* Returns 1 if OP is not an eliminable register.
965
966    This exists to cure a pathological abort in the s8addq (et al) patterns,
967
968         long foo () { long t; bar(); return (long) &t * 26107; }
969
970    which run afoul of a hack in reload to cure a (presumably) similar
971    problem with lea-type instructions on other targets.  But there is
972    one of us and many of them, so work around the problem by selectively
973    preventing combine from making the optimization.  */
974
975 int
976 reg_not_elim_operand (op, mode)
977       register rtx op;
978       enum machine_mode mode;
979 {
980   rtx inner = op;
981   if (GET_CODE (op) == SUBREG)
982     inner = SUBREG_REG (op);
983   if (inner == frame_pointer_rtx || inner == arg_pointer_rtx)
984     return 0;
985
986   return register_operand (op, mode);
987 }
988
989 /* Return 1 is OP is a memory location that is not a reference (using
990    an AND) to an unaligned location.  Take into account what reload
991    will do.  */
992
993 int
994 normal_memory_operand (op, mode)
995      register rtx op;
996      enum machine_mode mode ATTRIBUTE_UNUSED;
997 {
998   if (reload_in_progress)
999     {
1000       rtx tmp = op;
1001       if (GET_CODE (tmp) == SUBREG)
1002         tmp = SUBREG_REG (tmp);
1003       if (GET_CODE (tmp) == REG
1004           && REGNO (tmp) >= FIRST_PSEUDO_REGISTER)
1005         {
1006           op = reg_equiv_memory_loc[REGNO (tmp)];
1007
1008           /* This may not have been assigned an equivalent address if it will
1009              be eliminated.  In that case, it doesn't matter what we do.  */
1010           if (op == 0)
1011             return 1;
1012         }
1013     }
1014
1015   return GET_CODE (op) == MEM && GET_CODE (XEXP (op, 0)) != AND;
1016 }
1017
1018 /* Accept a register, but not a subreg of any kind.  This allows us to
1019    avoid pathological cases in reload wrt data movement common in 
1020    int->fp conversion.  */
1021
1022 int
1023 reg_no_subreg_operand (op, mode)
1024      register rtx op;
1025      enum machine_mode mode;
1026 {
1027   if (GET_CODE (op) == SUBREG)
1028     return 0;
1029   return register_operand (op, mode);
1030 }
1031
1032 /* Recognize a addition operation that includes a constant.  Used to
1033    convince reload to canonize (plus (plus reg c1) c2) during register
1034    elimination.  */
1035
1036 int
1037 addition_operation (op, mode)
1038      register rtx op;
1039      enum machine_mode mode;
1040 {
1041   if (GET_MODE (op) != mode && mode != VOIDmode)
1042     return 0;
1043   if (GET_CODE (op) == PLUS
1044       && register_operand (XEXP (op, 0), mode)
1045       && GET_CODE (XEXP (op, 1)) == CONST_INT
1046       && CONST_OK_FOR_LETTER_P (INTVAL (XEXP (op, 1)), 'K'))
1047     return 1;
1048   return 0;
1049 }
1050
1051 /* Return 1 if this function can directly return via $26.  */
1052
1053 int
1054 direct_return ()
1055 {
1056   return (! TARGET_OPEN_VMS && reload_completed && alpha_sa_size () == 0
1057           && get_frame_size () == 0
1058           && current_function_outgoing_args_size == 0
1059           && current_function_pretend_args_size == 0);
1060 }
1061 \f
1062 /* REF is an alignable memory location.  Place an aligned SImode
1063    reference into *PALIGNED_MEM and the number of bits to shift into
1064    *PBITNUM.  SCRATCH is a free register for use in reloading out
1065    of range stack slots.  */
1066
1067 void
1068 get_aligned_mem (ref, paligned_mem, pbitnum)
1069      rtx ref;
1070      rtx *paligned_mem, *pbitnum;
1071 {
1072   rtx base;
1073   HOST_WIDE_INT offset = 0;
1074
1075   if (GET_CODE (ref) != MEM)
1076     abort ();
1077
1078   if (reload_in_progress
1079       && ! memory_address_p (GET_MODE (ref), XEXP (ref, 0)))
1080     {
1081       base = find_replacement (&XEXP (ref, 0));
1082
1083       if (! memory_address_p (GET_MODE (ref), base))
1084         abort ();
1085     }
1086   else
1087     {
1088       base = XEXP (ref, 0);
1089     }
1090
1091   if (GET_CODE (base) == PLUS)
1092     offset += INTVAL (XEXP (base, 1)), base = XEXP (base, 0);
1093
1094   *paligned_mem = gen_rtx_MEM (SImode, plus_constant (base, offset & ~3));
1095   MEM_COPY_ATTRIBUTES (*paligned_mem, ref);
1096
1097   /* Sadly, we cannot use alias sets here because we may overlap other
1098      data in a different alias set.  */
1099   MEM_ALIAS_SET (*paligned_mem) = 0;
1100
1101   *pbitnum = GEN_INT ((offset & 3) * 8);
1102 }
1103
1104 /* Similar, but just get the address.  Handle the two reload cases.  
1105    Add EXTRA_OFFSET to the address we return.  */
1106
1107 rtx
1108 get_unaligned_address (ref, extra_offset)
1109      rtx ref;
1110      int extra_offset;
1111 {
1112   rtx base;
1113   HOST_WIDE_INT offset = 0;
1114
1115   if (GET_CODE (ref) != MEM)
1116     abort ();
1117
1118   if (reload_in_progress
1119       && ! memory_address_p (GET_MODE (ref), XEXP (ref, 0)))
1120     {
1121       base = find_replacement (&XEXP (ref, 0));
1122
1123       if (! memory_address_p (GET_MODE (ref), base))
1124         abort ();
1125     }
1126   else
1127     {
1128       base = XEXP (ref, 0);
1129     }
1130
1131   if (GET_CODE (base) == PLUS)
1132     offset += INTVAL (XEXP (base, 1)), base = XEXP (base, 0);
1133
1134   return plus_constant (base, offset + extra_offset);
1135 }
1136
1137 /* Loading and storing HImode or QImode values to and from memory
1138    usually requires a scratch register.  The exceptions are loading
1139    QImode and HImode from an aligned address to a general register
1140    unless byte instructions are permitted. 
1141
1142    We also cannot load an unaligned address or a paradoxical SUBREG
1143    into an FP register. 
1144
1145    We also cannot do integral arithmetic into FP regs, as might result
1146    from register elimination into a DImode fp register.  */
1147
1148 enum reg_class
1149 secondary_reload_class (class, mode, x, in)
1150      enum reg_class class;
1151      enum machine_mode mode;
1152      rtx x;
1153      int in;
1154 {
1155   if ((mode == QImode || mode == HImode) && ! TARGET_BWX)
1156     {
1157       if (GET_CODE (x) == MEM
1158           || (GET_CODE (x) == REG && REGNO (x) >= FIRST_PSEUDO_REGISTER)
1159           || (GET_CODE (x) == SUBREG
1160               && (GET_CODE (SUBREG_REG (x)) == MEM
1161                   || (GET_CODE (SUBREG_REG (x)) == REG
1162                       && REGNO (SUBREG_REG (x)) >= FIRST_PSEUDO_REGISTER))))
1163         {
1164           if (!in || !aligned_memory_operand(x, mode))
1165             return GENERAL_REGS;
1166         }
1167     }
1168
1169   if (class == FLOAT_REGS)
1170     {
1171       if (GET_CODE (x) == MEM && GET_CODE (XEXP (x, 0)) == AND)
1172         return GENERAL_REGS;
1173
1174       if (GET_CODE (x) == SUBREG
1175           && (GET_MODE_SIZE (GET_MODE (x))
1176               > GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))))
1177         return GENERAL_REGS;
1178
1179       if (in && INTEGRAL_MODE_P (mode) && ! general_operand (x, mode))
1180         return GENERAL_REGS;
1181     }
1182
1183   return NO_REGS;
1184 }
1185 \f
1186 /* Subfunction of the following function.  Update the flags of any MEM
1187    found in part of X.  */
1188
1189 static void
1190 alpha_set_memflags_1 (x, in_struct_p, volatile_p, unchanging_p)
1191      rtx x;
1192      int in_struct_p, volatile_p, unchanging_p;
1193 {
1194   int i;
1195
1196   switch (GET_CODE (x))
1197     {
1198     case SEQUENCE:
1199     case PARALLEL:
1200       for (i = XVECLEN (x, 0) - 1; i >= 0; i--)
1201         alpha_set_memflags_1 (XVECEXP (x, 0, i), in_struct_p, volatile_p,
1202                               unchanging_p);
1203       break;
1204
1205     case INSN:
1206       alpha_set_memflags_1 (PATTERN (x), in_struct_p, volatile_p,
1207                             unchanging_p);
1208       break;
1209
1210     case SET:
1211       alpha_set_memflags_1 (SET_DEST (x), in_struct_p, volatile_p,
1212                             unchanging_p);
1213       alpha_set_memflags_1 (SET_SRC (x), in_struct_p, volatile_p,
1214                             unchanging_p);
1215       break;
1216
1217     case MEM:
1218       MEM_IN_STRUCT_P (x) = in_struct_p;
1219       MEM_VOLATILE_P (x) = volatile_p;
1220       RTX_UNCHANGING_P (x) = unchanging_p;
1221       /* Sadly, we cannot use alias sets because the extra aliasing
1222          produced by the AND interferes.  Given that two-byte quantities
1223          are the only thing we would be able to differentiate anyway,
1224          there does not seem to be any point in convoluting the early
1225          out of the alias check.  */
1226       /* MEM_ALIAS_SET (x) = alias_set; */
1227       break;
1228
1229     default:
1230       break;
1231     }
1232 }
1233
1234 /* Given INSN, which is either an INSN or a SEQUENCE generated to
1235    perform a memory operation, look for any MEMs in either a SET_DEST or
1236    a SET_SRC and copy the in-struct, unchanging, and volatile flags from
1237    REF into each of the MEMs found.  If REF is not a MEM, don't do
1238    anything.  */
1239
1240 void
1241 alpha_set_memflags (insn, ref)
1242      rtx insn;
1243      rtx ref;
1244 {
1245   int in_struct_p, volatile_p, unchanging_p;
1246
1247   if (GET_CODE (ref) != MEM)
1248     return;
1249
1250   in_struct_p = MEM_IN_STRUCT_P (ref);
1251   volatile_p = MEM_VOLATILE_P (ref);
1252   unchanging_p = RTX_UNCHANGING_P (ref);
1253
1254   /* This is only called from alpha.md, after having had something 
1255      generated from one of the insn patterns.  So if everything is
1256      zero, the pattern is already up-to-date.  */
1257   if (! in_struct_p && ! volatile_p && ! unchanging_p)
1258     return;
1259
1260   alpha_set_memflags_1 (insn, in_struct_p, volatile_p, unchanging_p);
1261 }
1262 \f
1263 /* Try to output insns to set TARGET equal to the constant C if it can be
1264    done in less than N insns.  Do all computations in MODE.  Returns the place
1265    where the output has been placed if it can be done and the insns have been
1266    emitted.  If it would take more than N insns, zero is returned and no
1267    insns and emitted.  */
1268
1269 rtx
1270 alpha_emit_set_const (target, mode, c, n)
1271      rtx target;
1272      enum machine_mode mode;
1273      HOST_WIDE_INT c;
1274      int n;
1275 {
1276   rtx pat;
1277   int i;
1278
1279   /* Try 1 insn, then 2, then up to N. */
1280   for (i = 1; i <= n; i++)
1281     if ((pat = alpha_emit_set_const_1 (target, mode, c, i)) != 0)
1282       return pat;
1283
1284   return 0;
1285 }
1286
1287 /* Internal routine for the above to check for N or below insns.  */
1288
1289 static rtx
1290 alpha_emit_set_const_1 (target, mode, c, n)
1291      rtx target;
1292      enum machine_mode mode;
1293      HOST_WIDE_INT c;
1294      int n;
1295 {
1296   HOST_WIDE_INT new;
1297   int i, bits;
1298   /* Use a pseudo if highly optimizing and still generating RTL.  */
1299   rtx subtarget
1300     = (flag_expensive_optimizations && rtx_equal_function_value_matters
1301        ? 0 : target);
1302   rtx temp;
1303
1304 #if HOST_BITS_PER_WIDE_INT == 64
1305   /* We are only called for SImode and DImode.  If this is SImode, ensure that
1306      we are sign extended to a full word.  This does not make any sense when
1307      cross-compiling on a narrow machine.  */
1308
1309   if (mode == SImode)
1310     c = ((c & 0xffffffff) ^ 0x80000000) - 0x80000000;
1311 #endif
1312
1313   /* If this is a sign-extended 32-bit constant, we can do this in at most
1314      three insns, so do it if we have enough insns left.  We always have
1315      a sign-extended 32-bit constant when compiling on a narrow machine.   */
1316
1317   if (HOST_BITS_PER_WIDE_INT != 64
1318       || c >> 31 == -1 || c >> 31 == 0)
1319     {
1320       HOST_WIDE_INT low = ((c & 0xffff) ^ 0x8000) - 0x8000;
1321       HOST_WIDE_INT tmp1 = c - low;
1322       HOST_WIDE_INT high = (((tmp1 >> 16) & 0xffff) ^ 0x8000) - 0x8000;
1323       HOST_WIDE_INT extra = 0;
1324
1325       /* If HIGH will be interpreted as negative but the constant is
1326          positive, we must adjust it to do two ldha insns.  */
1327
1328       if ((high & 0x8000) != 0 && c >= 0)
1329         {
1330           extra = 0x4000;
1331           tmp1 -= 0x40000000;
1332           high = ((tmp1 >> 16) & 0xffff) - 2 * ((tmp1 >> 16) & 0x8000);
1333         }
1334
1335       if (c == low || (low == 0 && extra == 0))
1336         {
1337           /* We used to use copy_to_suggested_reg (GEN_INT (c), target, mode)
1338              but that meant that we can't handle INT_MIN on 32-bit machines
1339              (like NT/Alpha), because we recurse indefinitely through 
1340              emit_move_insn to gen_movdi.  So instead, since we know exactly
1341              what we want, create it explicitly.  */
1342
1343           if (target == NULL)
1344             target = gen_reg_rtx (mode);
1345           emit_insn (gen_rtx_SET (VOIDmode, target, GEN_INT (c)));
1346           return target;
1347         }
1348       else if (n >= 2 + (extra != 0))
1349         {
1350           temp = copy_to_suggested_reg (GEN_INT (high << 16), subtarget, mode);
1351
1352           if (extra != 0)
1353             temp = expand_binop (mode, add_optab, temp, GEN_INT (extra << 16),
1354                                  subtarget, 0, OPTAB_WIDEN);
1355
1356           return expand_binop (mode, add_optab, temp, GEN_INT (low),
1357                                target, 0, OPTAB_WIDEN);
1358         }
1359     }
1360
1361   /* If we couldn't do it that way, try some other methods.  But if we have
1362      no instructions left, don't bother.  Likewise, if this is SImode and
1363      we can't make pseudos, we can't do anything since the expand_binop
1364      and expand_unop calls will widen and try to make pseudos.  */
1365
1366   if (n == 1
1367       || (mode == SImode && ! rtx_equal_function_value_matters))
1368     return 0;
1369
1370   /* Next, see if we can load a related constant and then shift and possibly
1371      negate it to get the constant we want.  Try this once each increasing
1372      numbers of insns.  */
1373
1374   for (i = 1; i < n; i++)
1375     {
1376       /* First, see if minus some low bits, we've an easy load of
1377          high bits.  */
1378
1379       new = ((c & 0xffff) ^ 0x8000) - 0x8000;
1380       if (new != 0
1381           && (temp = alpha_emit_set_const (subtarget, mode, c - new, i)) != 0)
1382         return expand_binop (mode, add_optab, temp, GEN_INT (new),
1383                              target, 0, OPTAB_WIDEN);
1384
1385       /* Next try complementing.  */
1386       if ((temp = alpha_emit_set_const (subtarget, mode, ~ c, i)) != 0)
1387         return expand_unop (mode, one_cmpl_optab, temp, target, 0);
1388
1389       /* Next try to form a constant and do a left shift.  We can do this
1390          if some low-order bits are zero; the exact_log2 call below tells
1391          us that information.  The bits we are shifting out could be any
1392          value, but here we'll just try the 0- and sign-extended forms of
1393          the constant.  To try to increase the chance of having the same
1394          constant in more than one insn, start at the highest number of
1395          bits to shift, but try all possibilities in case a ZAPNOT will
1396          be useful.  */
1397
1398       if ((bits = exact_log2 (c & - c)) > 0)
1399         for (; bits > 0; bits--)
1400           if ((temp = (alpha_emit_set_const
1401                        (subtarget, mode, c >> bits, i))) != 0
1402               || ((temp = (alpha_emit_set_const
1403                           (subtarget, mode,
1404                            ((unsigned HOST_WIDE_INT) c) >> bits, i)))
1405                   != 0))
1406             return expand_binop (mode, ashl_optab, temp, GEN_INT (bits),
1407                                  target, 0, OPTAB_WIDEN);
1408
1409       /* Now try high-order zero bits.  Here we try the shifted-in bits as
1410          all zero and all ones.  Be careful to avoid shifting outside the
1411          mode and to avoid shifting outside the host wide int size.  */
1412       /* On narrow hosts, don't shift a 1 into the high bit, since we'll
1413          confuse the recursive call and set all of the high 32 bits.  */
1414
1415       if ((bits = (MIN (HOST_BITS_PER_WIDE_INT, GET_MODE_SIZE (mode) * 8)
1416                    - floor_log2 (c) - 1 - (HOST_BITS_PER_WIDE_INT < 64))) > 0)
1417         for (; bits > 0; bits--)
1418           if ((temp = alpha_emit_set_const (subtarget, mode,
1419                                             c << bits, i)) != 0
1420               || ((temp = (alpha_emit_set_const
1421                            (subtarget, mode,
1422                             ((c << bits) | (((HOST_WIDE_INT) 1 << bits) - 1)),
1423                             i)))
1424                   != 0))
1425             return expand_binop (mode, lshr_optab, temp, GEN_INT (bits),
1426                                  target, 1, OPTAB_WIDEN);
1427
1428       /* Now try high-order 1 bits.  We get that with a sign-extension.
1429          But one bit isn't enough here.  Be careful to avoid shifting outside
1430          the mode and to avoid shifting outside the host wide int size. */
1431       
1432       if ((bits = (MIN (HOST_BITS_PER_WIDE_INT, GET_MODE_SIZE (mode) * 8)
1433                    - floor_log2 (~ c) - 2)) > 0)
1434         for (; bits > 0; bits--)
1435           if ((temp = alpha_emit_set_const (subtarget, mode,
1436                                             c << bits, i)) != 0
1437               || ((temp = (alpha_emit_set_const
1438                            (subtarget, mode,
1439                             ((c << bits) | (((HOST_WIDE_INT) 1 << bits) - 1)),
1440                             i)))
1441                   != 0))
1442             return expand_binop (mode, ashr_optab, temp, GEN_INT (bits),
1443                                  target, 0, OPTAB_WIDEN);
1444     }
1445
1446 #if HOST_BITS_PER_WIDE_INT == 64
1447   /* Finally, see if can load a value into the target that is the same as the
1448      constant except that all bytes that are 0 are changed to be 0xff.  If we
1449      can, then we can do a ZAPNOT to obtain the desired constant.  */
1450
1451   new = c;
1452   for (i = 0; i < 64; i += 8)
1453     if ((new & ((HOST_WIDE_INT) 0xff << i)) == 0)
1454       new |= (HOST_WIDE_INT) 0xff << i;
1455
1456   /* We are only called for SImode and DImode.  If this is SImode, ensure that
1457      we are sign extended to a full word.  */
1458
1459   if (mode == SImode)
1460     new = ((new & 0xffffffff) ^ 0x80000000) - 0x80000000;
1461
1462   if (new != c && new != -1
1463       && (temp = alpha_emit_set_const (subtarget, mode, new, n - 1)) != 0)
1464     return expand_binop (mode, and_optab, temp, GEN_INT (c | ~ new),
1465                          target, 0, OPTAB_WIDEN);
1466 #endif
1467
1468   return 0;
1469 }
1470
1471 /* Having failed to find a 3 insn sequence in alpha_emit_set_const,
1472    fall back to a straight forward decomposition.  We do this to avoid
1473    exponential run times encountered when looking for longer sequences
1474    with alpha_emit_set_const.  */
1475
1476 rtx
1477 alpha_emit_set_long_const (target, c1, c2)
1478      rtx target;
1479      HOST_WIDE_INT c1, c2;
1480 {
1481   HOST_WIDE_INT d1, d2, d3, d4;
1482
1483   /* Decompose the entire word */
1484 #if HOST_BITS_PER_WIDE_INT >= 64
1485   if (c2 != -(c1 < 0))
1486     abort ();
1487   d1 = ((c1 & 0xffff) ^ 0x8000) - 0x8000;
1488   c1 -= d1;
1489   d2 = ((c1 & 0xffffffff) ^ 0x80000000) - 0x80000000;
1490   c1 = (c1 - d2) >> 32;
1491   d3 = ((c1 & 0xffff) ^ 0x8000) - 0x8000;
1492   c1 -= d3;
1493   d4 = ((c1 & 0xffffffff) ^ 0x80000000) - 0x80000000;
1494   if (c1 != d4)
1495     abort ();
1496 #else
1497   d1 = ((c1 & 0xffff) ^ 0x8000) - 0x8000;
1498   c1 -= d1;
1499   d2 = ((c1 & 0xffffffff) ^ 0x80000000) - 0x80000000;
1500   if (c1 != d2)
1501     abort ();
1502   c2 += (d2 < 0);
1503   d3 = ((c2 & 0xffff) ^ 0x8000) - 0x8000;
1504   c2 -= d3;
1505   d4 = ((c2 & 0xffffffff) ^ 0x80000000) - 0x80000000;
1506   if (c2 != d4)
1507     abort ();
1508 #endif
1509
1510   /* Construct the high word */
1511   if (d4)
1512     {
1513       emit_move_insn (target, GEN_INT (d4));
1514       if (d3)
1515         emit_move_insn (target, gen_rtx_PLUS (DImode, target, GEN_INT (d3)));
1516     }
1517   else
1518     emit_move_insn (target, GEN_INT (d3));
1519
1520   /* Shift it into place */
1521   emit_move_insn (target, gen_rtx_ASHIFT (DImode, target, GEN_INT (32)));
1522
1523   /* Add in the low bits.  */
1524   if (d2)
1525     emit_move_insn (target, gen_rtx_PLUS (DImode, target, GEN_INT (d2)));
1526   if (d1)
1527     emit_move_insn (target, gen_rtx_PLUS (DImode, target, GEN_INT (d1)));
1528
1529   return target;
1530 }
1531
1532 /* Generate an unsigned DImode to FP conversion.  This is the same code
1533    optabs would emit if we didn't have TFmode patterns.
1534
1535    For SFmode, this is the only construction I've found that can pass
1536    gcc.c-torture/execute/ieee/rbug.c.  No scenario that uses DFmode
1537    intermediates will work, because you'll get intermediate rounding
1538    that ruins the end result.  Some of this could be fixed by turning
1539    on round-to-positive-infinity, but that requires diddling the fpsr,
1540    which kills performance.  I tried turning this around and converting
1541    to a negative number, so that I could turn on /m, but either I did
1542    it wrong or there's something else cause I wound up with the exact
1543    same single-bit error.  There is a branch-less form of this same code:
1544
1545         srl     $16,1,$1
1546         and     $16,1,$2
1547         cmplt   $16,0,$3
1548         or      $1,$2,$2
1549         cmovge  $16,$16,$2
1550         itoft   $3,$f10
1551         itoft   $2,$f11
1552         cvtqs   $f11,$f11
1553         adds    $f11,$f11,$f0
1554         fcmoveq $f10,$f11,$f0
1555
1556    I'm not using it because it's the same number of instructions as
1557    this branch-full form, and it has more serialized long latency
1558    instructions on the critical path.
1559
1560    For DFmode, we can avoid rounding errors by breaking up the word
1561    into two pieces, converting them separately, and adding them back:
1562
1563    LC0: .long 0,0x5f800000
1564
1565         itoft   $16,$f11
1566         lda     $2,LC0
1567         cmplt   $16,0,$1
1568         cpyse   $f11,$f31,$f10
1569         cpyse   $f31,$f11,$f11
1570         s4addq  $1,$2,$1
1571         lds     $f12,0($1)
1572         cvtqt   $f10,$f10
1573         cvtqt   $f11,$f11
1574         addt    $f12,$f10,$f0
1575         addt    $f0,$f11,$f0
1576
1577    This doesn't seem to be a clear-cut win over the optabs form.
1578    It probably all depends on the distribution of numbers being
1579    converted -- in the optabs form, all but high-bit-set has a
1580    much lower minimum execution time.  */
1581
1582 void
1583 alpha_emit_floatuns (operands)
1584      rtx operands[2];
1585 {
1586   rtx neglab, donelab, i0, i1, f0, in, out;
1587   enum machine_mode mode;
1588
1589   out = operands[0];
1590   in = force_reg (DImode, operands[1]);
1591   mode = GET_MODE (out);
1592   neglab = gen_label_rtx ();
1593   donelab = gen_label_rtx ();
1594   i0 = gen_reg_rtx (DImode);
1595   i1 = gen_reg_rtx (DImode);
1596   f0 = gen_reg_rtx (mode);
1597
1598   emit_cmp_and_jump_insns (in, const0_rtx, LT, const0_rtx, DImode, 0,
1599                            8, neglab);
1600
1601   emit_insn (gen_rtx_SET (VOIDmode, out, gen_rtx_FLOAT (mode, in)));
1602   emit_jump_insn (gen_jump (donelab));
1603   emit_barrier ();
1604
1605   emit_label (neglab);
1606
1607   emit_insn (gen_lshrdi3 (i0, in, const1_rtx));
1608   emit_insn (gen_anddi3 (i1, in, const1_rtx));
1609   emit_insn (gen_iordi3 (i0, i0, i1));
1610   emit_insn (gen_rtx_SET (VOIDmode, f0, gen_rtx_FLOAT (mode, i0)));
1611   emit_insn (gen_rtx_SET (VOIDmode, out, gen_rtx_PLUS (mode, f0, f0)));
1612
1613   emit_label (donelab);
1614 }
1615
1616 /* Generate the comparison for a conditional branch.  */
1617
1618 rtx
1619 alpha_emit_conditional_branch (code)
1620      enum rtx_code code;
1621 {
1622   enum rtx_code cmp_code, branch_code;
1623   enum machine_mode cmp_mode, branch_mode = VOIDmode;
1624   rtx op0 = alpha_compare.op0, op1 = alpha_compare.op1;
1625   rtx tem;
1626
1627   if (alpha_compare.fp_p && GET_MODE (op0) == TFmode)
1628     {
1629       if (! TARGET_HAS_XFLOATING_LIBS)
1630         abort ();
1631
1632       /* X_floating library comparison functions return
1633            -1  unordered
1634             0  false
1635             1  true
1636          Convert the compare against the raw return value.  */
1637
1638       if (code == UNORDERED || code == ORDERED)
1639         cmp_code = EQ;
1640       else
1641         cmp_code = code;
1642
1643       op0 = alpha_emit_xfloating_compare (cmp_code, op0, op1);
1644       op1 = const0_rtx;
1645       alpha_compare.fp_p = 0;
1646
1647       if (code == UNORDERED)
1648         code = LT;
1649       else if (code == ORDERED)
1650         code = GE;
1651       else
1652         code = GT;
1653     }
1654
1655   /* The general case: fold the comparison code to the types of compares
1656      that we have, choosing the branch as necessary.  */
1657   switch (code)
1658     {
1659     case EQ:  case LE:  case LT:  case LEU:  case LTU:
1660     case UNORDERED:
1661       /* We have these compares: */
1662       cmp_code = code, branch_code = NE;
1663       break;
1664
1665     case NE:
1666     case ORDERED:
1667       /* These must be reversed. */
1668       cmp_code = reverse_condition (code), branch_code = EQ;
1669       break;
1670
1671     case GE:  case GT: case GEU:  case GTU:
1672       /* For FP, we swap them, for INT, we reverse them.  */
1673       if (alpha_compare.fp_p)
1674         {
1675           cmp_code = swap_condition (code);
1676           branch_code = NE;
1677           tem = op0, op0 = op1, op1 = tem;
1678         }
1679       else
1680         {
1681           cmp_code = reverse_condition (code);
1682           branch_code = EQ;
1683         }
1684       break;
1685
1686     default:
1687       abort ();
1688     }
1689
1690   if (alpha_compare.fp_p)
1691     {
1692       cmp_mode = DFmode;
1693       if (flag_unsafe_math_optimizations)
1694         {
1695           /* When we are not as concerned about non-finite values, and we
1696              are comparing against zero, we can branch directly.  */
1697           if (op1 == CONST0_RTX (DFmode))
1698             cmp_code = NIL, branch_code = code;
1699           else if (op0 == CONST0_RTX (DFmode))
1700             {
1701               /* Undo the swap we probably did just above.  */
1702               tem = op0, op0 = op1, op1 = tem;
1703               branch_code = swap_condition (cmp_code);
1704               cmp_code = NIL;
1705             }
1706         }
1707       else
1708         {
1709           /* ??? We mark the the branch mode to be CCmode to prevent the
1710              compare and branch from being combined, since the compare 
1711              insn follows IEEE rules that the branch does not.  */
1712           branch_mode = CCmode;
1713         }
1714     }
1715   else
1716     {
1717       cmp_mode = DImode;
1718
1719       /* The following optimizations are only for signed compares.  */
1720       if (code != LEU && code != LTU && code != GEU && code != GTU)
1721         {
1722           /* Whee.  Compare and branch against 0 directly.  */
1723           if (op1 == const0_rtx)
1724             cmp_code = NIL, branch_code = code;
1725
1726           /* We want to use cmpcc/bcc when we can, since there is a zero delay
1727              bypass between logicals and br/cmov on EV5.  But we don't want to
1728              force valid immediate constants into registers needlessly.  */
1729           else if (GET_CODE (op1) == CONST_INT)
1730             {
1731               HOST_WIDE_INT v = INTVAL (op1), n = -v;
1732
1733               if (! CONST_OK_FOR_LETTER_P (v, 'I')
1734                   && (CONST_OK_FOR_LETTER_P (n, 'K')
1735                       || CONST_OK_FOR_LETTER_P (n, 'L')))
1736                 {
1737                   cmp_code = PLUS, branch_code = code;
1738                   op1 = GEN_INT (n);
1739                 }
1740             }
1741         }
1742
1743       if (!reg_or_0_operand (op0, DImode))
1744         op0 = force_reg (DImode, op0);
1745       if (cmp_code != PLUS && !reg_or_8bit_operand (op1, DImode))
1746         op1 = force_reg (DImode, op1);
1747     }
1748
1749   /* Emit an initial compare instruction, if necessary.  */
1750   tem = op0;
1751   if (cmp_code != NIL)
1752     {
1753       tem = gen_reg_rtx (cmp_mode);
1754       emit_move_insn (tem, gen_rtx_fmt_ee (cmp_code, cmp_mode, op0, op1));
1755     }
1756
1757   /* Zero the operands.  */
1758   memset (&alpha_compare, 0, sizeof (alpha_compare));
1759
1760   /* Return the branch comparison.  */
1761   return gen_rtx_fmt_ee (branch_code, branch_mode, tem, CONST0_RTX (cmp_mode));
1762 }
1763
1764 /* Certain simplifications can be done to make invalid setcc operations
1765    valid.  Return the final comparison, or NULL if we can't work.  */
1766
1767 rtx
1768 alpha_emit_setcc (code)
1769      enum rtx_code code;
1770 {
1771   enum rtx_code cmp_code;
1772   rtx op0 = alpha_compare.op0, op1 = alpha_compare.op1;
1773   int fp_p = alpha_compare.fp_p;
1774   rtx tmp;
1775
1776   /* Zero the operands.  */
1777   memset (&alpha_compare, 0, sizeof (alpha_compare));
1778
1779   if (fp_p && GET_MODE (op0) == TFmode)
1780     {
1781       if (! TARGET_HAS_XFLOATING_LIBS)
1782         abort ();
1783
1784       /* X_floating library comparison functions return
1785            -1  unordered
1786             0  false
1787             1  true
1788          Convert the compare against the raw return value.  */
1789
1790       if (code == UNORDERED || code == ORDERED)
1791         cmp_code = EQ;
1792       else
1793         cmp_code = code;
1794
1795       op0 = alpha_emit_xfloating_compare (cmp_code, op0, op1);
1796       op1 = const0_rtx;
1797       fp_p = 0;
1798
1799       if (code == UNORDERED)
1800         code = LT;
1801       else if (code == ORDERED)
1802         code = GE;
1803       else
1804         code = GT;
1805     }
1806
1807   if (fp_p && !TARGET_FIX)
1808     return NULL_RTX;
1809
1810   /* The general case: fold the comparison code to the types of compares
1811      that we have, choosing the branch as necessary.  */
1812
1813   cmp_code = NIL;
1814   switch (code)
1815     {
1816     case EQ:  case LE:  case LT:  case LEU:  case LTU:
1817     case UNORDERED:
1818       /* We have these compares.  */
1819       if (fp_p)
1820         cmp_code = code, code = NE;
1821       break;
1822
1823     case NE:
1824       if (!fp_p && op1 == const0_rtx)
1825         break;
1826       /* FALLTHRU */
1827
1828     case ORDERED:
1829       cmp_code = reverse_condition (code);
1830       code = EQ;
1831       break;
1832
1833     case GE:  case GT: case GEU:  case GTU:
1834       /* These are normally need swapping, but for integer zero we have
1835          special patterns that recognize swapped operands.  */
1836       if (!fp_p && op1 == const0_rtx)
1837         break;
1838       code = swap_condition (code);
1839       if (fp_p)
1840         cmp_code = code, code = NE;
1841       tmp = op0, op0 = op1, op1 = tmp;
1842       break;
1843
1844     default:
1845       abort ();
1846     }
1847
1848   if (!fp_p)
1849     {
1850       if (!register_operand (op0, DImode))
1851         op0 = force_reg (DImode, op0);
1852       if (!reg_or_8bit_operand (op1, DImode))
1853         op1 = force_reg (DImode, op1);
1854     }
1855
1856   /* Emit an initial compare instruction, if necessary.  */
1857   if (cmp_code != NIL)
1858     {
1859       enum machine_mode mode = fp_p ? DFmode : DImode;
1860
1861       tmp = gen_reg_rtx (mode);
1862       emit_insn (gen_rtx_SET (VOIDmode, tmp,
1863                               gen_rtx_fmt_ee (cmp_code, mode, op0, op1)));
1864
1865       op0 = fp_p ? gen_lowpart (DImode, tmp) : tmp;
1866       op1 = const0_rtx;
1867     }
1868
1869   /* Return the setcc comparison.  */
1870   return gen_rtx_fmt_ee (code, DImode, op0, op1);
1871 }
1872
1873
1874 /* Rewrite a comparison against zero CMP of the form
1875    (CODE (cc0) (const_int 0)) so it can be written validly in
1876    a conditional move (if_then_else CMP ...).
1877    If both of the operands that set cc0 are non-zero we must emit
1878    an insn to perform the compare (it can't be done within
1879    the conditional move). */
1880 rtx
1881 alpha_emit_conditional_move (cmp, mode)
1882      rtx cmp;
1883      enum machine_mode mode;
1884 {
1885   enum rtx_code code = GET_CODE (cmp);
1886   enum rtx_code cmov_code = NE;
1887   rtx op0 = alpha_compare.op0;
1888   rtx op1 = alpha_compare.op1;
1889   int fp_p = alpha_compare.fp_p;
1890   enum machine_mode cmp_mode
1891     = (GET_MODE (op0) == VOIDmode ? DImode : GET_MODE (op0));
1892   enum machine_mode cmp_op_mode = fp_p ? DFmode : DImode;
1893   enum machine_mode cmov_mode = VOIDmode;
1894   int local_fast_math = flag_unsafe_math_optimizations;
1895   rtx tem;
1896
1897   /* Zero the operands.  */
1898   memset (&alpha_compare, 0, sizeof (alpha_compare));
1899
1900   if (fp_p != FLOAT_MODE_P (mode))
1901     {
1902       enum rtx_code cmp_code;
1903
1904       if (! TARGET_FIX)
1905         return 0;
1906
1907       /* If we have fp<->int register move instructions, do a cmov by
1908          performing the comparison in fp registers, and move the
1909          zero/non-zero value to integer registers, where we can then
1910          use a normal cmov, or vice-versa.  */
1911
1912       switch (code)
1913         {
1914         case EQ: case LE: case LT: case LEU: case LTU:
1915           /* We have these compares.  */
1916           cmp_code = code, code = NE;
1917           break;
1918
1919         case NE:
1920           /* This must be reversed.  */
1921           cmp_code = EQ, code = EQ;
1922           break;
1923
1924         case GE: case GT: case GEU: case GTU:
1925           /* These must be swapped.  */
1926           if (op1 == CONST0_RTX (cmp_mode))
1927             cmp_code = code, code = NE;
1928           else
1929             {
1930               cmp_code = swap_condition (code);
1931               code = NE;
1932               tem = op0, op0 = op1, op1 = tem;
1933             }
1934           break;
1935
1936         default:
1937           abort ();
1938         }
1939
1940       tem = gen_reg_rtx (cmp_op_mode);
1941       emit_insn (gen_rtx_SET (VOIDmode, tem,
1942                               gen_rtx_fmt_ee (cmp_code, cmp_op_mode,
1943                                               op0, op1)));
1944
1945       cmp_mode = cmp_op_mode = fp_p ? DImode : DFmode;
1946       op0 = gen_lowpart (cmp_op_mode, tem);
1947       op1 = CONST0_RTX (cmp_op_mode);
1948       fp_p = !fp_p;
1949       local_fast_math = 1;
1950     }
1951
1952   /* We may be able to use a conditional move directly.
1953      This avoids emitting spurious compares. */
1954   if (signed_comparison_operator (cmp, VOIDmode)
1955       && (!fp_p || local_fast_math)
1956       && (op0 == CONST0_RTX (cmp_mode) || op1 == CONST0_RTX (cmp_mode)))
1957     return gen_rtx_fmt_ee (code, VOIDmode, op0, op1);
1958
1959   /* We can't put the comparison inside the conditional move;
1960      emit a compare instruction and put that inside the
1961      conditional move.  Make sure we emit only comparisons we have;
1962      swap or reverse as necessary.  */
1963
1964   if (no_new_pseudos)
1965     return NULL_RTX;
1966
1967   switch (code)
1968     {
1969     case EQ:  case LE:  case LT:  case LEU:  case LTU:
1970       /* We have these compares: */
1971       break;
1972
1973     case NE:
1974       /* This must be reversed. */
1975       code = reverse_condition (code);
1976       cmov_code = EQ;
1977       break;
1978
1979     case GE:  case GT:  case GEU:  case GTU:
1980       /* These must be swapped.  */
1981       if (op1 != CONST0_RTX (cmp_mode))
1982         {
1983           code = swap_condition (code);
1984           tem = op0, op0 = op1, op1 = tem;
1985         }
1986       break;
1987
1988     default:
1989       abort ();
1990     }
1991
1992   if (!fp_p)
1993     {
1994       if (!reg_or_0_operand (op0, DImode))
1995         op0 = force_reg (DImode, op0);
1996       if (!reg_or_8bit_operand (op1, DImode))
1997         op1 = force_reg (DImode, op1);
1998     }
1999
2000   /* ??? We mark the branch mode to be CCmode to prevent the compare
2001      and cmov from being combined, since the compare insn follows IEEE
2002      rules that the cmov does not.  */
2003   if (fp_p && !local_fast_math)
2004     cmov_mode = CCmode;
2005
2006   tem = gen_reg_rtx (cmp_op_mode);
2007   emit_move_insn (tem, gen_rtx_fmt_ee (code, cmp_op_mode, op0, op1));
2008   return gen_rtx_fmt_ee (cmov_code, cmov_mode, tem, CONST0_RTX (cmp_op_mode));
2009 }
2010
2011 /* Simplify a conditional move of two constants into a setcc with
2012    arithmetic.  This is done with a splitter since combine would
2013    just undo the work if done during code generation.  It also catches
2014    cases we wouldn't have before cse.  */
2015
2016 int
2017 alpha_split_conditional_move (code, dest, cond, t_rtx, f_rtx)
2018      enum rtx_code code;
2019      rtx dest, cond, t_rtx, f_rtx;
2020 {
2021   HOST_WIDE_INT t, f, diff;
2022   enum machine_mode mode;
2023   rtx target, subtarget, tmp;
2024
2025   mode = GET_MODE (dest);
2026   t = INTVAL (t_rtx);
2027   f = INTVAL (f_rtx);
2028   diff = t - f;
2029
2030   if (((code == NE || code == EQ) && diff < 0)
2031       || (code == GE || code == GT))
2032     {
2033       code = reverse_condition (code);
2034       diff = t, t = f, f = diff;
2035       diff = t - f;
2036     }
2037
2038   subtarget = target = dest;
2039   if (mode != DImode)
2040     {
2041       target = gen_lowpart (DImode, dest);
2042       if (! no_new_pseudos)
2043         subtarget = gen_reg_rtx (DImode);
2044       else
2045         subtarget = target;
2046     }
2047
2048   if (f == 0 && exact_log2 (diff) > 0
2049       /* On EV6, we've got enough shifters to make non-arithmatic shifts
2050          viable over a longer latency cmove.  On EV5, the E0 slot is a
2051          scarce resource, and on EV4 shift has the same latency as a cmove. */
2052       && (diff <= 8 || alpha_cpu == PROCESSOR_EV6))
2053     {
2054       tmp = gen_rtx_fmt_ee (code, DImode, cond, const0_rtx);
2055       emit_insn (gen_rtx_SET (VOIDmode, subtarget, tmp));
2056
2057       tmp = gen_rtx_ASHIFT (DImode, subtarget, GEN_INT (exact_log2 (t)));
2058       emit_insn (gen_rtx_SET (VOIDmode, target, tmp));
2059     }
2060   else if (f == 0 && t == -1)
2061     {
2062       tmp = gen_rtx_fmt_ee (code, DImode, cond, const0_rtx);
2063       emit_insn (gen_rtx_SET (VOIDmode, subtarget, tmp));
2064
2065       emit_insn (gen_negdi2 (target, subtarget));
2066     }
2067   else if (diff == 1 || diff == 4 || diff == 8)
2068     {
2069       rtx add_op;
2070
2071       tmp = gen_rtx_fmt_ee (code, DImode, cond, const0_rtx);
2072       emit_insn (gen_rtx_SET (VOIDmode, subtarget, tmp));
2073
2074       if (diff == 1)
2075         emit_insn (gen_adddi3 (target, subtarget, GEN_INT (f)));
2076       else
2077         {
2078           add_op = GEN_INT (f);
2079           if (sext_add_operand (add_op, mode))
2080             {
2081               tmp = gen_rtx_MULT (DImode, subtarget, GEN_INT (diff));
2082               tmp = gen_rtx_PLUS (DImode, tmp, add_op);
2083               emit_insn (gen_rtx_SET (VOIDmode, target, tmp));
2084             }
2085           else
2086             return 0;
2087         }
2088     }
2089   else
2090     return 0;
2091
2092   return 1;
2093 }
2094 \f
2095 /* Look up the function X_floating library function name for the
2096    given operation.  */
2097
2098 static const char *
2099 alpha_lookup_xfloating_lib_func (code)
2100      enum rtx_code code;
2101 {
2102   struct xfloating_op
2103     {
2104       enum rtx_code code;
2105       const char *func;
2106     };
2107
2108   static const struct xfloating_op vms_xfloating_ops[] = 
2109     {
2110       { PLUS,           "OTS$ADD_X" },
2111       { MINUS,          "OTS$SUB_X" },
2112       { MULT,           "OTS$MUL_X" },
2113       { DIV,            "OTS$DIV_X" },
2114       { EQ,             "OTS$EQL_X" },
2115       { NE,             "OTS$NEQ_X" },
2116       { LT,             "OTS$LSS_X" },
2117       { LE,             "OTS$LEQ_X" },
2118       { GT,             "OTS$GTR_X" },
2119       { GE,             "OTS$GEQ_X" },
2120       { FIX,            "OTS$CVTXQ" },
2121       { FLOAT,          "OTS$CVTQX" },
2122       { UNSIGNED_FLOAT, "OTS$CVTQUX" },
2123       { FLOAT_EXTEND,   "OTS$CVT_FLOAT_T_X" },
2124       { FLOAT_TRUNCATE, "OTS$CVT_FLOAT_X_T" },
2125     };
2126
2127   static const struct xfloating_op osf_xfloating_ops[] = 
2128     {
2129       { PLUS,           "_OtsAddX" },
2130       { MINUS,          "_OtsSubX" },
2131       { MULT,           "_OtsMulX" },
2132       { DIV,            "_OtsDivX" },
2133       { EQ,             "_OtsEqlX" },
2134       { NE,             "_OtsNeqX" },
2135       { LT,             "_OtsLssX" },
2136       { LE,             "_OtsLeqX" },
2137       { GT,             "_OtsGtrX" },
2138       { GE,             "_OtsGeqX" },
2139       { FIX,            "_OtsCvtXQ" },
2140       { FLOAT,          "_OtsCvtQX" },
2141       { UNSIGNED_FLOAT, "_OtsCvtQUX" },
2142       { FLOAT_EXTEND,   "_OtsConvertFloatTX" },
2143       { FLOAT_TRUNCATE, "_OtsConvertFloatXT" },
2144     };
2145
2146   const struct xfloating_op *ops;
2147   const long n = ARRAY_SIZE (osf_xfloating_ops);
2148   long i;
2149
2150   /* How irritating.  Nothing to key off for the table.  Hardcode
2151      knowledge of the G_floating routines.  */
2152   if (TARGET_FLOAT_VAX)
2153     {
2154       if (TARGET_OPEN_VMS)
2155         {
2156           if (code == FLOAT_EXTEND)
2157             return "OTS$CVT_FLOAT_G_X";
2158           if (code == FLOAT_TRUNCATE)
2159             return "OTS$CVT_FLOAT_X_G";
2160         }
2161       else
2162         {
2163           if (code == FLOAT_EXTEND)
2164             return "_OtsConvertFloatGX";
2165           if (code == FLOAT_TRUNCATE)
2166             return "_OtsConvertFloatXG";
2167         }
2168     }
2169
2170   if (TARGET_OPEN_VMS)
2171     ops = vms_xfloating_ops;
2172   else
2173     ops = osf_xfloating_ops;
2174
2175   for (i = 0; i < n; ++i)
2176     if (ops[i].code == code)
2177       return ops[i].func;
2178
2179   abort();
2180 }
2181
2182 /* Most X_floating operations take the rounding mode as an argument.
2183    Compute that here.  */
2184
2185 static int
2186 alpha_compute_xfloating_mode_arg (code, round)
2187      enum rtx_code code;
2188      enum alpha_fp_rounding_mode round;
2189 {
2190   int mode;
2191
2192   switch (round)
2193     {
2194     case ALPHA_FPRM_NORM:
2195       mode = 2;
2196       break;
2197     case ALPHA_FPRM_MINF:
2198       mode = 1;
2199       break;
2200     case ALPHA_FPRM_CHOP:
2201       mode = 0;
2202       break;
2203     case ALPHA_FPRM_DYN:
2204       mode = 4;
2205       break;
2206     default:
2207       abort ();
2208
2209     /* XXX For reference, round to +inf is mode = 3.  */
2210     }
2211
2212   if (code == FLOAT_TRUNCATE && alpha_fptm == ALPHA_FPTM_N)
2213     mode |= 0x10000;
2214
2215   return mode;
2216 }
2217
2218 /* Emit an X_floating library function call.
2219
2220    Note that these functions do not follow normal calling conventions:
2221    TFmode arguments are passed in two integer registers (as opposed to
2222    indirect); TFmode return values appear in R16+R17. 
2223
2224    FUNC is the function name to call.
2225    TARGET is where the output belongs.
2226    OPERANDS are the inputs.
2227    NOPERANDS is the count of inputs.
2228    EQUIV is the expression equivalent for the function.
2229 */
2230
2231 static void
2232 alpha_emit_xfloating_libcall (func, target, operands, noperands, equiv)
2233      const char *func;
2234      rtx target;
2235      rtx operands[];
2236      int noperands;
2237      rtx equiv;
2238 {
2239   rtx usage = NULL_RTX, tmp, reg;
2240   int regno = 16, i;
2241
2242   start_sequence ();
2243
2244   for (i = 0; i < noperands; ++i)
2245     {
2246       switch (GET_MODE (operands[i]))
2247         {
2248         case TFmode:
2249           reg = gen_rtx_REG (TFmode, regno);
2250           regno += 2;
2251           break;
2252
2253         case DFmode:
2254           reg = gen_rtx_REG (DFmode, regno + 32);
2255           regno += 1;
2256           break;
2257
2258         case VOIDmode:
2259           if (GET_CODE (operands[i]) != CONST_INT)
2260             abort ();
2261           /* FALLTHRU */
2262         case DImode:
2263           reg = gen_rtx_REG (DImode, regno);
2264           regno += 1;
2265           break;
2266
2267         default:
2268           abort ();
2269         }
2270
2271       emit_move_insn (reg, operands[i]);
2272       usage = alloc_EXPR_LIST (0, gen_rtx_USE (VOIDmode, reg), usage);
2273     }
2274
2275   switch (GET_MODE (target))
2276     {
2277     case TFmode:
2278       reg = gen_rtx_REG (TFmode, 16);
2279       break;
2280     case DFmode:
2281       reg = gen_rtx_REG (DFmode, 32);
2282       break;
2283     case DImode:
2284       reg = gen_rtx_REG (DImode, 0);
2285       break;
2286     default:
2287       abort ();
2288     }
2289
2290   tmp = gen_rtx_MEM (QImode, gen_rtx_SYMBOL_REF (Pmode, (char *) func));
2291   tmp = emit_call_insn (GEN_CALL_VALUE (reg, tmp, const0_rtx,
2292                                         const0_rtx, const0_rtx));
2293   CALL_INSN_FUNCTION_USAGE (tmp) = usage;
2294
2295   tmp = get_insns ();
2296   end_sequence ();
2297
2298   emit_libcall_block (tmp, target, reg, equiv);
2299 }
2300
2301 /* Emit an X_floating library function call for arithmetic (+,-,*,/).  */
2302
2303 void
2304 alpha_emit_xfloating_arith (code, operands)
2305      enum rtx_code code;
2306      rtx operands[];
2307 {
2308   const char *func;
2309   int mode;
2310   rtx out_operands[3];
2311
2312   func = alpha_lookup_xfloating_lib_func (code);
2313   mode = alpha_compute_xfloating_mode_arg (code, alpha_fprm);
2314
2315   out_operands[0] = operands[1];
2316   out_operands[1] = operands[2];
2317   out_operands[2] = GEN_INT (mode);
2318   alpha_emit_xfloating_libcall (func, operands[0], out_operands, 3,  
2319                                 gen_rtx_fmt_ee (code, TFmode, operands[1],
2320                                                 operands[2]));
2321 }
2322
2323 /* Emit an X_floating library function call for a comparison.  */
2324
2325 static rtx
2326 alpha_emit_xfloating_compare (code, op0, op1)
2327      enum rtx_code code;
2328      rtx op0, op1;
2329 {
2330   const char *func;
2331   rtx out, operands[2];
2332
2333   func = alpha_lookup_xfloating_lib_func (code);
2334
2335   operands[0] = op0;
2336   operands[1] = op1;
2337   out = gen_reg_rtx (DImode);
2338
2339   /* ??? Strange equiv cause what's actually returned is -1,0,1, not a
2340      proper boolean value.  */
2341   alpha_emit_xfloating_libcall (func, out, operands, 2, 
2342                                 gen_rtx_COMPARE (TFmode, op0, op1));
2343
2344   return out;
2345 }
2346
2347 /* Emit an X_floating library function call for a conversion.  */
2348
2349 void
2350 alpha_emit_xfloating_cvt (code, operands)
2351      enum rtx_code code;
2352      rtx operands[];
2353 {
2354   int noperands = 1, mode;
2355   rtx out_operands[2];
2356   const char *func;
2357
2358   func = alpha_lookup_xfloating_lib_func (code);
2359
2360   out_operands[0] = operands[1];
2361
2362   switch (code)
2363     {
2364     case FIX:
2365       mode = alpha_compute_xfloating_mode_arg (code, ALPHA_FPRM_CHOP);
2366       out_operands[1] = GEN_INT (mode);
2367       noperands = 2;
2368       break;
2369     case FLOAT_TRUNCATE:
2370       mode = alpha_compute_xfloating_mode_arg (code, alpha_fprm);
2371       out_operands[1] = GEN_INT (mode);
2372       noperands = 2;
2373       break;
2374     default:
2375       break;
2376     }
2377
2378   alpha_emit_xfloating_libcall (func, operands[0], out_operands, noperands,
2379                                 gen_rtx_fmt_e (code, GET_MODE (operands[0]),
2380                                                operands[1]));
2381 }
2382
2383 /* Split a TFmode OP[1] into DImode OP[2,3] and likewise for
2384    OP[0] into OP[0,1].  Naturally, output operand ordering is
2385    little-endian.  */
2386
2387 void
2388 alpha_split_tfmode_pair (operands)
2389      rtx operands[4];
2390 {
2391   if (GET_CODE (operands[1]) == REG)
2392     {
2393       operands[3] = gen_rtx_REG (DImode, REGNO (operands[1]) + 1);
2394       operands[2] = gen_rtx_REG (DImode, REGNO (operands[1]));
2395     }
2396   else if (GET_CODE (operands[1]) == MEM)
2397     {
2398       operands[3] = change_address (operands[1], DImode,
2399                                     plus_constant (XEXP (operands[1], 0), 8));
2400       operands[2] = change_address (operands[1], DImode, NULL_RTX);
2401     }
2402   else if (operands[1] == CONST0_RTX (TFmode))
2403     operands[2] = operands[3] = const0_rtx;
2404   else
2405     abort ();
2406
2407   if (GET_CODE (operands[0]) == REG)
2408     {
2409       operands[1] = gen_rtx_REG (DImode, REGNO (operands[0]) + 1);
2410       operands[0] = gen_rtx_REG (DImode, REGNO (operands[0]));
2411     }
2412   else if (GET_CODE (operands[0]) == MEM)
2413     {
2414       operands[1] = change_address (operands[0], DImode,
2415                                     plus_constant (XEXP (operands[0], 0), 8));
2416       operands[0] = change_address (operands[0], DImode, NULL_RTX);
2417     }
2418   else
2419     abort ();
2420 }
2421
2422 /* Implement negtf2 or abstf2.  Op0 is destination, op1 is source, 
2423    op2 is a register containing the sign bit, operation is the 
2424    logical operation to be performed.  */
2425
2426 void
2427 alpha_split_tfmode_frobsign (operands, operation)
2428      rtx operands[3];
2429      rtx (*operation) PARAMS ((rtx, rtx, rtx));
2430 {
2431   rtx high_bit = operands[2];
2432   rtx scratch;
2433   int move;
2434
2435   alpha_split_tfmode_pair (operands);
2436
2437   /* Detect three flavours of operand overlap.  */
2438   move = 1;
2439   if (rtx_equal_p (operands[0], operands[2]))
2440     move = 0;
2441   else if (rtx_equal_p (operands[1], operands[2]))
2442     {
2443       if (rtx_equal_p (operands[0], high_bit))
2444         move = 2;
2445       else
2446         move = -1;
2447     }
2448
2449   if (move < 0)
2450     emit_move_insn (operands[0], operands[2]);
2451
2452   /* ??? If the destination overlaps both source tf and high_bit, then
2453      assume source tf is dead in its entirety and use the other half
2454      for a scratch register.  Otherwise "scratch" is just the proper
2455      destination register.  */
2456   scratch = operands[move < 2 ? 1 : 3];
2457
2458   emit_insn ((*operation) (scratch, high_bit, operands[3]));
2459
2460   if (move > 0)
2461     {
2462       emit_move_insn (operands[0], operands[2]);
2463       if (move > 1)
2464         emit_move_insn (operands[1], scratch);
2465     }
2466 }
2467 \f
2468 /* Use ext[wlq][lh] as the Architecture Handbook describes for extracting
2469    unaligned data:
2470
2471            unsigned:                       signed:
2472    word:   ldq_u  r1,X(r11)                ldq_u  r1,X(r11)
2473            ldq_u  r2,X+1(r11)              ldq_u  r2,X+1(r11)
2474            lda    r3,X(r11)                lda    r3,X+2(r11)
2475            extwl  r1,r3,r1                 extql  r1,r3,r1
2476            extwh  r2,r3,r2                 extqh  r2,r3,r2
2477            or     r1.r2.r1                 or     r1,r2,r1
2478                                            sra    r1,48,r1
2479
2480    long:   ldq_u  r1,X(r11)                ldq_u  r1,X(r11)
2481            ldq_u  r2,X+3(r11)              ldq_u  r2,X+3(r11)
2482            lda    r3,X(r11)                lda    r3,X(r11)
2483            extll  r1,r3,r1                 extll  r1,r3,r1
2484            extlh  r2,r3,r2                 extlh  r2,r3,r2
2485            or     r1.r2.r1                 addl   r1,r2,r1
2486
2487    quad:   ldq_u  r1,X(r11)
2488            ldq_u  r2,X+7(r11)
2489            lda    r3,X(r11)
2490            extql  r1,r3,r1
2491            extqh  r2,r3,r2
2492            or     r1.r2.r1
2493 */
2494
2495 void
2496 alpha_expand_unaligned_load (tgt, mem, size, ofs, sign)
2497      rtx tgt, mem;
2498      HOST_WIDE_INT size, ofs;
2499      int sign;
2500 {
2501   rtx meml, memh, addr, extl, exth, tmp;
2502   enum machine_mode mode;
2503
2504   meml = gen_reg_rtx (DImode);
2505   memh = gen_reg_rtx (DImode);
2506   addr = gen_reg_rtx (DImode);
2507   extl = gen_reg_rtx (DImode);
2508   exth = gen_reg_rtx (DImode);
2509
2510   /* AND addresses cannot be in any alias set, since they may implicitly
2511      alias surrounding code.  Ideally we'd have some alias set that 
2512      covered all types except those with alignment 8 or higher.  */
2513
2514   tmp = change_address (mem, DImode,
2515                         gen_rtx_AND (DImode, 
2516                                      plus_constant (XEXP (mem, 0), ofs),
2517                                      GEN_INT (-8)));
2518   MEM_ALIAS_SET (tmp) = 0;
2519   emit_move_insn (meml, tmp);
2520
2521   tmp = change_address (mem, DImode,
2522                         gen_rtx_AND (DImode, 
2523                                      plus_constant (XEXP (mem, 0),
2524                                                     ofs + size - 1),
2525                                      GEN_INT (-8)));
2526   MEM_ALIAS_SET (tmp) = 0;
2527   emit_move_insn (memh, tmp);
2528
2529   if (sign && size == 2)
2530     {
2531       emit_move_insn (addr, plus_constant (XEXP (mem, 0), ofs+2));
2532
2533       emit_insn (gen_extxl (extl, meml, GEN_INT (64), addr));
2534       emit_insn (gen_extqh (exth, memh, addr));
2535
2536       /* We must use tgt here for the target.  Alpha-vms port fails if we use
2537          addr for the target, because addr is marked as a pointer and combine
2538          knows that pointers are always sign-extended 32 bit values.  */
2539       addr = expand_binop (DImode, ior_optab, extl, exth, tgt, 1, OPTAB_WIDEN);
2540       addr = expand_binop (DImode, ashr_optab, addr, GEN_INT (48), 
2541                            addr, 1, OPTAB_WIDEN);
2542     }
2543   else
2544     {
2545       emit_move_insn (addr, plus_constant (XEXP (mem, 0), ofs));
2546       emit_insn (gen_extxl (extl, meml, GEN_INT (size*8), addr));
2547       switch ((int) size)
2548         {
2549         case 2:
2550           emit_insn (gen_extwh (exth, memh, addr));
2551           mode = HImode;
2552           break;
2553
2554         case 4:
2555           emit_insn (gen_extlh (exth, memh, addr));
2556           mode = SImode;
2557           break;
2558
2559         case 8:
2560           emit_insn (gen_extqh (exth, memh, addr));
2561           mode = DImode;
2562           break;
2563
2564         default:
2565           abort();
2566         }
2567
2568       addr = expand_binop (mode, ior_optab, gen_lowpart (mode, extl),
2569                            gen_lowpart (mode, exth), gen_lowpart (mode, tgt),
2570                            sign, OPTAB_WIDEN);
2571     }
2572
2573   if (addr != tgt)
2574     emit_move_insn (tgt, gen_lowpart(GET_MODE (tgt), addr));
2575 }
2576
2577 /* Similarly, use ins and msk instructions to perform unaligned stores.  */
2578
2579 void
2580 alpha_expand_unaligned_store (dst, src, size, ofs)
2581      rtx dst, src;
2582      HOST_WIDE_INT size, ofs;
2583 {
2584   rtx dstl, dsth, addr, insl, insh, meml, memh;
2585   
2586   dstl = gen_reg_rtx (DImode);
2587   dsth = gen_reg_rtx (DImode);
2588   insl = gen_reg_rtx (DImode);
2589   insh = gen_reg_rtx (DImode);
2590
2591   /* AND addresses cannot be in any alias set, since they may implicitly
2592      alias surrounding code.  Ideally we'd have some alias set that 
2593      covered all types except those with alignment 8 or higher.  */
2594
2595   meml = change_address (dst, DImode,
2596                          gen_rtx_AND (DImode, 
2597                                       plus_constant (XEXP (dst, 0), ofs),
2598                                       GEN_INT (-8)));
2599   MEM_ALIAS_SET (meml) = 0;
2600
2601   memh = change_address (dst, DImode,
2602                          gen_rtx_AND (DImode, 
2603                                       plus_constant (XEXP (dst, 0),
2604                                                      ofs+size-1),
2605                                       GEN_INT (-8)));
2606   MEM_ALIAS_SET (memh) = 0;
2607
2608   emit_move_insn (dsth, memh);
2609   emit_move_insn (dstl, meml);
2610   addr = copy_addr_to_reg (plus_constant (XEXP (dst, 0), ofs));
2611
2612   if (src != const0_rtx)
2613     {
2614       emit_insn (gen_insxh (insh, gen_lowpart (DImode, src),
2615                             GEN_INT (size*8), addr));
2616
2617       switch ((int) size)
2618         {
2619         case 2:
2620           emit_insn (gen_inswl (insl, gen_lowpart (HImode, src), addr));
2621           break;
2622         case 4:
2623           emit_insn (gen_insll (insl, gen_lowpart (SImode, src), addr));
2624           break;
2625         case 8:
2626           emit_insn (gen_insql (insl, src, addr));
2627           break;
2628         }
2629     }
2630
2631   emit_insn (gen_mskxh (dsth, dsth, GEN_INT (size*8), addr));
2632
2633   switch ((int) size)
2634     {
2635     case 2:
2636       emit_insn (gen_mskxl (dstl, dstl, GEN_INT (0xffff), addr));
2637       break;
2638     case 4:
2639       emit_insn (gen_mskxl (dstl, dstl, GEN_INT (0xffffffff), addr));
2640       break;
2641     case 8:
2642       {
2643 #if HOST_BITS_PER_WIDE_INT == 32
2644         rtx msk = immed_double_const (0xffffffff, 0xffffffff, DImode);
2645 #else
2646         rtx msk = immed_double_const (0xffffffffffffffff, 0, DImode);
2647 #endif
2648         emit_insn (gen_mskxl (dstl, dstl, msk, addr));
2649       }
2650       break;
2651     }
2652
2653   if (src != const0_rtx)
2654     {
2655       dsth = expand_binop (DImode, ior_optab, insh, dsth, dsth, 0, OPTAB_WIDEN);
2656       dstl = expand_binop (DImode, ior_optab, insl, dstl, dstl, 0, OPTAB_WIDEN);
2657     }
2658   
2659   /* Must store high before low for degenerate case of aligned.  */
2660   emit_move_insn (memh, dsth);
2661   emit_move_insn (meml, dstl);
2662 }
2663
2664 /* The block move code tries to maximize speed by separating loads and
2665    stores at the expense of register pressure: we load all of the data
2666    before we store it back out.  There are two secondary effects worth
2667    mentioning, that this speeds copying to/from aligned and unaligned
2668    buffers, and that it makes the code significantly easier to write.  */
2669
2670 #define MAX_MOVE_WORDS  8
2671
2672 /* Load an integral number of consecutive unaligned quadwords.  */
2673
2674 static void
2675 alpha_expand_unaligned_load_words (out_regs, smem, words, ofs)
2676      rtx *out_regs;
2677      rtx smem;
2678      HOST_WIDE_INT words, ofs;
2679 {
2680   rtx const im8 = GEN_INT (-8);
2681   rtx const i64 = GEN_INT (64);
2682   rtx ext_tmps[MAX_MOVE_WORDS], data_regs[MAX_MOVE_WORDS+1];
2683   rtx sreg, areg, tmp;
2684   HOST_WIDE_INT i;
2685
2686   /* Generate all the tmp registers we need.  */
2687   for (i = 0; i < words; ++i)
2688     {
2689       data_regs[i] = out_regs[i];
2690       ext_tmps[i] = gen_reg_rtx (DImode);
2691     }
2692   data_regs[words] = gen_reg_rtx (DImode);
2693
2694   if (ofs != 0)
2695     smem = change_address (smem, GET_MODE (smem),
2696                            plus_constant (XEXP (smem, 0), ofs));
2697   
2698   /* Load up all of the source data.  */
2699   for (i = 0; i < words; ++i)
2700     {
2701       tmp = change_address (smem, DImode,
2702                             gen_rtx_AND (DImode,
2703                                          plus_constant (XEXP(smem,0), 8*i),
2704                                          im8));
2705       MEM_ALIAS_SET (tmp) = 0;
2706       emit_move_insn (data_regs[i], tmp);
2707     }
2708
2709   tmp = change_address (smem, DImode,
2710                         gen_rtx_AND (DImode,
2711                                      plus_constant (XEXP(smem,0), 8*words - 1),
2712                                      im8));
2713   MEM_ALIAS_SET (tmp) = 0;
2714   emit_move_insn (data_regs[words], tmp);
2715
2716   /* Extract the half-word fragments.  Unfortunately DEC decided to make
2717      extxh with offset zero a noop instead of zeroing the register, so 
2718      we must take care of that edge condition ourselves with cmov.  */
2719
2720   sreg = copy_addr_to_reg (XEXP (smem, 0));
2721   areg = expand_binop (DImode, and_optab, sreg, GEN_INT (7), NULL, 
2722                        1, OPTAB_WIDEN);
2723   for (i = 0; i < words; ++i)
2724     {
2725       emit_insn (gen_extxl (data_regs[i], data_regs[i], i64, sreg));
2726
2727       emit_insn (gen_extqh (ext_tmps[i], data_regs[i+1], sreg));
2728       emit_insn (gen_rtx_SET (VOIDmode, ext_tmps[i],
2729                               gen_rtx_IF_THEN_ELSE (DImode,
2730                                                     gen_rtx_EQ (DImode, areg,
2731                                                                 const0_rtx),
2732                                                     const0_rtx, ext_tmps[i])));
2733     }
2734
2735   /* Merge the half-words into whole words.  */
2736   for (i = 0; i < words; ++i)
2737     {
2738       out_regs[i] = expand_binop (DImode, ior_optab, data_regs[i],
2739                                   ext_tmps[i], data_regs[i], 1, OPTAB_WIDEN);
2740     }
2741 }
2742
2743 /* Store an integral number of consecutive unaligned quadwords.  DATA_REGS
2744    may be NULL to store zeros.  */
2745
2746 static void
2747 alpha_expand_unaligned_store_words (data_regs, dmem, words, ofs)
2748      rtx *data_regs;
2749      rtx dmem;
2750      HOST_WIDE_INT words, ofs;
2751 {
2752   rtx const im8 = GEN_INT (-8);
2753   rtx const i64 = GEN_INT (64);
2754 #if HOST_BITS_PER_WIDE_INT == 32
2755   rtx const im1 = immed_double_const (0xffffffff, 0xffffffff, DImode);
2756 #else
2757   rtx const im1 = immed_double_const (0xffffffffffffffff, 0, DImode);
2758 #endif
2759   rtx ins_tmps[MAX_MOVE_WORDS];
2760   rtx st_tmp_1, st_tmp_2, dreg;
2761   rtx st_addr_1, st_addr_2;
2762   HOST_WIDE_INT i;
2763
2764   /* Generate all the tmp registers we need.  */
2765   if (data_regs != NULL)
2766     for (i = 0; i < words; ++i)
2767       ins_tmps[i] = gen_reg_rtx(DImode);
2768   st_tmp_1 = gen_reg_rtx(DImode);
2769   st_tmp_2 = gen_reg_rtx(DImode);
2770   
2771   if (ofs != 0)
2772     dmem = change_address (dmem, GET_MODE (dmem),
2773                            plus_constant (XEXP (dmem, 0), ofs));
2774   
2775
2776   st_addr_2 = change_address (dmem, DImode,
2777                               gen_rtx_AND (DImode,
2778                                            plus_constant (XEXP(dmem,0),
2779                                                           words*8 - 1),
2780                                        im8));
2781   MEM_ALIAS_SET (st_addr_2) = 0;
2782
2783   st_addr_1 = change_address (dmem, DImode,
2784                               gen_rtx_AND (DImode, 
2785                                            XEXP (dmem, 0),
2786                                            im8));
2787   MEM_ALIAS_SET (st_addr_1) = 0;
2788
2789   /* Load up the destination end bits.  */
2790   emit_move_insn (st_tmp_2, st_addr_2);
2791   emit_move_insn (st_tmp_1, st_addr_1);
2792
2793   /* Shift the input data into place.  */
2794   dreg = copy_addr_to_reg (XEXP (dmem, 0));
2795   if (data_regs != NULL)
2796     {
2797       for (i = words-1; i >= 0; --i)
2798         {
2799           emit_insn (gen_insxh (ins_tmps[i], data_regs[i], i64, dreg));
2800           emit_insn (gen_insql (data_regs[i], data_regs[i], dreg));
2801         }
2802       for (i = words-1; i > 0; --i)
2803         {
2804           ins_tmps[i-1] = expand_binop (DImode, ior_optab, data_regs[i],
2805                                         ins_tmps[i-1], ins_tmps[i-1], 1,
2806                                         OPTAB_WIDEN);
2807         }
2808     }
2809
2810   /* Split and merge the ends with the destination data.  */
2811   emit_insn (gen_mskxh (st_tmp_2, st_tmp_2, i64, dreg));
2812   emit_insn (gen_mskxl (st_tmp_1, st_tmp_1, im1, dreg));
2813
2814   if (data_regs != NULL)
2815     {
2816       st_tmp_2 = expand_binop (DImode, ior_optab, st_tmp_2, ins_tmps[words-1],
2817                                st_tmp_2, 1, OPTAB_WIDEN);
2818       st_tmp_1 = expand_binop (DImode, ior_optab, st_tmp_1, data_regs[0],
2819                                st_tmp_1, 1, OPTAB_WIDEN);
2820     }
2821
2822   /* Store it all.  */
2823   emit_move_insn (st_addr_2, st_tmp_2);
2824   for (i = words-1; i > 0; --i)
2825     {
2826       rtx tmp = change_address (dmem, DImode,
2827                                 gen_rtx_AND (DImode,
2828                                              plus_constant(XEXP (dmem,0), i*8),
2829                                              im8));
2830       MEM_ALIAS_SET (tmp) = 0;
2831       emit_move_insn (tmp, data_regs ? ins_tmps[i-1] : const0_rtx);
2832     }
2833   emit_move_insn (st_addr_1, st_tmp_1);
2834 }
2835
2836
2837 /* Expand string/block move operations.
2838
2839    operands[0] is the pointer to the destination.
2840    operands[1] is the pointer to the source.
2841    operands[2] is the number of bytes to move.
2842    operands[3] is the alignment.  */
2843
2844 int
2845 alpha_expand_block_move (operands)
2846      rtx operands[];
2847 {
2848   rtx bytes_rtx = operands[2];
2849   rtx align_rtx = operands[3];
2850   HOST_WIDE_INT orig_bytes = INTVAL (bytes_rtx);
2851   HOST_WIDE_INT bytes = orig_bytes;
2852   HOST_WIDE_INT src_align = INTVAL (align_rtx) * BITS_PER_UNIT;
2853   HOST_WIDE_INT dst_align = src_align;
2854   rtx orig_src = operands[1];
2855   rtx orig_dst = operands[0];
2856   rtx data_regs[2 * MAX_MOVE_WORDS + 16];
2857   rtx tmp;
2858   int i, words, ofs, nregs = 0;
2859   
2860   if (orig_bytes <= 0)
2861     return 1;
2862   else if (orig_bytes > MAX_MOVE_WORDS * UNITS_PER_WORD)
2863     return 0;
2864
2865   /* Look for additional alignment information from recorded register info.  */
2866
2867   tmp = XEXP (orig_src, 0);
2868   if (GET_CODE (tmp) == REG)
2869     src_align = MAX (src_align, REGNO_POINTER_ALIGN (REGNO (tmp)));
2870   else if (GET_CODE (tmp) == PLUS
2871            && GET_CODE (XEXP (tmp, 0)) == REG
2872            && GET_CODE (XEXP (tmp, 1)) == CONST_INT)
2873     {
2874       unsigned HOST_WIDE_INT c = INTVAL (XEXP (tmp, 1));
2875       unsigned int a = REGNO_POINTER_ALIGN (REGNO (XEXP (tmp, 0)));
2876
2877       if (a > src_align)
2878         {
2879           if (a >= 64 && c % 8 == 0)
2880             src_align = 64;
2881           else if (a >= 32 && c % 4 == 0)
2882             src_align = 32;
2883           else if (a >= 16 && c % 2 == 0)
2884             src_align = 16;
2885         }
2886     }
2887         
2888   tmp = XEXP (orig_dst, 0);
2889   if (GET_CODE (tmp) == REG)
2890     dst_align = MAX (dst_align, REGNO_POINTER_ALIGN (REGNO (tmp)));
2891   else if (GET_CODE (tmp) == PLUS
2892            && GET_CODE (XEXP (tmp, 0)) == REG
2893            && GET_CODE (XEXP (tmp, 1)) == CONST_INT)
2894     {
2895       unsigned HOST_WIDE_INT c = INTVAL (XEXP (tmp, 1));
2896       unsigned int a = REGNO_POINTER_ALIGN (REGNO (XEXP (tmp, 0)));
2897
2898       if (a > dst_align)
2899         {
2900           if (a >= 64 && c % 8 == 0)
2901             dst_align = 64;
2902           else if (a >= 32 && c % 4 == 0)
2903             dst_align = 32;
2904           else if (a >= 16 && c % 2 == 0)
2905             dst_align = 16;
2906         }
2907     }
2908
2909   /* Load the entire block into registers.  */
2910   if (GET_CODE (XEXP (orig_src, 0)) == ADDRESSOF)
2911     {
2912       enum machine_mode mode;
2913
2914       tmp = XEXP (XEXP (orig_src, 0), 0);
2915
2916       /* Don't use the existing register if we're reading more than
2917          is held in the register.  Nor if there is not a mode that
2918          handles the exact size.  */
2919       mode = mode_for_size (bytes * BITS_PER_UNIT, MODE_INT, 1);
2920       if (mode != BLKmode
2921           && GET_MODE_SIZE (GET_MODE (tmp)) >= bytes)
2922         {
2923           if (mode == TImode)
2924             {
2925               data_regs[nregs] = gen_lowpart (DImode, tmp);
2926               data_regs[nregs+1] = gen_highpart (DImode, tmp);
2927               nregs += 2;
2928             }
2929           else
2930             data_regs[nregs++] = gen_lowpart (mode, tmp);
2931
2932           goto src_done;
2933         }
2934
2935       /* No appropriate mode; fall back on memory.  */
2936       orig_src = change_address (orig_src, GET_MODE (orig_src),
2937                                  copy_addr_to_reg (XEXP (orig_src, 0)));
2938       src_align = GET_MODE_BITSIZE (GET_MODE (tmp));
2939     }
2940
2941   ofs = 0;
2942   if (src_align >= 64 && bytes >= 8)
2943     {
2944       words = bytes / 8;
2945
2946       for (i = 0; i < words; ++i)
2947         data_regs[nregs + i] = gen_reg_rtx(DImode);
2948
2949       for (i = 0; i < words; ++i)
2950         emit_move_insn (data_regs[nregs + i],
2951                         change_address (orig_src, DImode,
2952                                         plus_constant (XEXP (orig_src, 0), 
2953                                                        ofs + i * 8)));
2954
2955       nregs += words;
2956       bytes -= words * 8;
2957       ofs += words * 8;
2958     }
2959
2960   if (src_align >= 32 && bytes >= 4)
2961     {
2962       words = bytes / 4;
2963
2964       for (i = 0; i < words; ++i)
2965         data_regs[nregs + i] = gen_reg_rtx(SImode);
2966
2967       for (i = 0; i < words; ++i)
2968         emit_move_insn (data_regs[nregs + i],
2969                         change_address (orig_src, SImode,
2970                                         plus_constant (XEXP (orig_src, 0),
2971                                                        ofs + i * 4)));
2972
2973       nregs += words;
2974       bytes -= words * 4;
2975       ofs += words * 4;
2976     }
2977
2978   if (bytes >= 8)
2979     {
2980       words = bytes / 8;
2981
2982       for (i = 0; i < words+1; ++i)
2983         data_regs[nregs + i] = gen_reg_rtx(DImode);
2984
2985       alpha_expand_unaligned_load_words (data_regs + nregs, orig_src,
2986                                          words, ofs);
2987
2988       nregs += words;
2989       bytes -= words * 8;
2990       ofs += words * 8;
2991     }
2992
2993   if (! TARGET_BWX && bytes >= 4)
2994     {
2995       data_regs[nregs++] = tmp = gen_reg_rtx (SImode);
2996       alpha_expand_unaligned_load (tmp, orig_src, 4, ofs, 0);
2997       bytes -= 4;
2998       ofs += 4;
2999     }
3000
3001   if (bytes >= 2)
3002     {
3003       if (src_align >= 16)
3004         {
3005           do {
3006             data_regs[nregs++] = tmp = gen_reg_rtx (HImode);
3007             emit_move_insn (tmp,
3008                             change_address (orig_src, HImode,
3009                                             plus_constant (XEXP (orig_src, 0),
3010                                                            ofs)));
3011             bytes -= 2;
3012             ofs += 2;
3013           } while (bytes >= 2);
3014         }
3015       else if (! TARGET_BWX)
3016         {
3017           data_regs[nregs++] = tmp = gen_reg_rtx (HImode);
3018           alpha_expand_unaligned_load (tmp, orig_src, 2, ofs, 0);
3019           bytes -= 2;
3020           ofs += 2;
3021         }
3022     }
3023
3024   while (bytes > 0)
3025     {
3026       data_regs[nregs++] = tmp = gen_reg_rtx (QImode);
3027       emit_move_insn (tmp,
3028                       change_address (orig_src, QImode,
3029                                       plus_constant (XEXP (orig_src, 0),
3030                                                      ofs)));
3031       bytes -= 1;
3032       ofs += 1;
3033     }
3034
3035  src_done:
3036
3037   if (nregs > ARRAY_SIZE (data_regs))
3038     abort ();
3039
3040   /* Now save it back out again.  */
3041
3042   i = 0, ofs = 0;
3043
3044   if (GET_CODE (XEXP (orig_dst, 0)) == ADDRESSOF)
3045     {
3046       enum machine_mode mode;
3047       tmp = XEXP (XEXP (orig_dst, 0), 0);
3048
3049       mode = mode_for_size (orig_bytes * BITS_PER_UNIT, MODE_INT, 1);
3050       if (GET_MODE (tmp) == mode)
3051         {
3052           if (nregs == 1)
3053             {
3054               emit_move_insn (tmp, data_regs[0]);
3055               i = 1;
3056               goto dst_done;
3057             }
3058
3059           else if (nregs == 2 && mode == TImode)
3060             {
3061               /* Undo the subregging done above when copying between
3062                  two TImode registers.  */
3063               if (GET_CODE (data_regs[0]) == SUBREG
3064                   && GET_MODE (SUBREG_REG (data_regs[0])) == TImode)
3065                 emit_move_insn (tmp, SUBREG_REG (data_regs[0]));
3066               else
3067                 {
3068                   rtx seq;
3069
3070                   start_sequence ();
3071                   emit_move_insn (gen_lowpart (DImode, tmp), data_regs[0]);
3072                   emit_move_insn (gen_highpart (DImode, tmp), data_regs[1]);
3073                   seq = get_insns ();
3074                   end_sequence ();
3075
3076                   emit_no_conflict_block (seq, tmp, data_regs[0],
3077                                           data_regs[1], NULL_RTX);
3078                 }
3079
3080               i = 2;
3081               goto dst_done;
3082             }
3083         }
3084
3085       /* ??? If nregs > 1, consider reconstructing the word in regs.  */
3086       /* ??? Optimize mode < dst_mode with strict_low_part.  */
3087
3088       /* No appropriate mode; fall back on memory.  We can speed things
3089          up by recognizing extra alignment information.  */
3090       orig_dst = change_address (orig_dst, GET_MODE (orig_dst),
3091                                  copy_addr_to_reg (XEXP (orig_dst, 0)));
3092       dst_align = GET_MODE_BITSIZE (GET_MODE (tmp));
3093     }
3094
3095   /* Write out the data in whatever chunks reading the source allowed.  */
3096   if (dst_align >= 64)
3097     {
3098       while (i < nregs && GET_MODE (data_regs[i]) == DImode)
3099         {
3100           emit_move_insn (change_address (orig_dst, DImode,
3101                                           plus_constant (XEXP (orig_dst, 0),
3102                                                          ofs)),
3103                           data_regs[i]);
3104           ofs += 8;
3105           i++;
3106         }
3107     }
3108
3109   if (dst_align >= 32)
3110     {
3111       /* If the source has remaining DImode regs, write them out in
3112          two pieces.  */
3113       while (i < nregs && GET_MODE (data_regs[i]) == DImode)
3114         {
3115           tmp = expand_binop (DImode, lshr_optab, data_regs[i], GEN_INT (32),
3116                               NULL_RTX, 1, OPTAB_WIDEN);
3117
3118           emit_move_insn (change_address (orig_dst, SImode,
3119                                           plus_constant (XEXP (orig_dst, 0),
3120                                                          ofs)),
3121                           gen_lowpart (SImode, data_regs[i]));
3122           emit_move_insn (change_address (orig_dst, SImode,
3123                                           plus_constant (XEXP (orig_dst, 0),
3124                                                          ofs + 4)),
3125                           gen_lowpart (SImode, tmp));
3126           ofs += 8;
3127           i++;
3128         }
3129
3130       while (i < nregs && GET_MODE (data_regs[i]) == SImode)
3131         {
3132           emit_move_insn (change_address(orig_dst, SImode,
3133                                          plus_constant (XEXP (orig_dst, 0),
3134                                                         ofs)),
3135                           data_regs[i]);
3136           ofs += 4;
3137           i++;
3138         }
3139     }
3140
3141   if (i < nregs && GET_MODE (data_regs[i]) == DImode)
3142     {
3143       /* Write out a remaining block of words using unaligned methods.  */
3144
3145       for (words = 1; i + words < nregs; words++)
3146         if (GET_MODE (data_regs[i + words]) != DImode)
3147           break;
3148
3149       if (words == 1)
3150         alpha_expand_unaligned_store (orig_dst, data_regs[i], 8, ofs);
3151       else
3152         alpha_expand_unaligned_store_words (data_regs + i, orig_dst,
3153                                             words, ofs);
3154      
3155       i += words;
3156       ofs += words * 8;
3157     }
3158
3159   /* Due to the above, this won't be aligned.  */
3160   /* ??? If we have more than one of these, consider constructing full
3161      words in registers and using alpha_expand_unaligned_store_words.  */
3162   while (i < nregs && GET_MODE (data_regs[i]) == SImode)
3163     {
3164       alpha_expand_unaligned_store (orig_dst, data_regs[i], 4, ofs);
3165       ofs += 4;
3166       i++;
3167     }
3168
3169   if (dst_align >= 16)
3170     while (i < nregs && GET_MODE (data_regs[i]) == HImode)
3171       {
3172         emit_move_insn (change_address (orig_dst, HImode,
3173                                         plus_constant (XEXP (orig_dst, 0),
3174                                                        ofs)),
3175                         data_regs[i]);
3176         i++;
3177         ofs += 2;
3178       }
3179   else
3180     while (i < nregs && GET_MODE (data_regs[i]) == HImode)
3181       {
3182         alpha_expand_unaligned_store (orig_dst, data_regs[i], 2, ofs);
3183         i++;
3184         ofs += 2;
3185       }
3186
3187   while (i < nregs && GET_MODE (data_regs[i]) == QImode)
3188     {
3189       emit_move_insn (change_address (orig_dst, QImode,
3190                                       plus_constant (XEXP (orig_dst, 0),
3191                                                      ofs)),
3192                       data_regs[i]);
3193       i++;
3194       ofs += 1;
3195     }
3196
3197  dst_done:
3198
3199   if (i != nregs)
3200     abort ();
3201
3202   return 1;
3203 }
3204
3205 int
3206 alpha_expand_block_clear (operands)
3207      rtx operands[];
3208 {
3209   rtx bytes_rtx = operands[1];
3210   rtx align_rtx = operands[2];
3211   HOST_WIDE_INT orig_bytes = INTVAL (bytes_rtx);
3212   HOST_WIDE_INT bytes = orig_bytes;
3213   HOST_WIDE_INT align = INTVAL (align_rtx) * BITS_PER_UNIT;
3214   HOST_WIDE_INT alignofs = 0;
3215   rtx orig_dst = operands[0];
3216   rtx tmp;
3217   int i, words, ofs = 0;
3218   
3219   if (orig_bytes <= 0)
3220     return 1;
3221   if (orig_bytes > MAX_MOVE_WORDS * UNITS_PER_WORD)
3222     return 0;
3223
3224   /* Look for stricter alignment.  */
3225   tmp = XEXP (orig_dst, 0);
3226   if (GET_CODE (tmp) == REG)
3227     align = MAX (align, REGNO_POINTER_ALIGN (REGNO (tmp)));
3228   else if (GET_CODE (tmp) == PLUS
3229            && GET_CODE (XEXP (tmp, 0)) == REG
3230            && GET_CODE (XEXP (tmp, 1)) == CONST_INT)
3231     {
3232       HOST_WIDE_INT c = INTVAL (XEXP (tmp, 1));
3233       int a = REGNO_POINTER_ALIGN (REGNO (XEXP (tmp, 0)));
3234
3235       if (a > align)
3236         {
3237           if (a >= 64)
3238             align = a, alignofs = 8 - c % 8;
3239           else if (a >= 32)
3240             align = a, alignofs = 4 - c % 4;
3241           else if (a >= 16)
3242             align = a, alignofs = 2 - c % 2;
3243         }
3244     }
3245   else if (GET_CODE (tmp) == ADDRESSOF)
3246     {
3247       enum machine_mode mode;
3248
3249       mode = mode_for_size (bytes * BITS_PER_UNIT, MODE_INT, 1);
3250       if (GET_MODE (XEXP (tmp, 0)) == mode)
3251         {
3252           emit_move_insn (XEXP (tmp, 0), const0_rtx);
3253           return 1;
3254         }
3255
3256       /* No appropriate mode; fall back on memory.  */
3257       orig_dst = change_address (orig_dst, GET_MODE (orig_dst),
3258                                  copy_addr_to_reg (tmp));
3259       align = GET_MODE_BITSIZE (GET_MODE (XEXP (tmp, 0)));
3260     }
3261
3262   /* Handle an unaligned prefix first.  */
3263
3264   if (alignofs > 0)
3265     {
3266 #if HOST_BITS_PER_WIDE_INT >= 64
3267       /* Given that alignofs is bounded by align, the only time BWX could
3268          generate three stores is for a 7 byte fill.  Prefer two individual
3269          stores over a load/mask/store sequence.  */
3270       if ((!TARGET_BWX || alignofs == 7)
3271                && align >= 32
3272                && !(alignofs == 4 && bytes >= 4))
3273         {
3274           enum machine_mode mode = (align >= 64 ? DImode : SImode);
3275           int inv_alignofs = (align >= 64 ? 8 : 4) - alignofs;
3276           rtx mem, tmp;
3277           HOST_WIDE_INT mask;
3278
3279           mem = change_address (orig_dst, mode,
3280                                 plus_constant (XEXP (orig_dst, 0),
3281                                                ofs - inv_alignofs));
3282           MEM_ALIAS_SET (mem) = 0;
3283
3284           mask = ~(~(HOST_WIDE_INT)0 << (inv_alignofs * 8));
3285           if (bytes < alignofs)
3286             {
3287               mask |= ~(HOST_WIDE_INT)0 << ((inv_alignofs + bytes) * 8);
3288               ofs += bytes;
3289               bytes = 0;
3290             }
3291           else
3292             {
3293               bytes -= alignofs;
3294               ofs += alignofs;
3295             }
3296           alignofs = 0;
3297
3298           tmp = expand_binop (mode, and_optab, mem, GEN_INT (mask),
3299                               NULL_RTX, 1, OPTAB_WIDEN);
3300
3301           emit_move_insn (mem, tmp);
3302         }
3303 #endif
3304
3305       if (TARGET_BWX && (alignofs & 1) && bytes >= 1)
3306         {
3307           emit_move_insn (change_address (orig_dst, QImode,
3308                                           plus_constant (XEXP (orig_dst, 0),
3309                                                          ofs)),
3310                           const0_rtx);
3311           bytes -= 1;
3312           ofs += 1;
3313           alignofs -= 1;
3314         }
3315       if (TARGET_BWX && align >= 16 && (alignofs & 3) == 2 && bytes >= 2)
3316         {
3317           emit_move_insn (change_address (orig_dst, HImode,
3318                                           plus_constant (XEXP (orig_dst, 0),
3319                                                          ofs)),
3320                           const0_rtx);
3321           bytes -= 2;
3322           ofs += 2;
3323           alignofs -= 2;
3324         }
3325       if (alignofs == 4 && bytes >= 4)
3326         {
3327           emit_move_insn (change_address (orig_dst, SImode,
3328                                           plus_constant (XEXP (orig_dst, 0),
3329                                                          ofs)),
3330                           const0_rtx);
3331           bytes -= 4;
3332           ofs += 4;
3333           alignofs = 0;
3334         }
3335
3336       /* If we've not used the extra lead alignment information by now,
3337          we won't be able to.  Downgrade align to match what's left over.  */
3338       if (alignofs > 0)
3339         {
3340           alignofs = alignofs & -alignofs;
3341           align = MIN (align, alignofs * BITS_PER_UNIT);
3342         }
3343     }
3344
3345   /* Handle a block of contiguous long-words.  */
3346
3347   if (align >= 64 && bytes >= 8)
3348     {
3349       words = bytes / 8;
3350
3351       for (i = 0; i < words; ++i)
3352         emit_move_insn (change_address(orig_dst, DImode,
3353                                        plus_constant (XEXP (orig_dst, 0),
3354                                                       ofs + i * 8)),
3355                           const0_rtx);
3356
3357       bytes -= words * 8;
3358       ofs += words * 8;
3359     }
3360
3361   /* If the block is large and appropriately aligned, emit a single
3362      store followed by a sequence of stq_u insns.  */
3363
3364   if (align >= 32 && bytes > 16)
3365     {
3366       emit_move_insn (change_address (orig_dst, SImode,
3367                                       plus_constant (XEXP (orig_dst, 0), ofs)),
3368                       const0_rtx);
3369       bytes -= 4;
3370       ofs += 4;
3371
3372       words = bytes / 8;
3373       for (i = 0; i < words; ++i)
3374         {
3375           rtx mem;
3376           mem = change_address (orig_dst, DImode,
3377                                 gen_rtx_AND (DImode,
3378                                              plus_constant (XEXP (orig_dst, 0),
3379                                                             ofs + i*8),
3380                                              GEN_INT (-8)));
3381           MEM_ALIAS_SET (mem) = 0;
3382           emit_move_insn (mem, const0_rtx);
3383         }
3384
3385       /* Depending on the alignment, the first stq_u may have overlapped
3386          with the initial stl, which means that the last stq_u didn't
3387          write as much as it would appear.  Leave those questionable bytes
3388          unaccounted for.  */
3389       bytes -= words * 8 - 4;
3390       ofs += words * 8 - 4;
3391     }
3392
3393   /* Handle a smaller block of aligned words.  */
3394
3395   if ((align >= 64 && bytes == 4)
3396       || (align == 32 && bytes >= 4))
3397     {
3398       words = bytes / 4;
3399
3400       for (i = 0; i < words; ++i)
3401         emit_move_insn (change_address (orig_dst, SImode,
3402                                         plus_constant (XEXP (orig_dst, 0),
3403                                                        ofs + i * 4)),
3404                         const0_rtx);
3405
3406       bytes -= words * 4;
3407       ofs += words * 4;
3408     }
3409
3410   /* An unaligned block uses stq_u stores for as many as possible.  */
3411
3412   if (bytes >= 8)
3413     {
3414       words = bytes / 8;
3415
3416       alpha_expand_unaligned_store_words (NULL, orig_dst, words, ofs);
3417
3418       bytes -= words * 8;
3419       ofs += words * 8;
3420     }
3421
3422   /* Next clean up any trailing pieces.  */
3423
3424 #if HOST_BITS_PER_WIDE_INT >= 64
3425   /* Count the number of bits in BYTES for which aligned stores could
3426      be emitted.  */
3427   words = 0;
3428   for (i = (TARGET_BWX ? 1 : 4); i * BITS_PER_UNIT <= align ; i <<= 1)
3429     if (bytes & i)
3430       words += 1;
3431
3432   /* If we have appropriate alignment (and it wouldn't take too many
3433      instructions otherwise), mask out the bytes we need.  */
3434   if (TARGET_BWX ? words > 2 : bytes > 0)
3435     {
3436       if (align >= 64)
3437         {
3438           rtx mem, tmp;
3439           HOST_WIDE_INT mask;
3440
3441           mem = change_address (orig_dst, DImode,
3442                                 plus_constant (XEXP (orig_dst, 0), ofs));
3443           MEM_ALIAS_SET (mem) = 0;
3444
3445           mask = ~(HOST_WIDE_INT)0 << (bytes * 8);
3446
3447           tmp = expand_binop (DImode, and_optab, mem, GEN_INT (mask),
3448                               NULL_RTX, 1, OPTAB_WIDEN);
3449
3450           emit_move_insn (mem, tmp);
3451           return 1;
3452         }
3453       else if (align >= 32 && bytes < 4)
3454         {
3455           rtx mem, tmp;
3456           HOST_WIDE_INT mask;
3457
3458           mem = change_address (orig_dst, SImode,
3459                                 plus_constant (XEXP (orig_dst, 0), of