OSDN Git Service

* alpha.c (reg_or_6bit_operand): Remove CONSTANT_P_RTX handling.
[pf3gnuchains/gcc-fork.git] / gcc / config / alpha / alpha.c
1 /* Subroutines used for code generation on the DEC Alpha.
2    Copyright (C) 1992, 93, 94, 95, 96, 97, 1998 Free Software Foundation, Inc.
3    Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
4
5 This file is part of GNU CC.
6
7 GNU CC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
12 GNU CC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GNU CC; see the file COPYING.  If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA.  */
21
22
23 #include "config.h"
24 #include "system.h"
25 #include "rtl.h"
26 #include "regs.h"
27 #include "hard-reg-set.h"
28 #include "real.h"
29 #include "insn-config.h"
30 #include "conditions.h"
31 #include "insn-flags.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
44 /* External data.  */
45 extern char *version_string;
46 extern int rtx_equal_function_value_matters;
47
48 /* Specify which cpu to schedule for. */
49
50 enum processor_type alpha_cpu;
51 static char* const alpha_cpu_name[] = 
52 {
53   "ev4", "ev5", "ev6"
54 };
55
56 /* Specify how accurate floating-point traps need to be.  */
57
58 enum alpha_trap_precision alpha_tp;
59
60 /* Specify the floating-point rounding mode.  */
61
62 enum alpha_fp_rounding_mode alpha_fprm;
63
64 /* Specify which things cause traps.  */
65
66 enum alpha_fp_trap_mode alpha_fptm;
67
68 /* Strings decoded into the above options.  */
69
70 char *alpha_cpu_string;         /* -mcpu= */
71 char *alpha_tp_string;          /* -mtrap-precision=[p|s|i] */
72 char *alpha_fprm_string;        /* -mfp-rounding-mode=[n|m|c|d] */
73 char *alpha_fptm_string;        /* -mfp-trap-mode=[n|u|su|sui] */
74 char *alpha_mlat_string;        /* -mmemory-latency= */
75
76 /* Save information from a "cmpxx" operation until the branch or scc is
77    emitted.  */
78
79 rtx alpha_compare_op0, alpha_compare_op1;
80 int alpha_compare_fp_p;
81
82 /* Define the information needed to modify the epilogue for EH.  */
83
84 rtx alpha_eh_epilogue_sp_ofs;
85
86 /* Non-zero if inside of a function, because the Alpha asm can't
87    handle .files inside of functions.  */
88
89 static int inside_function = FALSE;
90
91 /* If non-null, this rtx holds the return address for the function.  */
92
93 static rtx alpha_return_addr_rtx;
94
95 /* The number of cycles of latency we should assume on memory reads.  */
96
97 int alpha_memory_latency = 3;
98
99 /* Whether the function needs the GP.  */
100
101 static int alpha_function_needs_gp;
102
103 /* The alias set for prologue/epilogue register save/restore.  */
104
105 static int alpha_sr_alias_set;
106
107 /* Declarations of static functions.  */
108 static void alpha_set_memflags_1
109   PROTO((rtx, int, int, int));
110 static rtx alpha_emit_set_const_1
111   PROTO((rtx, enum machine_mode, HOST_WIDE_INT, int));
112 static void alpha_expand_unaligned_load_words
113   PROTO((rtx *out_regs, rtx smem, HOST_WIDE_INT words, HOST_WIDE_INT ofs));
114 static void alpha_expand_unaligned_store_words
115   PROTO((rtx *out_regs, rtx smem, HOST_WIDE_INT words, HOST_WIDE_INT ofs));
116 static void alpha_sa_mask
117   PROTO((unsigned long *imaskP, unsigned long *fmaskP));
118 static int alpha_does_function_need_gp
119   PROTO((void));
120
121
122 /* Get the number of args of a function in one of two ways.  */
123 #ifdef OPEN_VMS
124 #define NUM_ARGS current_function_args_info.num_args
125 #else
126 #define NUM_ARGS current_function_args_info
127 #endif
128
129 #define REG_PV 27
130 #define REG_RA 26
131 \f
132 /* Parse target option strings. */
133
134 void
135 override_options ()
136 {
137   alpha_cpu
138     = TARGET_CPU_DEFAULT & MASK_CPU_EV6 ? PROCESSOR_EV6
139       : (TARGET_CPU_DEFAULT & MASK_CPU_EV5 ? PROCESSOR_EV5 : PROCESSOR_EV4);
140
141   if (alpha_cpu_string)
142     {
143       if (! strcmp (alpha_cpu_string, "ev4")
144           || ! strcmp (alpha_cpu_string, "21064"))
145         {
146           alpha_cpu = PROCESSOR_EV4;
147           target_flags &= ~ (MASK_BWX | MASK_CIX | MASK_MAX);
148         }
149       else if (! strcmp (alpha_cpu_string, "ev5")
150                || ! strcmp (alpha_cpu_string, "21164"))
151         {
152           alpha_cpu = PROCESSOR_EV5;
153           target_flags &= ~ (MASK_BWX | MASK_CIX | MASK_MAX);
154         }
155       else if (! strcmp (alpha_cpu_string, "ev56")
156                || ! strcmp (alpha_cpu_string, "21164a"))
157         {
158           alpha_cpu = PROCESSOR_EV5;
159           target_flags |= MASK_BWX;
160           target_flags &= ~ (MASK_CIX | MASK_MAX);
161         }
162       else if (! strcmp (alpha_cpu_string, "pca56")
163                || ! strcmp (alpha_cpu_string, "21164PC")
164                || ! strcmp (alpha_cpu_string, "21164pc"))
165         {
166           alpha_cpu = PROCESSOR_EV5;
167           target_flags |= MASK_BWX | MASK_MAX;
168           target_flags &= ~ MASK_CIX;
169         }
170       else if (! strcmp (alpha_cpu_string, "ev6")
171                || ! strcmp (alpha_cpu_string, "21264"))
172         {
173           alpha_cpu = PROCESSOR_EV6;
174           target_flags |= MASK_BWX | MASK_CIX | MASK_MAX;
175         }
176       else
177         error ("bad value `%s' for -mcpu switch", alpha_cpu_string);
178     }
179
180   alpha_tp = ALPHA_TP_PROG;
181   alpha_fprm = ALPHA_FPRM_NORM;
182   alpha_fptm = ALPHA_FPTM_N;
183
184   if (TARGET_IEEE)
185     {
186       alpha_tp = ALPHA_TP_INSN;
187       alpha_fptm = ALPHA_FPTM_SU;
188     }
189
190   if (TARGET_IEEE_WITH_INEXACT)
191     {
192       alpha_tp = ALPHA_TP_INSN;
193       alpha_fptm = ALPHA_FPTM_SUI;
194     }
195
196   if (alpha_tp_string)
197     {
198       if (! strcmp (alpha_tp_string, "p"))
199         alpha_tp = ALPHA_TP_PROG;
200       else if (! strcmp (alpha_tp_string, "f"))
201         alpha_tp = ALPHA_TP_FUNC;
202       else if (! strcmp (alpha_tp_string, "i"))
203         alpha_tp = ALPHA_TP_INSN;
204       else
205         error ("bad value `%s' for -mtrap-precision switch", alpha_tp_string);
206     }
207
208   if (alpha_fprm_string)
209     {
210       if (! strcmp (alpha_fprm_string, "n"))
211         alpha_fprm = ALPHA_FPRM_NORM;
212       else if (! strcmp (alpha_fprm_string, "m"))
213         alpha_fprm = ALPHA_FPRM_MINF;
214       else if (! strcmp (alpha_fprm_string, "c"))
215         alpha_fprm = ALPHA_FPRM_CHOP;
216       else if (! strcmp (alpha_fprm_string,"d"))
217         alpha_fprm = ALPHA_FPRM_DYN;
218       else
219         error ("bad value `%s' for -mfp-rounding-mode switch",
220                alpha_fprm_string);
221     }
222
223   if (alpha_fptm_string)
224     {
225       if (strcmp (alpha_fptm_string, "n") == 0)
226         alpha_fptm = ALPHA_FPTM_N;
227       else if (strcmp (alpha_fptm_string, "u") == 0)
228         alpha_fptm = ALPHA_FPTM_U;
229       else if (strcmp (alpha_fptm_string, "su") == 0)
230         alpha_fptm = ALPHA_FPTM_SU;
231       else if (strcmp (alpha_fptm_string, "sui") == 0)
232         alpha_fptm = ALPHA_FPTM_SUI;
233       else
234         error ("bad value `%s' for -mfp-trap-mode switch", alpha_fptm_string);
235     }
236
237   /* Do some sanity checks on the above option. */
238
239   if ((alpha_fptm == ALPHA_FPTM_SU || alpha_fptm == ALPHA_FPTM_SUI)
240       && alpha_tp != ALPHA_TP_INSN)
241     {
242       warning ("fp software completion requires -mtrap-precision=i");
243       alpha_tp = ALPHA_TP_INSN;
244     }
245
246   if (TARGET_FLOAT_VAX)
247     {
248       if (alpha_fprm == ALPHA_FPRM_MINF || alpha_fprm == ALPHA_FPRM_DYN)
249         {
250           warning ("rounding mode not supported for VAX floats");
251           alpha_fprm = ALPHA_FPRM_NORM;
252         }
253       if (alpha_fptm == ALPHA_FPTM_SUI)
254         {
255           warning ("trap mode not supported for VAX floats");
256           alpha_fptm = ALPHA_FPTM_SU;
257         }
258     }
259
260   {
261     char *end;
262     int lat;
263
264     if (!alpha_mlat_string)
265       alpha_mlat_string = "L1";
266
267     if (ISDIGIT ((unsigned char)alpha_mlat_string[0])
268         && (lat = strtol (alpha_mlat_string, &end, 10), *end == '\0'))
269       ;
270     else if ((alpha_mlat_string[0] == 'L' || alpha_mlat_string[0] == 'l')
271              && ISDIGIT ((unsigned char)alpha_mlat_string[1])
272              && alpha_mlat_string[2] == '\0')
273       {
274         static int const cache_latency[][4] = 
275         {
276           { 3, 30, -1 },        /* ev4 -- Bcache is a guess */
277           { 2, 12, 38 },        /* ev5 -- Bcache from PC164 LMbench numbers */
278           { 3, 13, -1 },        /* ev6 -- Ho hum, doesn't exist yet */
279         };
280
281         lat = alpha_mlat_string[1] - '0';
282         if (lat < 0 || lat > 3 || cache_latency[alpha_cpu][lat-1] == -1)
283           {
284             warning ("L%d cache latency unknown for %s",
285                      lat, alpha_cpu_name[alpha_cpu]);
286             lat = 3;
287           }
288         else
289           lat = cache_latency[alpha_cpu][lat-1];
290       }
291     else if (! strcmp (alpha_mlat_string, "main"))
292       {
293         /* Most current memories have about 370ns latency.  This is
294            a reasonable guess for a fast cpu.  */
295         lat = 150;
296       }
297     else
298       {
299         warning ("bad value `%s' for -mmemory-latency", alpha_mlat_string);
300         lat = 3;
301       }
302
303     alpha_memory_latency = lat;
304   }
305
306   /* Default the definition of "small data" to 8 bytes.  */
307   if (!g_switch_set)
308     g_switch_value = 8;
309
310   /* Acquire a unique set number for our register saves and restores.  */
311   alpha_sr_alias_set = new_alias_set ();
312 }
313 \f
314 /* Returns 1 if VALUE is a mask that contains full bytes of zero or ones.  */
315
316 int
317 zap_mask (value)
318      HOST_WIDE_INT value;
319 {
320   int i;
321
322   for (i = 0; i < HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR;
323        i++, value >>= 8)
324     if ((value & 0xff) != 0 && (value & 0xff) != 0xff)
325       return 0;
326
327   return 1;
328 }
329
330 /* Returns 1 if OP is either the constant zero or a register.  If a
331    register, it must be in the proper mode unless MODE is VOIDmode.  */
332
333 int
334 reg_or_0_operand (op, mode)
335       register rtx op;
336       enum machine_mode mode;
337 {
338   return op == const0_rtx || register_operand (op, mode);
339 }
340
341 /* Return 1 if OP is a constant in the range of 0-63 (for a shift) or
342    any register.  */
343
344 int
345 reg_or_6bit_operand (op, mode)
346      register rtx op;
347      enum machine_mode mode;
348 {
349   return ((GET_CODE (op) == CONST_INT
350            && (unsigned HOST_WIDE_INT) INTVAL (op) < 64)
351           || register_operand (op, mode));
352 }
353
354
355 /* Return 1 if OP is an 8-bit constant or any register.  */
356
357 int
358 reg_or_8bit_operand (op, mode)
359      register rtx op;
360      enum machine_mode mode;
361 {
362   return ((GET_CODE (op) == CONST_INT
363            && (unsigned HOST_WIDE_INT) INTVAL (op) < 0x100)
364           || register_operand (op, mode));
365 }
366
367 /* Return 1 if OP is an 8-bit constant.  */
368
369 int
370 cint8_operand (op, mode)
371      register rtx op;
372      enum machine_mode mode ATTRIBUTE_UNUSED;
373 {
374   return ((GET_CODE (op) == CONST_INT
375            && (unsigned HOST_WIDE_INT) INTVAL (op) < 0x100));
376 }
377
378 /* Return 1 if the operand is a valid second operand to an add insn.  */
379
380 int
381 add_operand (op, mode)
382      register rtx op;
383      enum machine_mode mode;
384 {
385   if (GET_CODE (op) == CONST_INT)
386     /* Constraints I, J, O and P are covered by K.  */
387     return (CONST_OK_FOR_LETTER_P (INTVAL (op), 'K')
388             || CONST_OK_FOR_LETTER_P (INTVAL (op), 'L'));
389
390   return register_operand (op, mode);
391 }
392
393 /* Return 1 if the operand is a valid second operand to a sign-extending
394    add insn.  */
395
396 int
397 sext_add_operand (op, mode)
398      register rtx op;
399      enum machine_mode mode;
400 {
401   if (GET_CODE (op) == CONST_INT)
402     return (CONST_OK_FOR_LETTER_P (INTVAL (op), 'I')
403             || CONST_OK_FOR_LETTER_P (INTVAL (op), 'O'));
404
405   return register_operand (op, mode);
406 }
407
408 /* Return 1 if OP is the constant 4 or 8.  */
409
410 int
411 const48_operand (op, mode)
412      register rtx op;
413      enum machine_mode mode ATTRIBUTE_UNUSED;
414 {
415   return (GET_CODE (op) == CONST_INT
416           && (INTVAL (op) == 4 || INTVAL (op) == 8));
417 }
418
419 /* Return 1 if OP is a valid first operand to an AND insn.  */
420
421 int
422 and_operand (op, mode)
423      register rtx op;
424      enum machine_mode mode;
425 {
426   if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == VOIDmode)
427     return (zap_mask (CONST_DOUBLE_LOW (op))
428             && zap_mask (CONST_DOUBLE_HIGH (op)));
429
430   if (GET_CODE (op) == CONST_INT)
431     return ((unsigned HOST_WIDE_INT) INTVAL (op) < 0x100
432             || (unsigned HOST_WIDE_INT) ~ INTVAL (op) < 0x100
433             || zap_mask (INTVAL (op)));
434
435   return register_operand (op, mode);
436 }
437
438 /* Return 1 if OP is a valid first operand to an IOR or XOR insn.  */
439
440 int
441 or_operand (op, mode)
442      register rtx op;
443      enum machine_mode mode;
444 {
445   if (GET_CODE (op) == CONST_INT)
446     return ((unsigned HOST_WIDE_INT) INTVAL (op) < 0x100
447             || (unsigned HOST_WIDE_INT) ~ INTVAL (op) < 0x100);
448
449   return register_operand (op, mode);
450 }
451
452 /* Return 1 if OP is a constant that is the width, in bits, of an integral
453    mode smaller than DImode.  */
454
455 int
456 mode_width_operand (op, mode)
457      register rtx op;
458      enum machine_mode mode ATTRIBUTE_UNUSED;
459 {
460   return (GET_CODE (op) == CONST_INT
461           && (INTVAL (op) == 8 || INTVAL (op) == 16
462               || INTVAL (op) == 32 || INTVAL (op) == 64));
463 }
464
465 /* Return 1 if OP is a constant that is the width of an integral machine mode
466    smaller than an integer.  */
467
468 int
469 mode_mask_operand (op, mode)
470      register rtx op;
471      enum machine_mode mode ATTRIBUTE_UNUSED;
472 {
473 #if HOST_BITS_PER_WIDE_INT == 32
474   if (GET_CODE (op) == CONST_DOUBLE)
475     return (CONST_DOUBLE_LOW (op) == -1
476             && (CONST_DOUBLE_HIGH (op) == -1
477                 || CONST_DOUBLE_HIGH (op) == 0));
478 #else
479   if (GET_CODE (op) == CONST_DOUBLE)
480     return (CONST_DOUBLE_LOW (op) == -1 && CONST_DOUBLE_HIGH (op) == 0);
481 #endif
482
483   return (GET_CODE (op) == CONST_INT
484           && (INTVAL (op) == 0xff
485               || INTVAL (op) == 0xffff
486               || INTVAL (op) == (HOST_WIDE_INT)0xffffffff
487 #if HOST_BITS_PER_WIDE_INT == 64
488               || INTVAL (op) == -1
489 #endif
490               ));
491 }
492
493 /* Return 1 if OP is a multiple of 8 less than 64.  */
494
495 int
496 mul8_operand (op, mode)
497      register rtx op;
498      enum machine_mode mode ATTRIBUTE_UNUSED;
499 {
500   return (GET_CODE (op) == CONST_INT
501           && (unsigned HOST_WIDE_INT) INTVAL (op) < 64
502           && (INTVAL (op) & 7) == 0);
503 }
504
505 /* Return 1 if OP is the constant zero in floating-point.  */
506
507 int
508 fp0_operand (op, mode)
509      register rtx op;
510      enum machine_mode mode;
511 {
512   return (GET_MODE (op) == mode
513           && GET_MODE_CLASS (mode) == MODE_FLOAT && op == CONST0_RTX (mode));
514 }
515
516 /* Return 1 if OP is the floating-point constant zero or a register.  */
517
518 int
519 reg_or_fp0_operand (op, mode)
520      register rtx op;
521      enum machine_mode mode;
522 {
523   return fp0_operand (op, mode) || register_operand (op, mode);
524 }
525
526 /* Return 1 if OP is a hard floating-point register.  */
527
528 int
529 hard_fp_register_operand (op, mode)
530      register rtx op;
531      enum machine_mode mode;
532 {
533   return ((GET_CODE (op) == REG && REGNO_REG_CLASS (REGNO (op)) == FLOAT_REGS)
534           || (GET_CODE (op) == SUBREG
535               && hard_fp_register_operand (SUBREG_REG (op), mode)));
536 }
537
538 /* Return 1 if OP is a register or a constant integer.  */
539
540
541 int
542 reg_or_cint_operand (op, mode)
543     register rtx op;
544     enum machine_mode mode;
545 {
546      return (GET_CODE (op) == CONST_INT
547              || register_operand (op, mode));
548 }
549
550 /* Return 1 if OP is something that can be reloaded into a register;
551    if it is a MEM, it need not be valid.  */
552
553 int
554 some_operand (op, mode)
555      register rtx op;
556      enum machine_mode mode;
557 {
558   if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op))
559     return 0;
560
561   switch (GET_CODE (op))
562     {
563     case REG:  case MEM:  case CONST_DOUBLE:  case CONST_INT:  case LABEL_REF:
564     case SYMBOL_REF:  case CONST:
565       return 1;
566
567     case SUBREG:
568       return some_operand (SUBREG_REG (op), VOIDmode);
569
570     default:
571       break;
572     }
573
574   return 0;
575 }
576
577 /* Return 1 if OP is a valid operand for the source of a move insn.  */
578
579 int
580 input_operand (op, mode)
581      register rtx op;
582      enum machine_mode mode;
583 {
584   if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op))
585     return 0;
586
587   if (GET_MODE_CLASS (mode) == MODE_FLOAT && GET_MODE (op) != mode)
588     return 0;
589
590   switch (GET_CODE (op))
591     {
592     case LABEL_REF:
593     case SYMBOL_REF:
594     case CONST:
595       /* This handles both the Windows/NT and OSF cases.  */
596       return mode == ptr_mode || mode == DImode;
597
598     case REG:
599       return 1;
600
601     case SUBREG:
602       if (register_operand (op, mode))
603         return 1;
604       /* ... fall through ... */
605     case MEM:
606       return ((TARGET_BWX || (mode != HImode && mode != QImode))
607               && general_operand (op, mode));
608
609     case CONST_DOUBLE:
610       return GET_MODE_CLASS (mode) == MODE_FLOAT && op == CONST0_RTX (mode);
611
612     case CONST_INT:
613       return mode == QImode || mode == HImode || add_operand (op, mode);
614
615     default:
616       break;
617     }
618
619   return 0;
620 }
621
622 /* Return 1 if OP is a SYMBOL_REF for a function known to be in this
623    file.  */
624
625 int
626 current_file_function_operand (op, mode)
627      rtx op;
628      enum machine_mode mode ATTRIBUTE_UNUSED;
629 {
630   return (GET_CODE (op) == SYMBOL_REF
631           && ! profile_flag && ! profile_block_flag
632           && (SYMBOL_REF_FLAG (op)
633               || op == XEXP (DECL_RTL (current_function_decl), 0)));
634 }
635
636 /* Return 1 if OP is a valid operand for the MEM of a CALL insn.  */
637
638 int
639 call_operand (op, mode)
640      rtx op;
641      enum machine_mode mode;
642 {
643   if (mode != Pmode)
644     return 0;
645
646   return (GET_CODE (op) == SYMBOL_REF
647           || (GET_CODE (op) == REG
648               && (TARGET_OPEN_VMS || TARGET_WINDOWS_NT || REGNO (op) == 27)));
649 }
650
651 /* Return 1 if OP is a valid Alpha comparison operator.  Here we know which
652    comparisons are valid in which insn.  */
653
654 int
655 alpha_comparison_operator (op, mode)
656      register rtx op;
657      enum machine_mode mode;
658 {
659   enum rtx_code code = GET_CODE (op);
660
661   if (mode != GET_MODE (op) || GET_RTX_CLASS (code) != '<')
662     return 0;
663
664   return (code == EQ || code == LE || code == LT
665           || (mode == DImode && (code == LEU || code == LTU)));
666 }
667
668 /* Return 1 if OP is a valid Alpha swapped comparison operator.  */
669
670 int
671 alpha_swapped_comparison_operator (op, mode)
672      register rtx op;
673      enum machine_mode mode;
674 {
675   enum rtx_code code = GET_CODE (op);
676
677   if (mode != GET_MODE (op) || GET_RTX_CLASS (code) != '<')
678     return 0;
679
680   code = swap_condition (code);
681   return (code == EQ || code == LE || code == LT
682           || (mode == DImode && (code == LEU || code == LTU)));
683 }
684
685 /* Return 1 if OP is a signed comparison operation.  */
686
687 int
688 signed_comparison_operator (op, mode)
689      register rtx op;
690      enum machine_mode mode ATTRIBUTE_UNUSED;
691 {
692   switch (GET_CODE (op))
693     {
694     case EQ:  case NE:  case LE:  case LT:  case GE:   case GT:
695       return 1;
696
697     default:
698       break;
699     }
700
701   return 0;
702 }
703
704 /* Return 1 if this is a divide or modulus operator.  */
705
706 int
707 divmod_operator (op, mode)
708      register rtx op;
709      enum machine_mode mode ATTRIBUTE_UNUSED;
710 {
711   switch (GET_CODE (op))
712     {
713     case DIV:  case MOD:  case UDIV:  case UMOD:
714       return 1;
715
716     default:
717       break;
718     }
719
720   return 0;
721 }
722
723 /* Return 1 if this memory address is a known aligned register plus
724    a constant.  It must be a valid address.  This means that we can do
725    this as an aligned reference plus some offset.
726
727    Take into account what reload will do.
728
729    We could say that out-of-range stack slots are alignable, but that would
730    complicate get_aligned_mem and it isn't worth the trouble since few
731    functions have large stack space.  */
732
733 int
734 aligned_memory_operand (op, mode)
735      register rtx op;
736      enum machine_mode mode;
737 {
738   if (GET_CODE (op) == SUBREG)
739     {
740       if (GET_MODE (op) != mode)
741         return 0;
742       op = SUBREG_REG (op);
743       mode = GET_MODE (op);
744     }
745
746   if (reload_in_progress && GET_CODE (op) == REG
747       && REGNO (op) >= FIRST_PSEUDO_REGISTER)
748     op = reg_equiv_mem[REGNO (op)];
749
750   if (GET_CODE (op) != MEM || GET_MODE (op) != mode
751       || ! memory_address_p (mode, XEXP (op, 0)))
752     return 0;
753
754   op = XEXP (op, 0);
755
756   if (GET_CODE (op) == PLUS)
757     op = XEXP (op, 0);
758
759   return (GET_CODE (op) == REG
760           && REGNO_POINTER_ALIGN (REGNO (op)) >= 4);
761 }
762
763 /* Similar, but return 1 if OP is a MEM which is not alignable.  */
764
765 int
766 unaligned_memory_operand (op, mode)
767      register rtx op;
768      enum machine_mode mode;
769 {
770   if (GET_CODE (op) == SUBREG)
771     {
772       if (GET_MODE (op) != mode)
773         return 0;
774       op = SUBREG_REG (op);
775       mode = GET_MODE (op);
776     }
777
778   if (reload_in_progress && GET_CODE (op) == REG
779       && REGNO (op) >= FIRST_PSEUDO_REGISTER)
780     op = reg_equiv_mem[REGNO (op)];
781
782   if (GET_CODE (op) != MEM || GET_MODE (op) != mode)
783     return 0;
784
785   op = XEXP (op, 0);
786
787   if (! memory_address_p (mode, op))
788     return 1;
789
790   if (GET_CODE (op) == PLUS)
791     op = XEXP (op, 0);
792
793   return (GET_CODE (op) != REG
794           || REGNO_POINTER_ALIGN (REGNO (op)) < 4);
795 }
796
797 /* Return 1 if OP is either a register or an unaligned memory location.  */
798
799 int
800 reg_or_unaligned_mem_operand (op, mode)
801      rtx op;
802      enum machine_mode mode;
803 {
804   return register_operand (op, mode) || unaligned_memory_operand (op, mode);
805 }
806
807 /* Return 1 if OP is any memory location.  During reload a pseudo matches.  */
808
809 int
810 any_memory_operand (op, mode)
811      register rtx op;
812      enum machine_mode mode ATTRIBUTE_UNUSED;
813 {
814   return (GET_CODE (op) == MEM
815           || (GET_CODE (op) == SUBREG && GET_CODE (SUBREG_REG (op)) == REG)
816           || (reload_in_progress && GET_CODE (op) == REG
817               && REGNO (op) >= FIRST_PSEUDO_REGISTER)
818           || (reload_in_progress && GET_CODE (op) == SUBREG
819               && GET_CODE (SUBREG_REG (op)) == REG
820               && REGNO (SUBREG_REG (op)) >= FIRST_PSEUDO_REGISTER));
821 }
822
823 /* Returns 1 if OP is not an eliminable register.
824
825    This exists to cure a pathological abort in the s8addq (et al) patterns,
826
827         long foo () { long t; bar(); return (long) &t * 26107; }
828
829    which run afoul of a hack in reload to cure a (presumably) similar
830    problem with lea-type instructions on other targets.  But there is
831    one of us and many of them, so work around the problem by selectively
832    preventing combine from making the optimization.  */
833
834 int
835 reg_not_elim_operand (op, mode)
836       register rtx op;
837       enum machine_mode mode;
838 {
839   rtx inner = op;
840   if (GET_CODE (op) == SUBREG)
841     inner = SUBREG_REG (op);
842   if (inner == frame_pointer_rtx || inner == arg_pointer_rtx)
843     return 0;
844
845   return register_operand (op, mode);
846 }
847 \f
848 /* Return 1 if this function can directly return via $26.  */
849
850 int
851 direct_return ()
852 {
853   return (! TARGET_OPEN_VMS && reload_completed && alpha_sa_size () == 0
854           && get_frame_size () == 0
855           && current_function_outgoing_args_size == 0
856           && current_function_pretend_args_size == 0);
857 }
858
859 /* REF is an alignable memory location.  Place an aligned SImode
860    reference into *PALIGNED_MEM and the number of bits to shift into
861    *PBITNUM.  */
862
863 void
864 get_aligned_mem (ref, paligned_mem, pbitnum)
865      rtx ref;
866      rtx *paligned_mem, *pbitnum;
867 {
868   rtx base;
869   HOST_WIDE_INT offset = 0;
870
871   if (GET_CODE (ref) == SUBREG)
872     {
873       offset = SUBREG_WORD (ref) * UNITS_PER_WORD;
874       if (BYTES_BIG_ENDIAN)
875         offset -= (MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (ref)))
876                    - MIN (UNITS_PER_WORD,
877                           GET_MODE_SIZE (GET_MODE (SUBREG_REG (ref)))));
878       ref = SUBREG_REG (ref);
879     }
880
881   if (GET_CODE (ref) == REG)
882     ref = reg_equiv_mem[REGNO (ref)];
883
884   if (reload_in_progress)
885     base = find_replacement (&XEXP (ref, 0));
886   else
887     base = XEXP (ref, 0);
888
889   if (GET_CODE (base) == PLUS)
890     offset += INTVAL (XEXP (base, 1)), base = XEXP (base, 0);
891
892   *paligned_mem = gen_rtx_MEM (SImode, plus_constant (base, offset & ~3));
893   MEM_IN_STRUCT_P (*paligned_mem) = MEM_IN_STRUCT_P (ref);
894   MEM_VOLATILE_P (*paligned_mem) = MEM_VOLATILE_P (ref);
895   RTX_UNCHANGING_P (*paligned_mem) = RTX_UNCHANGING_P (ref);
896
897   /* Sadly, we cannot use alias sets here because we may overlap other
898      data in a different alias set.  */
899   /* MEM_ALIAS_SET (*paligned_mem) = MEM_ALIAS_SET (ref); */
900
901   *pbitnum = GEN_INT ((offset & 3) * 8);
902 }
903
904 /* Similar, but just get the address.  Handle the two reload cases.  
905    Add EXTRA_OFFSET to the address we return.  */
906
907 rtx
908 get_unaligned_address (ref, extra_offset)
909      rtx ref;
910      int extra_offset;
911 {
912   rtx base;
913   HOST_WIDE_INT offset = 0;
914
915   if (GET_CODE (ref) == SUBREG)
916     {
917       offset = SUBREG_WORD (ref) * UNITS_PER_WORD;
918       if (BYTES_BIG_ENDIAN)
919         offset -= (MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (ref)))
920                    - MIN (UNITS_PER_WORD,
921                           GET_MODE_SIZE (GET_MODE (SUBREG_REG (ref)))));
922       ref = SUBREG_REG (ref);
923     }
924
925   if (GET_CODE (ref) == REG)
926     ref = reg_equiv_mem[REGNO (ref)];
927
928   if (reload_in_progress)
929     base = find_replacement (&XEXP (ref, 0));
930   else
931     base = XEXP (ref, 0);
932
933   if (GET_CODE (base) == PLUS)
934     offset += INTVAL (XEXP (base, 1)), base = XEXP (base, 0);
935
936   return plus_constant (base, offset + extra_offset);
937 }
938 \f
939 /* Subfunction of the following function.  Update the flags of any MEM
940    found in part of X.  */
941
942 static void
943 alpha_set_memflags_1 (x, in_struct_p, volatile_p, unchanging_p)
944      rtx x;
945      int in_struct_p, volatile_p, unchanging_p;
946 {
947   int i;
948
949   switch (GET_CODE (x))
950     {
951     case SEQUENCE:
952     case PARALLEL:
953       for (i = XVECLEN (x, 0) - 1; i >= 0; i--)
954         alpha_set_memflags_1 (XVECEXP (x, 0, i), in_struct_p, volatile_p,
955                               unchanging_p);
956       break;
957
958     case INSN:
959       alpha_set_memflags_1 (PATTERN (x), in_struct_p, volatile_p,
960                             unchanging_p);
961       break;
962
963     case SET:
964       alpha_set_memflags_1 (SET_DEST (x), in_struct_p, volatile_p,
965                             unchanging_p);
966       alpha_set_memflags_1 (SET_SRC (x), in_struct_p, volatile_p,
967                             unchanging_p);
968       break;
969
970     case MEM:
971       MEM_IN_STRUCT_P (x) = in_struct_p;
972       MEM_VOLATILE_P (x) = volatile_p;
973       RTX_UNCHANGING_P (x) = unchanging_p;
974       /* Sadly, we cannot use alias sets because the extra aliasing
975          produced by the AND interferes.  Given that two-byte quantities
976          are the only thing we would be able to differentiate anyway,
977          there does not seem to be any point in convoluting the early
978          out of the alias check.  */
979       /* MEM_ALIAS_SET (x) = alias_set; */
980       break;
981
982     default:
983       break;
984     }
985 }
986
987 /* Given INSN, which is either an INSN or a SEQUENCE generated to
988    perform a memory operation, look for any MEMs in either a SET_DEST or
989    a SET_SRC and copy the in-struct, unchanging, and volatile flags from
990    REF into each of the MEMs found.  If REF is not a MEM, don't do
991    anything.  */
992
993 void
994 alpha_set_memflags (insn, ref)
995      rtx insn;
996      rtx ref;
997 {
998   int in_struct_p, volatile_p, unchanging_p;
999
1000   if (GET_CODE (ref) != MEM)
1001     return;
1002
1003   in_struct_p = MEM_IN_STRUCT_P (ref);
1004   volatile_p = MEM_VOLATILE_P (ref);
1005   unchanging_p = RTX_UNCHANGING_P (ref);
1006
1007   /* This is only called from alpha.md, after having had something 
1008      generated from one of the insn patterns.  So if everything is
1009      zero, the pattern is already up-to-date.  */
1010   if (! in_struct_p && ! volatile_p && ! unchanging_p)
1011     return;
1012
1013   alpha_set_memflags_1 (insn, in_struct_p, volatile_p, unchanging_p);
1014 }
1015 \f
1016 /* Try to output insns to set TARGET equal to the constant C if it can be
1017    done in less than N insns.  Do all computations in MODE.  Returns the place
1018    where the output has been placed if it can be done and the insns have been
1019    emitted.  If it would take more than N insns, zero is returned and no
1020    insns and emitted.  */
1021
1022 rtx
1023 alpha_emit_set_const (target, mode, c, n)
1024      rtx target;
1025      enum machine_mode mode;
1026      HOST_WIDE_INT c;
1027      int n;
1028 {
1029   rtx pat;
1030   int i;
1031
1032   /* Try 1 insn, then 2, then up to N. */
1033   for (i = 1; i <= n; i++)
1034     if ((pat = alpha_emit_set_const_1 (target, mode, c, i)) != 0)
1035       return pat;
1036
1037   return 0;
1038 }
1039
1040 /* Internal routine for the above to check for N or below insns.  */
1041
1042 static rtx
1043 alpha_emit_set_const_1 (target, mode, c, n)
1044      rtx target;
1045      enum machine_mode mode;
1046      HOST_WIDE_INT c;
1047      int n;
1048 {
1049   HOST_WIDE_INT new = c;
1050   int i, bits;
1051   /* Use a pseudo if highly optimizing and still generating RTL.  */
1052   rtx subtarget
1053     = (flag_expensive_optimizations && rtx_equal_function_value_matters
1054        ? 0 : target);
1055   rtx temp;
1056
1057 #if HOST_BITS_PER_WIDE_INT == 64
1058   /* We are only called for SImode and DImode.  If this is SImode, ensure that
1059      we are sign extended to a full word.  This does not make any sense when
1060      cross-compiling on a narrow machine.  */
1061
1062   if (mode == SImode)
1063     c = (c & 0xffffffff) - 2 * (c & 0x80000000);
1064 #endif
1065
1066   /* If this is a sign-extended 32-bit constant, we can do this in at most
1067      three insns, so do it if we have enough insns left.  We always have
1068      a sign-extended 32-bit constant when compiling on a narrow machine.   */
1069
1070   if (HOST_BITS_PER_WIDE_INT != 64
1071       || c >> 31 == -1 || c >> 31 == 0)
1072     {
1073       HOST_WIDE_INT low = (c & 0xffff) - 2 * (c & 0x8000);
1074       HOST_WIDE_INT tmp1 = c - low;
1075       HOST_WIDE_INT high
1076         = ((tmp1 >> 16) & 0xffff) - 2 * ((tmp1 >> 16) & 0x8000);
1077       HOST_WIDE_INT extra = 0;
1078
1079       /* If HIGH will be interpreted as negative but the constant is
1080          positive, we must adjust it to do two ldha insns.  */
1081
1082       if ((high & 0x8000) != 0 && c >= 0)
1083         {
1084           extra = 0x4000;
1085           tmp1 -= 0x40000000;
1086           high = ((tmp1 >> 16) & 0xffff) - 2 * ((tmp1 >> 16) & 0x8000);
1087         }
1088
1089       if (c == low || (low == 0 && extra == 0))
1090         {
1091           /* We used to use copy_to_suggested_reg (GEN_INT (c), target, mode)
1092              but that meant that we can't handle INT_MIN on 32-bit machines
1093              (like NT/Alpha), because we recurse indefinitely through 
1094              emit_move_insn to gen_movdi.  So instead, since we know exactly
1095              what we want, create it explicitly.  */
1096
1097           if (target == NULL)
1098             target = gen_reg_rtx (mode);
1099           emit_insn (gen_rtx_SET (VOIDmode, target, GEN_INT (c)));
1100           return target;
1101         }
1102       else if (n >= 2 + (extra != 0))
1103         {
1104           temp = copy_to_suggested_reg (GEN_INT (low), subtarget, mode);
1105
1106           if (extra != 0)
1107             temp = expand_binop (mode, add_optab, temp, GEN_INT (extra << 16),
1108                                  subtarget, 0, OPTAB_WIDEN);
1109
1110           return expand_binop (mode, add_optab, temp, GEN_INT (high << 16),
1111                                target, 0, OPTAB_WIDEN);
1112         }
1113     }
1114
1115   /* If we couldn't do it that way, try some other methods.  But if we have
1116      no instructions left, don't bother.  Likewise, if this is SImode and
1117      we can't make pseudos, we can't do anything since the expand_binop
1118      and expand_unop calls will widen and try to make pseudos.  */
1119
1120   if (n == 1
1121       || (mode == SImode && ! rtx_equal_function_value_matters))
1122     return 0;
1123
1124 #if HOST_BITS_PER_WIDE_INT == 64
1125   /* First, see if can load a value into the target that is the same as the
1126      constant except that all bytes that are 0 are changed to be 0xff.  If we
1127      can, then we can do a ZAPNOT to obtain the desired constant.  */
1128
1129   for (i = 0; i < 64; i += 8)
1130     if ((new & ((HOST_WIDE_INT) 0xff << i)) == 0)
1131       new |= (HOST_WIDE_INT) 0xff << i;
1132
1133   /* We are only called for SImode and DImode.  If this is SImode, ensure that
1134      we are sign extended to a full word.  */
1135
1136   if (mode == SImode)
1137     new = (new & 0xffffffff) - 2 * (new & 0x80000000);
1138
1139   if (new != c
1140       && (temp = alpha_emit_set_const (subtarget, mode, new, n - 1)) != 0)
1141     return expand_binop (mode, and_optab, temp, GEN_INT (c | ~ new),
1142                          target, 0, OPTAB_WIDEN);
1143 #endif
1144
1145   /* Next, see if we can load a related constant and then shift and possibly
1146      negate it to get the constant we want.  Try this once each increasing
1147      numbers of insns.  */
1148
1149   for (i = 1; i < n; i++)
1150     {
1151       /* First try complementing.  */
1152       if ((temp = alpha_emit_set_const (subtarget, mode, ~ c, i)) != 0)
1153         return expand_unop (mode, one_cmpl_optab, temp, target, 0);
1154
1155       /* Next try to form a constant and do a left shift.  We can do this
1156          if some low-order bits are zero; the exact_log2 call below tells
1157          us that information.  The bits we are shifting out could be any
1158          value, but here we'll just try the 0- and sign-extended forms of
1159          the constant.  To try to increase the chance of having the same
1160          constant in more than one insn, start at the highest number of
1161          bits to shift, but try all possibilities in case a ZAPNOT will
1162          be useful.  */
1163
1164       if ((bits = exact_log2 (c & - c)) > 0)
1165         for (; bits > 0; bits--)
1166           if ((temp = (alpha_emit_set_const
1167                        (subtarget, mode,
1168                         (unsigned HOST_WIDE_INT) (c >> bits), i))) != 0
1169               || ((temp = (alpha_emit_set_const
1170                           (subtarget, mode,
1171                            ((unsigned HOST_WIDE_INT) c) >> bits, i)))
1172                   != 0))
1173             return expand_binop (mode, ashl_optab, temp, GEN_INT (bits),
1174                                  target, 0, OPTAB_WIDEN);
1175
1176       /* Now try high-order zero bits.  Here we try the shifted-in bits as
1177          all zero and all ones.  Be careful to avoid shifting outside the
1178          mode and to avoid shifting outside the host wide int size.  */
1179       /* On narrow hosts, don't shift a 1 into the high bit, since we'll
1180          confuse the recursive call and set all of the high 32 bits.  */
1181
1182       if ((bits = (MIN (HOST_BITS_PER_WIDE_INT, GET_MODE_SIZE (mode) * 8)
1183                    - floor_log2 (c) - 1 - (HOST_BITS_PER_WIDE_INT < 64))) > 0)
1184         for (; bits > 0; bits--)
1185           if ((temp = alpha_emit_set_const (subtarget, mode,
1186                                             c << bits, i)) != 0
1187               || ((temp = (alpha_emit_set_const
1188                            (subtarget, mode,
1189                             ((c << bits) | (((HOST_WIDE_INT) 1 << bits) - 1)),
1190                             i)))
1191                   != 0))
1192             return expand_binop (mode, lshr_optab, temp, GEN_INT (bits),
1193                                  target, 1, OPTAB_WIDEN);
1194
1195       /* Now try high-order 1 bits.  We get that with a sign-extension.
1196          But one bit isn't enough here.  Be careful to avoid shifting outside
1197          the mode and to avoid shifting outside the host wide int size. */
1198       
1199       if ((bits = (MIN (HOST_BITS_PER_WIDE_INT, GET_MODE_SIZE (mode) * 8)
1200                    - floor_log2 (~ c) - 2)) > 0)
1201         for (; bits > 0; bits--)
1202           if ((temp = alpha_emit_set_const (subtarget, mode,
1203                                             c << bits, i)) != 0
1204               || ((temp = (alpha_emit_set_const
1205                            (subtarget, mode,
1206                             ((c << bits) | (((HOST_WIDE_INT) 1 << bits) - 1)),
1207                             i)))
1208                   != 0))
1209             return expand_binop (mode, ashr_optab, temp, GEN_INT (bits),
1210                                  target, 0, OPTAB_WIDEN);
1211     }
1212
1213   return 0;
1214 }
1215
1216 /* Having failed to find a 3 insn sequence in alpha_emit_set_const,
1217    fall back to a straight forward decomposition.  We do this to avoid
1218    exponential run times encountered when looking for longer sequences
1219    with alpha_emit_set_const.  */
1220
1221 rtx
1222 alpha_emit_set_long_const (target, c1, c2)
1223      rtx target;
1224      HOST_WIDE_INT c1, c2;
1225 {
1226   HOST_WIDE_INT d1, d2, d3, d4;
1227
1228   /* Decompose the entire word */
1229 #if HOST_BITS_PER_WIDE_INT >= 64
1230   if (c2 != -(c1 < 0))
1231     abort ();
1232   d1 = ((c1 & 0xffff) ^ 0x8000) - 0x8000;
1233   c1 -= d1;
1234   d2 = ((c1 & 0xffffffff) ^ 0x80000000) - 0x80000000;
1235   c1 = (c1 - d2) >> 32;
1236   d3 = ((c1 & 0xffff) ^ 0x8000) - 0x8000;
1237   c1 -= d3;
1238   d4 = ((c1 & 0xffffffff) ^ 0x80000000) - 0x80000000;
1239   if (c1 != d4)
1240     abort ();
1241 #else
1242   d1 = ((c1 & 0xffff) ^ 0x8000) - 0x8000;
1243   c1 -= d1;
1244   d2 = ((c1 & 0xffffffff) ^ 0x80000000) - 0x80000000;
1245   if (c1 != d2)
1246     abort ();
1247   c2 += (d2 < 0);
1248   d3 = ((c2 & 0xffff) ^ 0x8000) - 0x8000;
1249   c2 -= d3;
1250   d4 = ((c2 & 0xffffffff) ^ 0x80000000) - 0x80000000;
1251   if (c2 != d4)
1252     abort ();
1253 #endif
1254
1255   /* Construct the high word */
1256   if (d4)
1257     {
1258       emit_move_insn (target, GEN_INT (d4));
1259       if (d3)
1260         emit_move_insn (target, gen_rtx_PLUS (DImode, target, GEN_INT (d3)));
1261     }
1262   else
1263     emit_move_insn (target, GEN_INT (d3));
1264
1265   /* Shift it into place */
1266   emit_move_insn (target, gen_rtx_ASHIFT (DImode, target, GEN_INT (32)));
1267
1268   /* Add in the low bits.  */
1269   if (d2)
1270     emit_move_insn (target, gen_rtx_PLUS (DImode, target, GEN_INT (d2)));
1271   if (d1)
1272     emit_move_insn (target, gen_rtx_PLUS (DImode, target, GEN_INT (d1)));
1273
1274   return target;
1275 }
1276
1277 /* Generate the comparison for a conditional branch.  */
1278
1279 rtx
1280 alpha_emit_conditional_branch (code)
1281      enum rtx_code code;
1282 {
1283   enum rtx_code cmp_code, branch_code;
1284   enum machine_mode cmp_mode, branch_mode = VOIDmode;
1285   rtx op0 = alpha_compare_op0, op1 = alpha_compare_op1;
1286   rtx tem;
1287
1288   /* The general case: fold the comparison code to the types of compares
1289      that we have, choosing the branch as necessary.  */
1290   switch (code)
1291     {
1292     case EQ:  case LE:  case LT:  case LEU:  case LTU:
1293       /* We have these compares: */
1294       cmp_code = code, branch_code = NE;
1295       break;
1296
1297     case NE:
1298       /* This must be reversed. */
1299       cmp_code = EQ, branch_code = EQ;
1300       break;
1301
1302     case GE:  case GT: case GEU:  case GTU:
1303       /* For FP, we swap them, for INT, we reverse them.  */
1304       if (alpha_compare_fp_p)
1305         {
1306           cmp_code = swap_condition (code);
1307           branch_code = NE;
1308           tem = op0, op0 = op1, op1 = tem;
1309         }
1310       else
1311         {
1312           cmp_code = reverse_condition (code);
1313           branch_code = EQ;
1314         }
1315       break;
1316
1317     default:
1318       abort ();
1319     }
1320
1321   if (alpha_compare_fp_p)
1322     {
1323       cmp_mode = DFmode;
1324       if (flag_fast_math)
1325         {
1326           /* When we are not as concerned about non-finite values, and we
1327              are comparing against zero, we can branch directly.  */
1328           if (op1 == CONST0_RTX (DFmode))
1329             cmp_code = NIL, branch_code = code;
1330           else if (op0 == CONST0_RTX (DFmode))
1331             {
1332               /* Undo the swap we probably did just above.  */
1333               tem = op0, op0 = op1, op1 = tem;
1334               branch_code = swap_condition (cmp_code);
1335               cmp_code = NIL;
1336             }
1337         }
1338       else
1339         {
1340           /* ??? We mark the the branch mode to be CCmode to prevent the
1341              compare and branch from being combined, since the compare 
1342              insn follows IEEE rules that the branch does not.  */
1343           branch_mode = CCmode;
1344         }
1345     }
1346   else
1347     {
1348       cmp_mode = DImode;
1349
1350       /* The following optimizations are only for signed compares.  */
1351       if (code != LEU && code != LTU && code != GEU && code != GTU)
1352         {
1353           /* Whee.  Compare and branch against 0 directly.  */
1354           if (op1 == const0_rtx)
1355             cmp_code = NIL, branch_code = code;
1356
1357           /* We want to use cmpcc/bcc when we can, since there is a zero delay
1358              bypass between logicals and br/cmov on EV5.  But we don't want to
1359              force valid immediate constants into registers needlessly.  */
1360           else if (GET_CODE (op1) == CONST_INT)
1361             {
1362               HOST_WIDE_INT v = INTVAL (op1), n = -v;
1363
1364               if (! CONST_OK_FOR_LETTER_P (v, 'I')
1365                   && (CONST_OK_FOR_LETTER_P (n, 'K')
1366                       || CONST_OK_FOR_LETTER_P (n, 'L')))
1367                 {
1368                   cmp_code = PLUS, branch_code = code;
1369                   op1 = GEN_INT (n);
1370                 }
1371             }
1372         }
1373     }
1374
1375   /* Force op0 into a register.  */
1376   if (GET_CODE (op0) != REG)
1377     op0 = force_reg (cmp_mode, op0);
1378
1379   /* Emit an initial compare instruction, if necessary.  */
1380   tem = op0;
1381   if (cmp_code != NIL)
1382     {
1383       tem = gen_reg_rtx (cmp_mode);
1384       emit_move_insn (tem, gen_rtx_fmt_ee (cmp_code, cmp_mode, op0, op1));
1385     }
1386
1387   /* Return the branch comparison.  */
1388   return gen_rtx_fmt_ee (branch_code, branch_mode, tem, CONST0_RTX (cmp_mode));
1389 }
1390
1391
1392 /* Rewrite a comparison against zero CMP of the form
1393    (CODE (cc0) (const_int 0)) so it can be written validly in
1394    a conditional move (if_then_else CMP ...).
1395    If both of the operands that set cc0 are non-zero we must emit
1396    an insn to perform the compare (it can't be done within
1397    the conditional move). */
1398 rtx
1399 alpha_emit_conditional_move (cmp, mode)
1400      rtx cmp;
1401      enum machine_mode mode;
1402 {
1403   enum rtx_code code = GET_CODE (cmp);
1404   enum rtx_code cmov_code = NE;
1405   rtx op0 = alpha_compare_op0;
1406   rtx op1 = alpha_compare_op1;
1407   enum machine_mode cmp_mode
1408     = (GET_MODE (op0) == VOIDmode ? DImode : GET_MODE (op0));
1409   enum machine_mode cmp_op_mode = alpha_compare_fp_p ? DFmode : DImode;
1410   enum machine_mode cmov_mode = VOIDmode;
1411   rtx tem;
1412
1413   if (alpha_compare_fp_p != FLOAT_MODE_P (mode))
1414     return 0;
1415
1416   /* We may be able to use a conditional move directly.
1417      This avoids emitting spurious compares. */
1418   if (signed_comparison_operator (cmp, cmp_op_mode)
1419       && (!alpha_compare_fp_p || flag_fast_math)
1420       && (op0 == CONST0_RTX (cmp_mode) || op1 == CONST0_RTX (cmp_mode)))
1421     return gen_rtx_fmt_ee (code, VOIDmode, op0, op1);
1422
1423   /* We can't put the comparison insides a conditional move;
1424      emit a compare instruction and put that inside the
1425      conditional move.  Make sure we emit only comparisons we have;
1426      swap or reverse as necessary.  */
1427
1428   switch (code)
1429     {
1430     case EQ:  case LE:  case LT:  case LEU:  case LTU:
1431       /* We have these compares: */
1432       break;
1433
1434     case NE:
1435       /* This must be reversed. */
1436       code = reverse_condition (code);
1437       cmov_code = EQ;
1438       break;
1439
1440     case GE:  case GT:  case GEU:  case GTU:
1441       /* These must be swapped.  Make sure the new first operand is in
1442          a register.  */
1443       code = swap_condition (code);
1444       tem = op0, op0 = op1, op1 = tem;
1445       op0 = force_reg (cmp_mode, op0);
1446       break;
1447
1448     default:
1449       abort ();
1450     }
1451
1452   /* ??? We mark the branch mode to be CCmode to prevent the compare
1453      and cmov from being combined, since the compare insn follows IEEE
1454      rules that the cmov does not.  */
1455   if (alpha_compare_fp_p && !flag_fast_math)
1456     cmov_mode = CCmode;
1457
1458   tem = gen_reg_rtx (cmp_op_mode);
1459   emit_move_insn (tem, gen_rtx_fmt_ee (code, cmp_op_mode, op0, op1));
1460   return gen_rtx_fmt_ee (cmov_code, cmov_mode, tem, CONST0_RTX (cmp_op_mode));
1461 }
1462 \f
1463 /* Use ext[wlq][lh] as the Architecture Handbook describes for extracting
1464    unaligned data:
1465
1466            unsigned:                       signed:
1467    word:   ldq_u  r1,X(r11)                ldq_u  r1,X(r11)
1468            ldq_u  r2,X+1(r11)              ldq_u  r2,X+1(r11)
1469            lda    r3,X(r11)                lda    r3,X+2(r11)
1470            extwl  r1,r3,r1                 extql  r1,r3,r1
1471            extwh  r2,r3,r2                 extqh  r2,r3,r2
1472            or     r1.r2.r1                 or     r1,r2,r1
1473                                            sra    r1,48,r1
1474
1475    long:   ldq_u  r1,X(r11)                ldq_u  r1,X(r11)
1476            ldq_u  r2,X+3(r11)              ldq_u  r2,X+3(r11)
1477            lda    r3,X(r11)                lda    r3,X(r11)
1478            extll  r1,r3,r1                 extll  r1,r3,r1
1479            extlh  r2,r3,r2                 extlh  r2,r3,r2
1480            or     r1.r2.r1                 addl   r1,r2,r1
1481
1482    quad:   ldq_u  r1,X(r11)
1483            ldq_u  r2,X+7(r11)
1484            lda    r3,X(r11)
1485            extql  r1,r3,r1
1486            extqh  r2,r3,r2
1487            or     r1.r2.r1
1488 */
1489
1490 void
1491 alpha_expand_unaligned_load (tgt, mem, size, ofs, sign)
1492      rtx tgt, mem;
1493      HOST_WIDE_INT size, ofs;
1494      int sign;
1495 {
1496   rtx meml, memh, addr, extl, exth;
1497   enum machine_mode mode;
1498
1499   meml = gen_reg_rtx (DImode);
1500   memh = gen_reg_rtx (DImode);
1501   addr = gen_reg_rtx (DImode);
1502   extl = gen_reg_rtx (DImode);
1503   exth = gen_reg_rtx (DImode);
1504
1505   emit_move_insn (meml,
1506                   change_address (mem, DImode,
1507                                   gen_rtx_AND (DImode, 
1508                                                plus_constant (XEXP (mem, 0),
1509                                                               ofs),
1510                                                GEN_INT (-8))));
1511
1512   emit_move_insn (memh,
1513                   change_address (mem, DImode,
1514                                   gen_rtx_AND (DImode, 
1515                                                plus_constant (XEXP (mem, 0),
1516                                                               ofs + size - 1),
1517                                                GEN_INT (-8))));
1518
1519   if (sign && size == 2)
1520     {
1521       emit_move_insn (addr, plus_constant (XEXP (mem, 0), ofs+2));
1522
1523       emit_insn (gen_extxl (extl, meml, GEN_INT (64), addr));
1524       emit_insn (gen_extqh (exth, memh, addr));
1525
1526       /* We must use tgt here for the target.  Alpha-vms port fails if we use
1527          addr for the target, because addr is marked as a pointer and combine
1528          knows that pointers are always sign-extended 32 bit values.  */
1529       addr = expand_binop (DImode, ior_optab, extl, exth, tgt, 1, OPTAB_WIDEN);
1530       addr = expand_binop (DImode, ashr_optab, addr, GEN_INT (48), 
1531                            addr, 1, OPTAB_WIDEN);
1532     }
1533   else
1534     {
1535       emit_move_insn (addr, plus_constant (XEXP (mem, 0), ofs));
1536       emit_insn (gen_extxl (extl, meml, GEN_INT (size*8), addr));
1537       switch (size)
1538         {
1539         case 2:
1540           emit_insn (gen_extwh (exth, memh, addr));
1541           mode = HImode;
1542           break;
1543
1544         case 4:
1545           emit_insn (gen_extlh (exth, memh, addr));
1546           mode = SImode;
1547           break;
1548
1549         case 8:
1550           emit_insn (gen_extqh (exth, memh, addr));
1551           mode = DImode;
1552           break;
1553         }
1554
1555       addr = expand_binop (mode, ior_optab, gen_lowpart (mode, extl),
1556                            gen_lowpart (mode, exth), gen_lowpart (mode, tgt),
1557                            sign, OPTAB_WIDEN);
1558     }
1559
1560   if (addr != tgt)
1561     emit_move_insn (tgt, gen_lowpart(GET_MODE (tgt), addr));
1562 }
1563
1564 /* Similarly, use ins and msk instructions to perform unaligned stores.  */
1565
1566 void
1567 alpha_expand_unaligned_store (dst, src, size, ofs)
1568      rtx dst, src;
1569      HOST_WIDE_INT size, ofs;
1570 {
1571   rtx dstl, dsth, addr, insl, insh, meml, memh;
1572   
1573   dstl = gen_reg_rtx (DImode);
1574   dsth = gen_reg_rtx (DImode);
1575   insl = gen_reg_rtx (DImode);
1576   insh = gen_reg_rtx (DImode);
1577
1578   meml = change_address (dst, DImode,
1579                          gen_rtx_AND (DImode, 
1580                                       plus_constant (XEXP (dst, 0), ofs),
1581                                       GEN_INT (-8)));
1582   memh = change_address (dst, DImode,
1583                          gen_rtx_AND (DImode, 
1584                                       plus_constant (XEXP (dst, 0),
1585                                                      ofs+size-1),
1586                                       GEN_INT (-8)));
1587
1588   emit_move_insn (dsth, memh);
1589   emit_move_insn (dstl, meml);
1590   addr = copy_addr_to_reg (plus_constant (XEXP (dst, 0), ofs));
1591
1592   if (src != const0_rtx)
1593     {
1594       emit_insn (gen_insxh (insh, gen_lowpart (DImode, src),
1595                             GEN_INT (size*8), addr));
1596
1597       switch (size)
1598         {
1599         case 2:
1600           emit_insn (gen_inswl (insl, gen_lowpart (HImode, src), addr));
1601           break;
1602         case 4:
1603           emit_insn (gen_insll (insl, gen_lowpart (SImode, src), addr));
1604           break;
1605         case 8:
1606           emit_insn (gen_insql (insl, src, addr));
1607           break;
1608         }
1609     }
1610
1611   emit_insn (gen_mskxh (dsth, dsth, GEN_INT (size*8), addr));
1612
1613   switch (size)
1614     {
1615     case 2:
1616       emit_insn (gen_mskxl (dstl, dstl, GEN_INT (0xffff), addr));
1617       break;
1618     case 4:
1619       emit_insn (gen_mskxl (dstl, dstl, GEN_INT (0xffffffff), addr));
1620       break;
1621     case 8:
1622       {
1623 #if HOST_BITS_PER_WIDE_INT == 32
1624         rtx msk = immed_double_const (0xffffffff, 0xffffffff, DImode);
1625 #else
1626         rtx msk = immed_double_const (0xffffffffffffffff, 0, DImode);
1627 #endif
1628         emit_insn (gen_mskxl (dstl, dstl, msk, addr));
1629       }
1630       break;
1631     }
1632
1633   if (src != const0_rtx)
1634     {
1635       dsth = expand_binop (DImode, ior_optab, insh, dsth, dsth, 0, OPTAB_WIDEN);
1636       dstl = expand_binop (DImode, ior_optab, insl, dstl, dstl, 0, OPTAB_WIDEN);
1637     }
1638   
1639   /* Must store high before low for degenerate case of aligned.  */
1640   emit_move_insn (memh, dsth);
1641   emit_move_insn (meml, dstl);
1642 }
1643
1644 /* The block move code tries to maximize speed by separating loads and
1645    stores at the expense of register pressure: we load all of the data
1646    before we store it back out.  There are two secondary effects worth
1647    mentioning, that this speeds copying to/from aligned and unaligned
1648    buffers, and that it makes the code significantly easier to write.  */
1649
1650 #define MAX_MOVE_WORDS  8
1651
1652 /* Load an integral number of consecutive unaligned quadwords.  */
1653
1654 static void
1655 alpha_expand_unaligned_load_words (out_regs, smem, words, ofs)
1656      rtx *out_regs;
1657      rtx smem;
1658      HOST_WIDE_INT words, ofs;
1659 {
1660   rtx const im8 = GEN_INT (-8);
1661   rtx const i64 = GEN_INT (64);
1662   rtx ext_tmps[MAX_MOVE_WORDS], data_regs[MAX_MOVE_WORDS+1];
1663   rtx sreg, areg;
1664   HOST_WIDE_INT i;
1665
1666   /* Generate all the tmp registers we need.  */
1667   for (i = 0; i < words; ++i)
1668     {
1669       data_regs[i] = out_regs[i];
1670       ext_tmps[i] = gen_reg_rtx (DImode);
1671     }
1672   data_regs[words] = gen_reg_rtx (DImode);
1673
1674   if (ofs != 0)
1675     smem = change_address (smem, GET_MODE (smem),
1676                            plus_constant (XEXP (smem, 0), ofs));
1677   
1678   /* Load up all of the source data.  */
1679   for (i = 0; i < words; ++i)
1680     {
1681       emit_move_insn (data_regs[i],
1682                       change_address (smem, DImode,
1683                                       gen_rtx_AND (DImode,
1684                                                    plus_constant (XEXP(smem,0),
1685                                                                   8*i),
1686                                                    im8)));
1687     }
1688   emit_move_insn (data_regs[words],
1689                   change_address (smem, DImode,
1690                                   gen_rtx_AND (DImode,
1691                                                plus_constant (XEXP(smem,0),
1692                                                               8*words - 1),
1693                                                im8)));
1694
1695   /* Extract the half-word fragments.  Unfortunately DEC decided to make
1696      extxh with offset zero a noop instead of zeroing the register, so 
1697      we must take care of that edge condition ourselves with cmov.  */
1698
1699   sreg = copy_addr_to_reg (XEXP (smem, 0));
1700   areg = expand_binop (DImode, and_optab, sreg, GEN_INT (7), NULL, 
1701                        1, OPTAB_WIDEN);
1702   for (i = 0; i < words; ++i)
1703     {
1704       emit_insn (gen_extxl (data_regs[i], data_regs[i], i64, sreg));
1705
1706       emit_insn (gen_extqh (ext_tmps[i], data_regs[i+1], sreg));
1707       emit_insn (gen_rtx_SET (VOIDmode, ext_tmps[i],
1708                               gen_rtx_IF_THEN_ELSE (DImode,
1709                                                     gen_rtx_EQ (DImode, areg,
1710                                                                 const0_rtx),
1711                                                     const0_rtx, ext_tmps[i])));
1712     }
1713
1714   /* Merge the half-words into whole words.  */
1715   for (i = 0; i < words; ++i)
1716     {
1717       out_regs[i] = expand_binop (DImode, ior_optab, data_regs[i],
1718                                   ext_tmps[i], data_regs[i], 1, OPTAB_WIDEN);
1719     }
1720 }
1721
1722 /* Store an integral number of consecutive unaligned quadwords.  DATA_REGS
1723    may be NULL to store zeros.  */
1724
1725 static void
1726 alpha_expand_unaligned_store_words (data_regs, dmem, words, ofs)
1727      rtx *data_regs;
1728      rtx dmem;
1729      HOST_WIDE_INT words, ofs;
1730 {
1731   rtx const im8 = GEN_INT (-8);
1732   rtx const i64 = GEN_INT (64);
1733 #if HOST_BITS_PER_WIDE_INT == 32
1734   rtx const im1 = immed_double_const (0xffffffff, 0xffffffff, DImode);
1735 #else
1736   rtx const im1 = immed_double_const (0xffffffffffffffff, 0, DImode);
1737 #endif
1738   rtx ins_tmps[MAX_MOVE_WORDS];
1739   rtx st_tmp_1, st_tmp_2, dreg;
1740   rtx st_addr_1, st_addr_2;
1741   HOST_WIDE_INT i;
1742
1743   /* Generate all the tmp registers we need.  */
1744   if (data_regs != NULL)
1745     for (i = 0; i < words; ++i)
1746       ins_tmps[i] = gen_reg_rtx(DImode);
1747   st_tmp_1 = gen_reg_rtx(DImode);
1748   st_tmp_2 = gen_reg_rtx(DImode);
1749   
1750   if (ofs != 0)
1751     dmem = change_address (dmem, GET_MODE (dmem),
1752                            plus_constant (XEXP (dmem, 0), ofs));
1753   
1754
1755   st_addr_2 = change_address (dmem, DImode,
1756                               gen_rtx_AND (DImode,
1757                                            plus_constant (XEXP(dmem,0),
1758                                                           words*8 - 1),
1759                                        im8));
1760   st_addr_1 = change_address (dmem, DImode,
1761                               gen_rtx_AND (DImode, 
1762                                            XEXP (dmem, 0),
1763                                            im8));
1764
1765   /* Load up the destination end bits.  */
1766   emit_move_insn (st_tmp_2, st_addr_2);
1767   emit_move_insn (st_tmp_1, st_addr_1);
1768
1769   /* Shift the input data into place.  */
1770   dreg = copy_addr_to_reg (XEXP (dmem, 0));
1771   if (data_regs != NULL)
1772     {
1773       for (i = words-1; i >= 0; --i)
1774         {
1775           emit_insn (gen_insxh (ins_tmps[i], data_regs[i], i64, dreg));
1776           emit_insn (gen_insql (data_regs[i], data_regs[i], dreg));
1777         }
1778       for (i = words-1; i > 0; --i)
1779         {
1780           ins_tmps[i-1] = expand_binop (DImode, ior_optab, data_regs[i],
1781                                         ins_tmps[i-1], ins_tmps[i-1], 1,
1782                                         OPTAB_WIDEN);
1783         }
1784     }
1785
1786   /* Split and merge the ends with the destination data.  */
1787   emit_insn (gen_mskxh (st_tmp_2, st_tmp_2, i64, dreg));
1788   emit_insn (gen_mskxl (st_tmp_1, st_tmp_1, im1, dreg));
1789
1790   if (data_regs != NULL)
1791     {
1792       st_tmp_2 = expand_binop (DImode, ior_optab, st_tmp_2, ins_tmps[words-1],
1793                                st_tmp_2, 1, OPTAB_WIDEN);
1794       st_tmp_1 = expand_binop (DImode, ior_optab, st_tmp_1, data_regs[0],
1795                                st_tmp_1, 1, OPTAB_WIDEN);
1796     }
1797
1798   /* Store it all.  */
1799   emit_move_insn (st_addr_2, st_tmp_2);
1800   for (i = words-1; i > 0; --i)
1801     {
1802       emit_move_insn (change_address (dmem, DImode,
1803                                       gen_rtx_AND (DImode,
1804                                                    plus_constant(XEXP (dmem,0),
1805                                                                  i*8),
1806                                                im8)),
1807                       data_regs ? ins_tmps[i-1] : const0_rtx);
1808     }
1809   emit_move_insn (st_addr_1, st_tmp_1);
1810 }
1811
1812
1813 /* Expand string/block move operations.
1814
1815    operands[0] is the pointer to the destination.
1816    operands[1] is the pointer to the source.
1817    operands[2] is the number of bytes to move.
1818    operands[3] is the alignment.  */
1819
1820 int
1821 alpha_expand_block_move (operands)
1822      rtx operands[];
1823 {
1824   rtx bytes_rtx = operands[2];
1825   rtx align_rtx = operands[3];
1826   HOST_WIDE_INT orig_bytes = INTVAL (bytes_rtx);
1827   HOST_WIDE_INT bytes = orig_bytes;
1828   HOST_WIDE_INT src_align = INTVAL (align_rtx);
1829   HOST_WIDE_INT dst_align = src_align;
1830   rtx orig_src  = operands[1];
1831   rtx orig_dst  = operands[0];
1832   rtx data_regs[2*MAX_MOVE_WORDS+16];
1833   rtx tmp;
1834   int i, words, ofs, nregs = 0;
1835   
1836   if (bytes <= 0)
1837     return 1;
1838   if (bytes > MAX_MOVE_WORDS*8)
1839     return 0;
1840
1841   /* Look for additional alignment information from recorded register info.  */
1842
1843   tmp = XEXP (orig_src, 0);
1844   if (GET_CODE (tmp) == REG)
1845     {
1846       if (REGNO_POINTER_ALIGN (REGNO (tmp)) > src_align)
1847         src_align = REGNO_POINTER_ALIGN (REGNO (tmp));
1848     }
1849   else if (GET_CODE (tmp) == PLUS
1850            && GET_CODE (XEXP (tmp, 0)) == REG
1851            && GET_CODE (XEXP (tmp, 1)) == CONST_INT)
1852     {
1853       HOST_WIDE_INT c = INTVAL (XEXP (tmp, 1));
1854       int a = REGNO_POINTER_ALIGN (REGNO (XEXP (tmp, 0)));
1855
1856       if (a > src_align)
1857         {
1858           if (a >= 8 && c % 8 == 0)
1859             src_align = 8;
1860           else if (a >= 4 && c % 4 == 0)
1861             src_align = 4;
1862           else if (a >= 2 && c % 2 == 0)
1863             src_align = 2;
1864         }
1865     }
1866         
1867   tmp = XEXP (orig_dst, 0);
1868   if (GET_CODE (tmp) == REG)
1869     {
1870       if (REGNO_POINTER_ALIGN (REGNO (tmp)) > dst_align)
1871         dst_align = REGNO_POINTER_ALIGN (REGNO (tmp));
1872     }
1873   else if (GET_CODE (tmp) == PLUS
1874            && GET_CODE (XEXP (tmp, 0)) == REG
1875            && GET_CODE (XEXP (tmp, 1)) == CONST_INT)
1876     {
1877       HOST_WIDE_INT c = INTVAL (XEXP (tmp, 1));
1878       int a = REGNO_POINTER_ALIGN (REGNO (XEXP (tmp, 0)));
1879
1880       if (a > dst_align)
1881         {
1882           if (a >= 8 && c % 8 == 0)
1883             dst_align = 8;
1884           else if (a >= 4 && c % 4 == 0)
1885             dst_align = 4;
1886           else if (a >= 2 && c % 2 == 0)
1887             dst_align = 2;
1888         }
1889     }
1890
1891   /*
1892    * Load the entire block into registers.
1893    */
1894
1895   if (GET_CODE (XEXP (orig_src, 0)) == ADDRESSOF)
1896     {
1897       enum machine_mode mode;
1898       tmp = XEXP (XEXP (orig_src, 0), 0);
1899
1900       mode = mode_for_size (bytes * BITS_PER_UNIT, MODE_INT, 1);
1901       if (mode != BLKmode
1902           && GET_MODE_SIZE (GET_MODE (tmp)) <= bytes)
1903         {
1904           /* Whee!  Optimize the load to use the existing register.  */
1905           data_regs[nregs++] = gen_lowpart (mode, tmp);
1906           goto src_done;
1907         }
1908
1909       /* ??? We could potentially be copying 3 bytes or whatnot from
1910          a wider reg.  Probably not worth worrying about.  */
1911       /* No appropriate mode; fall back on memory.  */
1912       orig_src = change_address (orig_src, GET_MODE (orig_src),
1913                                  copy_addr_to_reg (XEXP (orig_src, 0)));
1914     }
1915
1916   ofs = 0;
1917   if (src_align >= 8 && bytes >= 8)
1918     {
1919       words = bytes / 8;
1920
1921       for (i = 0; i < words; ++i)
1922         data_regs[nregs+i] = gen_reg_rtx(DImode);
1923
1924       for (i = 0; i < words; ++i)
1925         {
1926           emit_move_insn (data_regs[nregs+i],
1927                           change_address(orig_src, DImode,
1928                                          plus_constant (XEXP (orig_src, 0),
1929                                                         ofs + i*8)));
1930         }
1931
1932       nregs += words;
1933       bytes -= words * 8;
1934       ofs += words * 8;
1935     }
1936   if (src_align >= 4 && bytes >= 4)
1937     {
1938       words = bytes / 4;
1939
1940       for (i = 0; i < words; ++i)
1941         data_regs[nregs+i] = gen_reg_rtx(SImode);
1942
1943       for (i = 0; i < words; ++i)
1944         {
1945           emit_move_insn (data_regs[nregs+i],
1946                           change_address(orig_src, SImode,
1947                                          plus_constant (XEXP (orig_src, 0),
1948                                                         ofs + i*4)));
1949         }
1950
1951       nregs += words;
1952       bytes -= words * 4;
1953       ofs += words * 4;
1954     }
1955   if (bytes >= 16)
1956     {
1957       words = bytes / 8;
1958
1959       for (i = 0; i < words+1; ++i)
1960         data_regs[nregs+i] = gen_reg_rtx(DImode);
1961
1962       alpha_expand_unaligned_load_words(data_regs+nregs, orig_src, words, ofs);
1963
1964       nregs += words;
1965       bytes -= words * 8;
1966       ofs += words * 8;
1967     }
1968   if (!TARGET_BWX && bytes >= 8)
1969     {
1970       data_regs[nregs++] = tmp = gen_reg_rtx (DImode);
1971       alpha_expand_unaligned_load (tmp, orig_src, 8, ofs, 0);
1972       bytes -= 8;
1973       ofs += 8;
1974     }
1975   if (!TARGET_BWX && bytes >= 4)
1976     {
1977       data_regs[nregs++] = tmp = gen_reg_rtx (SImode);
1978       alpha_expand_unaligned_load (tmp, orig_src, 4, ofs, 0);
1979       bytes -= 4;
1980       ofs += 4;
1981     }
1982   if (bytes >= 2)
1983     {
1984       if (src_align >= 2)
1985         {
1986           do {
1987             data_regs[nregs++] = tmp = gen_reg_rtx (HImode);
1988             emit_move_insn (tmp,
1989                             change_address (orig_src, HImode,
1990                                             plus_constant (XEXP (orig_src, 0),
1991                                                            ofs)));
1992             bytes -= 2;
1993             ofs += 2;
1994           } while (bytes >= 2);
1995         }
1996       else if (!TARGET_BWX)
1997         {
1998           data_regs[nregs++] = tmp = gen_reg_rtx (HImode);
1999           alpha_expand_unaligned_load (tmp, orig_src, 2, ofs, 0);
2000           bytes -= 2;
2001           ofs += 2;
2002         }
2003     }
2004   while (bytes > 0)
2005     {
2006       data_regs[nregs++] = tmp = gen_reg_rtx (QImode);
2007       emit_move_insn (tmp,
2008                       change_address (orig_src, QImode,
2009                                       plus_constant (XEXP (orig_src, 0),
2010                                                      ofs)));
2011       bytes -= 1;
2012       ofs += 1;
2013     }
2014  src_done:
2015
2016   if (nregs > (int)(sizeof(data_regs)/sizeof(*data_regs)))
2017     abort();
2018
2019   /*
2020    * Now save it back out again.
2021    */
2022
2023   i = 0, ofs = 0;
2024
2025   if (GET_CODE (XEXP (orig_dst, 0)) == ADDRESSOF)
2026     {
2027       enum machine_mode mode;
2028       tmp = XEXP (XEXP (orig_dst, 0), 0);
2029
2030       mode = mode_for_size (orig_bytes * BITS_PER_UNIT, MODE_INT, 1);
2031       if (GET_MODE (tmp) == mode && nregs == 1)
2032         {
2033           emit_move_insn (tmp, data_regs[0]);
2034           i = 1;
2035           goto dst_done;
2036         }
2037
2038       /* ??? If nregs > 1, consider reconstructing the word in regs.  */
2039       /* ??? Optimize mode < dst_mode with strict_low_part.  */
2040
2041       /* No appropriate mode; fall back on memory.  We can speed things
2042          up by recognizing extra alignment information.  */
2043       orig_dst = change_address (orig_dst, GET_MODE (orig_dst),
2044                                  copy_addr_to_reg (XEXP (orig_dst, 0)));
2045       dst_align = GET_MODE_SIZE (GET_MODE (tmp));
2046     }
2047
2048   /* Write out the data in whatever chunks reading the source allowed.  */
2049   if (dst_align >= 8)
2050     {
2051       while (i < nregs && GET_MODE (data_regs[i]) == DImode)
2052         {
2053           emit_move_insn (change_address(orig_dst, DImode,
2054                                          plus_constant (XEXP (orig_dst, 0),
2055                                                         ofs)),
2056                           data_regs[i]);
2057           ofs += 8;
2058           i++;
2059         }
2060     }
2061   if (dst_align >= 4)
2062     {
2063       /* If the source has remaining DImode regs, write them out in
2064          two pieces.  */
2065       while (i < nregs && GET_MODE (data_regs[i]) == DImode)
2066         {
2067           tmp = expand_binop (DImode, lshr_optab, data_regs[i], GEN_INT (32),
2068                               NULL_RTX, 1, OPTAB_WIDEN);
2069
2070           emit_move_insn (change_address(orig_dst, SImode,
2071                                          plus_constant (XEXP (orig_dst, 0),
2072                                                         ofs)),
2073                           gen_lowpart (SImode, data_regs[i]));
2074           emit_move_insn (change_address(orig_dst, SImode,
2075                                          plus_constant (XEXP (orig_dst, 0),
2076                                                         ofs+4)),
2077                           gen_lowpart (SImode, tmp));
2078           ofs += 8;
2079           i++;
2080         }
2081
2082       while (i < nregs && GET_MODE (data_regs[i]) == SImode)
2083         {
2084           emit_move_insn (change_address(orig_dst, SImode,
2085                                          plus_constant (XEXP (orig_dst, 0),
2086                                                         ofs)),
2087                           data_regs[i]);
2088           ofs += 4;
2089           i++;
2090         }
2091     }
2092   if (i < nregs && GET_MODE (data_regs[i]) == DImode)
2093     {
2094       /* Write out a remaining block of words using unaligned methods.  */
2095
2096       for (words = 1; i+words < nregs ; ++words)
2097         if (GET_MODE (data_regs[i+words]) != DImode)
2098           break;
2099
2100       if (words == 1)
2101         alpha_expand_unaligned_store (orig_dst, data_regs[i], 8, ofs);
2102       else
2103         alpha_expand_unaligned_store_words (data_regs+i, orig_dst, words, ofs);
2104      
2105       i += words;
2106       ofs += words * 8;
2107     }
2108
2109   /* Due to the above, this won't be aligned.  */
2110   /* ??? If we have more than one of these, consider constructing full
2111      words in registers and using alpha_expand_unaligned_store_words.  */
2112   while (i < nregs && GET_MODE (data_regs[i]) == SImode)
2113     {
2114       alpha_expand_unaligned_store (orig_dst, data_regs[i], 4, ofs);
2115       ofs += 4;
2116       i++;
2117     }
2118
2119   if (dst_align >= 2)
2120     while (i < nregs && GET_MODE (data_regs[i]) == HImode)
2121       {
2122         emit_move_insn (change_address (orig_dst, HImode,
2123                                         plus_constant (XEXP (orig_dst, 0),
2124                                                        ofs)),
2125                         data_regs[i]);
2126         i++;
2127         ofs += 2;
2128       }
2129   else
2130     while (i < nregs && GET_MODE (data_regs[i]) == HImode)
2131       {
2132         alpha_expand_unaligned_store (orig_dst, data_regs[i], 2, ofs);
2133         i++;
2134         ofs += 2;
2135       }
2136   while (i < nregs && GET_MODE (data_regs[i]) == QImode)
2137     {
2138       emit_move_insn (change_address (orig_dst, QImode,
2139                                       plus_constant (XEXP (orig_dst, 0),
2140                                                      ofs)),
2141                       data_regs[i]);
2142       i++;
2143       ofs += 1;
2144     }
2145  dst_done:
2146
2147   if (i != nregs)
2148     abort();
2149
2150   return 1;
2151 }
2152
2153 int
2154 alpha_expand_block_clear (operands)
2155      rtx operands[];
2156 {
2157   rtx bytes_rtx = operands[1];
2158   rtx align_rtx = operands[2];
2159   HOST_WIDE_INT bytes = INTVAL (bytes_rtx);
2160   HOST_WIDE_INT align = INTVAL (align_rtx);
2161   rtx orig_dst  = operands[0];
2162   rtx tmp;
2163   HOST_WIDE_INT i, words, ofs = 0;
2164   
2165   if (bytes <= 0)
2166     return 1;
2167   if (bytes > MAX_MOVE_WORDS*8)
2168     return 0;
2169
2170   /* Look for stricter alignment.  */
2171
2172   tmp = XEXP (orig_dst, 0);
2173   if (GET_CODE (tmp) == REG)
2174     {
2175       if (REGNO_POINTER_ALIGN (REGNO (tmp)) > align)
2176         align = REGNO_POINTER_ALIGN (REGNO (tmp));
2177     }
2178   else if (GET_CODE (tmp) == PLUS
2179            && GET_CODE (XEXP (tmp, 0)) == REG
2180            && GET_CODE (XEXP (tmp, 1)) == CONST_INT)
2181     {
2182       HOST_WIDE_INT c = INTVAL (XEXP (tmp, 1));
2183       int a = REGNO_POINTER_ALIGN (REGNO (XEXP (tmp, 0)));
2184
2185       if (a > align)
2186         {
2187           if (a >= 8 && c % 8 == 0)
2188             align = 8;
2189           else if (a >= 4 && c % 4 == 0)
2190             align = 4;
2191           else if (a >= 2 && c % 2 == 0)
2192             align = 2;
2193         }
2194     }
2195
2196   /* Handle a block of contiguous words first.  */
2197
2198   if (align >= 8 && bytes >= 8)
2199     {
2200       words = bytes / 8;
2201
2202       for (i = 0; i < words; ++i)
2203         {
2204           emit_move_insn (change_address(orig_dst, DImode,
2205                                          plus_constant (XEXP (orig_dst, 0),
2206                                                         ofs + i*8)),
2207                           const0_rtx);
2208         }
2209
2210       bytes -= words * 8;
2211       ofs += words * 8;
2212     }
2213   if (align >= 4 && bytes >= 4)
2214     {
2215       words = bytes / 4;
2216
2217       for (i = 0; i < words; ++i)
2218         {
2219           emit_move_insn (change_address(orig_dst, SImode,
2220                                          plus_constant (XEXP (orig_dst, 0),
2221                                                         ofs + i*4)),
2222                           const0_rtx);
2223         }
2224
2225       bytes -= words * 4;
2226       ofs += words * 4;
2227     }
2228   if (bytes >= 16)
2229     {
2230       words = bytes / 8;
2231
2232       alpha_expand_unaligned_store_words (NULL, orig_dst, words, ofs);
2233
2234       bytes -= words * 8;
2235       ofs += words * 8;
2236     }
2237
2238   /* Next clean up any trailing pieces.  We know from the contiguous
2239      block move that there are no aligned SImode or DImode hunks left.  */
2240
2241   if (!TARGET_BWX && bytes >= 8)
2242     {
2243       alpha_expand_unaligned_store (orig_dst, const0_rtx, 8, ofs);
2244       bytes -= 8;
2245       ofs += 8;
2246     }
2247   if (!TARGET_BWX && bytes >= 4)
2248     {
2249       alpha_expand_unaligned_store (orig_dst, const0_rtx, 4, ofs);
2250       bytes -= 4;
2251       ofs += 4;
2252     }
2253   if (bytes >= 2)
2254     {
2255       if (align >= 2)
2256         {
2257           do {
2258             emit_move_insn (change_address (orig_dst, HImode,
2259                                             plus_constant (XEXP (orig_dst, 0),
2260                                                            ofs)),
2261                             const0_rtx);
2262             bytes -= 2;
2263             ofs += 2;
2264           } while (bytes >= 2);
2265         }
2266       else if (!TARGET_BWX)
2267         {
2268           alpha_expand_unaligned_store (orig_dst, const0_rtx, 2, ofs);
2269           bytes -= 2;
2270           ofs += 2;
2271         }
2272     }
2273   while (bytes > 0)
2274     {
2275       emit_move_insn (change_address (orig_dst, QImode,
2276                                       plus_constant (XEXP (orig_dst, 0),
2277                                                      ofs)),
2278                       const0_rtx);
2279       bytes -= 1;
2280       ofs += 1;
2281     }
2282
2283   return 1;
2284 }
2285
2286 \f
2287 /* Adjust the cost of a scheduling dependency.  Return the new cost of
2288    a dependency LINK or INSN on DEP_INSN.  COST is the current cost.  */
2289
2290 int
2291 alpha_adjust_cost (insn, link, dep_insn, cost)
2292      rtx insn;
2293      rtx link;
2294      rtx dep_insn;
2295      int cost;
2296 {
2297   rtx set, set_src;
2298   enum attr_type insn_type, dep_insn_type;
2299
2300   /* If the dependence is an anti-dependence, there is no cost.  For an
2301      output dependence, there is sometimes a cost, but it doesn't seem
2302      worth handling those few cases.  */
2303
2304   if (REG_NOTE_KIND (link) != 0)
2305     return 0;
2306
2307   /* If we can't recognize the insns, we can't really do anything.  */
2308   if (recog_memoized (insn) < 0 || recog_memoized (dep_insn) < 0)
2309     return cost;
2310
2311   insn_type = get_attr_type (insn);
2312   dep_insn_type = get_attr_type (dep_insn);
2313
2314   /* Bring in the user-defined memory latency.  */
2315   if (dep_insn_type == TYPE_ILD
2316       || dep_insn_type == TYPE_FLD
2317       || dep_insn_type == TYPE_LDSYM)
2318     cost += alpha_memory_latency-1;
2319
2320   switch (alpha_cpu)
2321     {
2322     case PROCESSOR_EV4:
2323       /* On EV4, if INSN is a store insn and DEP_INSN is setting the data
2324          being stored, we can sometimes lower the cost.  */
2325
2326       if ((insn_type == TYPE_IST || insn_type == TYPE_FST)
2327           && (set = single_set (dep_insn)) != 0
2328           && GET_CODE (PATTERN (insn)) == SET
2329           && rtx_equal_p (SET_DEST (set), SET_SRC (PATTERN (insn))))
2330         {
2331           switch (dep_insn_type)
2332             {
2333             case TYPE_ILD:
2334             case TYPE_FLD:
2335               /* No savings here.  */
2336               return cost;
2337
2338             case TYPE_IMUL:
2339               /* In these cases, we save one cycle.  */
2340               return cost - 1;
2341
2342             default:
2343               /* In all other cases, we save two cycles.  */
2344               return MAX (0, cost - 2);
2345             }
2346         }
2347
2348       /* Another case that needs adjustment is an arithmetic or logical
2349          operation.  It's cost is usually one cycle, but we default it to
2350          two in the MD file.  The only case that it is actually two is
2351          for the address in loads, stores, and jumps.  */
2352
2353       if (dep_insn_type == TYPE_IADD || dep_insn_type == TYPE_ILOG)
2354         {
2355           switch (insn_type)
2356             {
2357             case TYPE_ILD:
2358             case TYPE_IST:
2359             case TYPE_FLD:
2360             case TYPE_FST:
2361             case TYPE_JSR:
2362               return cost;
2363             default:
2364               return 1;
2365             }
2366         }
2367
2368       /* The final case is when a compare feeds into an integer branch;
2369          the cost is only one cycle in that case.  */
2370
2371       if (dep_insn_type == TYPE_ICMP && insn_type == TYPE_IBR)
2372         return 1;
2373       break;
2374
2375     case PROCESSOR_EV5:
2376       /* And the lord DEC saith:  "A special bypass provides an effective
2377          latency of 0 cycles for an ICMP or ILOG insn producing the test
2378          operand of an IBR or ICMOV insn." */
2379
2380       if ((dep_insn_type == TYPE_ICMP || dep_insn_type == TYPE_ILOG)
2381           && (set = single_set (dep_insn)) != 0)
2382         {
2383           /* A branch only has one input.  This must be it.  */
2384           if (insn_type == TYPE_IBR)
2385             return 0;
2386           /* A conditional move has three, make sure it is the test.  */
2387           if (insn_type == TYPE_ICMOV
2388               && GET_CODE (set_src = PATTERN (insn)) == SET
2389               && GET_CODE (set_src = SET_SRC (set_src)) == IF_THEN_ELSE
2390               && rtx_equal_p (SET_DEST (set), XEXP (set_src, 0)))
2391             return 0;
2392         }
2393
2394       /* "The multiplier is unable to receive data from IEU bypass paths.
2395          The instruction issues at the expected time, but its latency is
2396          increased by the time it takes for the input data to become
2397          available to the multiplier" -- which happens in pipeline stage
2398          six, when results are comitted to the register file.  */
2399
2400       if (insn_type == TYPE_IMUL)
2401         {
2402           switch (dep_insn_type)
2403             {
2404             /* These insns produce their results in pipeline stage five.  */
2405             case TYPE_ILD:
2406             case TYPE_ICMOV:
2407             case TYPE_IMUL:
2408             case TYPE_MVI:
2409               return cost + 1;
2410
2411             /* Other integer insns produce results in pipeline stage four.  */
2412             default:
2413               return cost + 2;
2414             }
2415         }
2416       break;
2417
2418     case PROCESSOR_EV6:
2419       /* There is additional latency to move the result of (most) FP 
2420          operations anywhere but the FP register file.  */
2421
2422       if ((insn_type == TYPE_FST || insn_type == TYPE_FTOI)
2423           && (dep_insn_type == TYPE_FADD ||
2424               dep_insn_type == TYPE_FMUL ||
2425               dep_insn_type == TYPE_FCMOV))
2426         return cost + 2;
2427
2428       break;
2429     }
2430
2431   /* Otherwise, return the default cost. */
2432   return cost;
2433 }
2434 \f
2435 /* Functions to save and restore alpha_return_addr_rtx.  */
2436
2437 struct machine_function
2438 {
2439   rtx ra_rtx;
2440 };
2441
2442 static void
2443 alpha_save_machine_status (p)
2444      struct function *p;
2445 {
2446   struct machine_function *machine =
2447     (struct machine_function *) xmalloc (sizeof (struct machine_function));
2448
2449   p->machine = machine;
2450   machine->ra_rtx = alpha_return_addr_rtx;
2451 }
2452
2453 static void
2454 alpha_restore_machine_status (p)
2455      struct function *p;
2456 {
2457   struct machine_function *machine = p->machine;
2458
2459   alpha_return_addr_rtx = machine->ra_rtx;
2460
2461   free (machine);
2462   p->machine = (struct machine_function *)0;
2463 }
2464
2465 /* Do anything needed before RTL is emitted for each function.  */
2466
2467 void
2468 alpha_init_expanders ()
2469 {
2470   alpha_return_addr_rtx = NULL_RTX;
2471   alpha_eh_epilogue_sp_ofs = NULL_RTX;
2472
2473   /* Arrange to save and restore machine status around nested functions.  */
2474   save_machine_status = alpha_save_machine_status;
2475   restore_machine_status = alpha_restore_machine_status;
2476 }
2477
2478 /* Start the ball rolling with RETURN_ADDR_RTX.  */
2479
2480 rtx
2481 alpha_return_addr (count, frame)
2482      int count;
2483      rtx frame ATTRIBUTE_UNUSED;
2484 {
2485   rtx init;
2486
2487   if (count != 0)
2488     return const0_rtx;
2489
2490   if (alpha_return_addr_rtx)
2491     return alpha_return_addr_rtx;
2492
2493   /* No rtx yet.  Invent one, and initialize it from $26 in the prologue.  */
2494   alpha_return_addr_rtx = gen_reg_rtx (Pmode);
2495   init = gen_rtx_SET (VOIDmode, alpha_return_addr_rtx,
2496                       gen_rtx_REG (Pmode, REG_RA));
2497
2498   /* Emit the insn to the prologue with the other argument copies.  */
2499   push_topmost_sequence ();
2500   emit_insn_after (init, get_insns ());
2501   pop_topmost_sequence ();
2502
2503   return alpha_return_addr_rtx;
2504 }
2505
2506 static int
2507 alpha_ra_ever_killed ()
2508 {
2509   rtx top;
2510
2511 #ifdef ASM_OUTPUT_MI_THUNK
2512   if (current_function_is_thunk)
2513     return 0;
2514 #endif
2515   if (!alpha_return_addr_rtx)
2516     return regs_ever_live[REG_RA];
2517
2518   push_topmost_sequence ();
2519   top = get_insns ();
2520   pop_topmost_sequence ();
2521
2522   return reg_set_between_p (gen_rtx_REG (Pmode, REG_RA), top, NULL_RTX);
2523 }
2524
2525 \f
2526 /* Print an operand.  Recognize special options, documented below.  */
2527
2528 void
2529 print_operand (file, x, code)
2530     FILE *file;
2531     rtx x;
2532     char code;
2533 {
2534   int i;
2535
2536   switch (code)
2537     {
2538     case '&':
2539       /* Generates fp-rounding mode suffix: nothing for normal, 'c' for
2540          chopped, 'm' for minus-infinity, and 'd' for dynamic rounding
2541          mode.  alpha_fprm controls which suffix is generated.  */
2542       switch (alpha_fprm)
2543         {
2544         case ALPHA_FPRM_NORM:
2545           break;
2546         case ALPHA_FPRM_MINF: 
2547           fputc ('m', file);
2548           break;
2549         case ALPHA_FPRM_CHOP:
2550           fputc ('c', file);
2551           break;
2552         case ALPHA_FPRM_DYN:
2553           fputc ('d', file);
2554           break;
2555         }
2556       break;
2557
2558     case '\'':
2559       /* Generates trap-mode suffix for instructions that accept the su
2560          suffix only (cmpt et al).  */
2561       if (alpha_tp == ALPHA_TP_INSN)
2562         fputs ("su", file);
2563       break;
2564
2565     case '`':
2566       /* Generates trap-mode suffix for instructions that accept the
2567          v and sv suffix.  The only instruction that needs this is cvtql.  */
2568       switch (alpha_fptm)
2569         {
2570         case ALPHA_FPTM_N:
2571           break;
2572         case ALPHA_FPTM_U:
2573           fputs ("v", file);
2574           break;
2575         case ALPHA_FPTM_SU:
2576         case ALPHA_FPTM_SUI:
2577           fputs ("sv", file);
2578           break;
2579         }
2580       break;
2581
2582     case '(':
2583       /* Generates trap-mode suffix for instructions that accept the
2584          v, sv, and svi suffix.  The only instruction that needs this
2585          is cvttq.  */
2586       switch (alpha_fptm)
2587         {
2588         case ALPHA_FPTM_N:
2589           break;
2590         case ALPHA_FPTM_U:
2591           fputs ("v", file);
2592           break;
2593         case ALPHA_FPTM_SU:
2594           fputs ("sv", file);
2595           break;
2596         case ALPHA_FPTM_SUI:
2597           fputs ("svi", file);
2598           break;
2599         }
2600       break;
2601
2602     case ')':
2603       /* Generates trap-mode suffix for instructions that accept the u, su,
2604          and sui suffix.  This is the bulk of the IEEE floating point
2605          instructions (addt et al).  */
2606       switch (alpha_fptm)
2607         {
2608         case ALPHA_FPTM_N:
2609           break;
2610         case ALPHA_FPTM_U:
2611           fputc ('u', file);
2612           break;
2613         case ALPHA_FPTM_SU:
2614           fputs ("su", file);
2615           break;
2616         case ALPHA_FPTM_SUI:
2617           fputs ("sui", file);
2618           break;
2619         }
2620       break;
2621
2622     case '+':
2623       /* Generates trap-mode suffix for instructions that accept the sui
2624          suffix (cvtqt and cvtqs).  */
2625       switch (alpha_fptm)
2626         {
2627         case ALPHA_FPTM_N:
2628         case ALPHA_FPTM_U:
2629         case ALPHA_FPTM_SU:     /* cvtqt/cvtqs can't cause underflow */
2630           break;
2631         case ALPHA_FPTM_SUI:
2632           fputs ("sui", file);
2633           break;
2634         }
2635       break;
2636
2637     case ',':
2638       /* Generates single precision instruction suffix.  */
2639       fprintf (file, "%c", (TARGET_FLOAT_VAX ? 'f' : 's'));
2640       break;
2641
2642     case '-':
2643       /* Generates double precision instruction suffix.  */
2644       fprintf (file, "%c", (TARGET_FLOAT_VAX ? 'g' : 't'));
2645       break;
2646
2647     case 'r':
2648       /* If this operand is the constant zero, write it as "$31".  */
2649       if (GET_CODE (x) == REG)
2650         fprintf (file, "%s", reg_names[REGNO (x)]);
2651       else if (x == CONST0_RTX (GET_MODE (x)))
2652         fprintf (file, "$31");
2653       else
2654         output_operand_lossage ("invalid %%r value");
2655
2656       break;
2657
2658     case 'R':
2659       /* Similar, but for floating-point.  */
2660       if (GET_CODE (x) == REG)
2661         fprintf (file, "%s", reg_names[REGNO (x)]);
2662       else if (x == CONST0_RTX (GET_MODE (x)))
2663         fprintf (file, "$f31");
2664       else
2665         output_operand_lossage ("invalid %%R value");
2666
2667       break;
2668
2669     case 'N':
2670       /* Write the 1's complement of a constant.  */
2671       if (GET_CODE (x) != CONST_INT)
2672         output_operand_lossage ("invalid %%N value");
2673
2674       fprintf (file, HOST_WIDE_INT_PRINT_DEC, ~ INTVAL (x));
2675       break;
2676
2677     case 'P':
2678       /* Write 1 << C, for a constant C.  */
2679       if (GET_CODE (x) != CONST_INT)
2680         output_operand_lossage ("invalid %%P value");
2681
2682       fprintf (file, HOST_WIDE_INT_PRINT_DEC, (HOST_WIDE_INT) 1 << INTVAL (x));
2683       break;
2684
2685     case 'h':
2686       /* Write the high-order 16 bits of a constant, sign-extended.  */
2687       if (GET_CODE (x) != CONST_INT)
2688         output_operand_lossage ("invalid %%h value");
2689
2690       fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x) >> 16);
2691       break;
2692
2693     case 'L':
2694       /* Write the low-order 16 bits of a constant, sign-extended.  */
2695       if (GET_CODE (x) != CONST_INT)
2696         output_operand_lossage ("invalid %%L value");
2697
2698       fprintf (file, HOST_WIDE_INT_PRINT_DEC,
2699                (INTVAL (x) & 0xffff) - 2 * (INTVAL (x) & 0x8000));
2700       break;
2701
2702     case 'm':
2703       /* Write mask for ZAP insn.  */
2704       if (GET_CODE (x) == CONST_DOUBLE)
2705         {
2706           HOST_WIDE_INT mask = 0;
2707           HOST_WIDE_INT value;
2708
2709           value = CONST_DOUBLE_LOW (x);
2710           for (i = 0; i < HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR;
2711                i++, value >>= 8)
2712             if (value & 0xff)
2713               mask |= (1 << i);
2714
2715           value = CONST_DOUBLE_HIGH (x);
2716           for (i = 0; i < HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR;
2717                i++, value >>= 8)
2718             if (value & 0xff)
2719               mask |= (1 << (i + sizeof (int)));
2720
2721           fprintf (file, HOST_WIDE_INT_PRINT_DEC, mask & 0xff);
2722         }
2723
2724       else if (GET_CODE (x) == CONST_INT)
2725         {
2726           HOST_WIDE_INT mask = 0, value = INTVAL (x);
2727
2728           for (i = 0; i < 8; i++, value >>= 8)
2729             if (value & 0xff)
2730               mask |= (1 << i);
2731
2732           fprintf (file, HOST_WIDE_INT_PRINT_DEC, mask);
2733         }
2734       else
2735         output_operand_lossage ("invalid %%m value");
2736       break;
2737
2738     case 'M':
2739       /* 'b', 'w', 'l', or 'q' as the value of the constant.  */
2740       if (GET_CODE (x) != CONST_INT
2741           || (INTVAL (x) != 8 && INTVAL (x) != 16
2742               && INTVAL (x) != 32 && INTVAL (x) != 64))
2743         output_operand_lossage ("invalid %%M value");
2744
2745       fprintf (file, "%s",
2746                (INTVAL (x) == 8 ? "b"
2747                 : INTVAL (x) == 16 ? "w"
2748                 : INTVAL (x) == 32 ? "l"
2749                 : "q"));
2750       break;
2751
2752     case 'U':
2753       /* Similar, except do it from the mask.  */
2754       if (GET_CODE (x) == CONST_INT && INTVAL (x) == 0xff)
2755         fprintf (file, "b");
2756       else if (GET_CODE (x) == CONST_INT && INTVAL (x) == 0xffff)
2757         fprintf (file, "w");
2758       else if (GET_CODE (x) == CONST_INT && INTVAL (x) == 0xffffffff)
2759         fprintf (file, "l");
2760 #if HOST_BITS_PER_WIDE_INT == 32
2761       else if (GET_CODE (x) == CONST_DOUBLE
2762                && CONST_DOUBLE_HIGH (x) == 0
2763                && CONST_DOUBLE_LOW (x) == -1)
2764         fprintf (file, "l");
2765       else if (GET_CODE (x) == CONST_DOUBLE
2766                && CONST_DOUBLE_HIGH (x) == -1
2767                && CONST_DOUBLE_LOW (x) == -1)
2768         fprintf (file, "q");
2769 #else
2770       else if (GET_CODE (x) == CONST_INT && INTVAL (x) == -1)
2771         fprintf (file, "q");
2772       else if (GET_CODE (x) == CONST_DOUBLE
2773                && CONST_DOUBLE_HIGH (x) == 0
2774                && CONST_DOUBLE_LOW (x) == -1)
2775         fprintf (file, "q");
2776 #endif
2777       else
2778         output_operand_lossage ("invalid %%U value");
2779       break;
2780
2781     case 's':
2782       /* Write the constant value divided by 8.  */
2783       if (GET_CODE (x) != CONST_INT
2784           && (unsigned HOST_WIDE_INT) INTVAL (x) >= 64
2785           && (INTVAL (x) & 7) != 8)
2786         output_operand_lossage ("invalid %%s value");
2787
2788       fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x) / 8);
2789       break;
2790
2791     case 'S':
2792       /* Same, except compute (64 - c) / 8 */
2793
2794       if (GET_CODE (x) != CONST_INT
2795           && (unsigned HOST_WIDE_INT) INTVAL (x) >= 64
2796           && (INTVAL (x) & 7) != 8)
2797         output_operand_lossage ("invalid %%s value");
2798
2799       fprintf (file, HOST_WIDE_INT_PRINT_DEC, (64 - INTVAL (x)) / 8);
2800       break;
2801
2802     case 'C': case 'D': case 'c': case 'd':
2803       /* Write out comparison name.  */
2804       {
2805         enum rtx_code c = GET_CODE (x);
2806
2807         if (GET_RTX_CLASS (c) != '<')
2808           output_operand_lossage ("invalid %%C value");
2809
2810         if (code == 'D')
2811           c = reverse_condition (c);
2812         else if (code == 'c')
2813           c = swap_condition (c);
2814         else if (code == 'd')
2815           c = swap_condition (reverse_condition (c));
2816
2817         if (c == LEU)
2818           fprintf (file, "ule");
2819         else if (c == LTU)
2820           fprintf (file, "ult");
2821         else
2822           fprintf (file, "%s", GET_RTX_NAME (c));
2823       }
2824       break;
2825
2826     case 'E':
2827       /* Write the divide or modulus operator.  */
2828       switch (GET_CODE (x))
2829         {
2830         case DIV:
2831           fprintf (file, "div%s", GET_MODE (x) == SImode ? "l" : "q");
2832           break;
2833         case UDIV:
2834           fprintf (file, "div%su", GET_MODE (x) == SImode ? "l" : "q");
2835           break;
2836         case MOD:
2837           fprintf (file, "rem%s", GET_MODE (x) == SImode ? "l" : "q");
2838           break;
2839         case UMOD:
2840           fprintf (file, "rem%su", GET_MODE (x) == SImode ? "l" : "q");
2841           break;
2842         default:
2843           output_operand_lossage ("invalid %%E value");
2844           break;
2845         }
2846       break;
2847
2848     case 'A':
2849       /* Write "_u" for unaligned access.  */
2850       if (GET_CODE (x) == MEM && GET_CODE (XEXP (x, 0)) == AND)
2851         fprintf (file, "_u");
2852       break;
2853
2854     case 0:
2855       if (GET_CODE (x) == REG)
2856         fprintf (file, "%s", reg_names[REGNO (x)]);
2857       else if (GET_CODE (x) == MEM)
2858         output_address (XEXP (x, 0));
2859       else
2860         output_addr_const (file, x);
2861       break;
2862
2863     default:
2864       output_operand_lossage ("invalid %%xn code");
2865     }
2866 }
2867 \f
2868 /* Emit RTL insns to initialize the variable parts of a trampoline at
2869    TRAMP. FNADDR is an RTX for the address of the function's pure
2870    code.  CXT is an RTX for the static chain value for the function.
2871
2872    The three offset parameters are for the individual template's
2873    layout.  A JMPOFS < 0 indicates that the trampoline does not 
2874    contain instructions at all.
2875
2876    We assume here that a function will be called many more times than
2877    its address is taken (e.g., it might be passed to qsort), so we
2878    take the trouble to initialize the "hint" field in the JMP insn.
2879    Note that the hint field is PC (new) + 4 * bits 13:0.  */
2880
2881 void
2882 alpha_initialize_trampoline (tramp, fnaddr, cxt, fnofs, cxtofs, jmpofs)
2883      rtx tramp, fnaddr, cxt;
2884      int fnofs, cxtofs, jmpofs;
2885 {
2886   rtx temp, temp1, addr;
2887   /* ??? Something is wrong with VMS codegen in that we get aborts when
2888      using ptr_mode.  Hack around it for now.  */
2889   enum machine_mode mode = TARGET_OPEN_VMS ? Pmode : ptr_mode;
2890
2891   /* Store function address and CXT.  */
2892   addr = memory_address (mode, plus_constant (tramp, fnofs));
2893   emit_move_insn (gen_rtx (MEM, mode, addr), fnaddr);
2894   addr = memory_address (mode, plus_constant (tramp, cxtofs));
2895   emit_move_insn (gen_rtx (MEM, mode, addr), cxt);
2896
2897   /* This has been disabled since the hint only has a 32k range, and in
2898      no existing OS is the stack within 32k of the text segment. */
2899   if (0 && jmpofs >= 0)
2900     {
2901       /* Compute hint value.  */
2902       temp = force_operand (plus_constant (tramp, jmpofs+4), NULL_RTX);
2903       temp = expand_binop (DImode, sub_optab, fnaddr, temp, temp, 1,
2904                            OPTAB_WIDEN);
2905       temp = expand_shift (RSHIFT_EXPR, Pmode, temp,
2906                            build_int_2 (2, 0), NULL_RTX, 1);
2907       temp = expand_and (gen_lowpart (SImode, temp), GEN_INT (0x3fff), 0);
2908
2909       /* Merge in the hint.  */
2910       addr = memory_address (SImode, plus_constant (tramp, jmpofs));
2911       temp1 = force_reg (SImode, gen_rtx (MEM, SImode, addr));
2912       temp1 = expand_and (temp1, GEN_INT (0xffffc000), NULL_RTX);
2913       temp1 = expand_binop (SImode, ior_optab, temp1, temp, temp1, 1,
2914                             OPTAB_WIDEN);
2915       emit_move_insn (gen_rtx (MEM, SImode, addr), temp1);
2916     }
2917
2918 #ifdef TRANSFER_FROM_TRAMPOLINE
2919   emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "__enable_execute_stack"),
2920                      0, VOIDmode, 1, addr, Pmode);
2921 #endif
2922
2923   if (jmpofs >= 0)
2924     emit_insn (gen_imb ());
2925 }
2926 \f
2927 /* Do what is necessary for `va_start'.  The argument is ignored;
2928    We look at the current function to determine if stdarg or varargs
2929    is used and fill in an initial va_list.  A pointer to this constructor
2930    is returned.  */
2931
2932 struct rtx_def *
2933 alpha_builtin_saveregs (arglist)
2934      tree arglist ATTRIBUTE_UNUSED;
2935 {
2936   rtx block, addr, dest, argsize;
2937   tree fntype = TREE_TYPE (current_function_decl);
2938   int stdarg = (TYPE_ARG_TYPES (fntype) != 0
2939                 && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
2940                     != void_type_node));
2941
2942   /* Compute the current position into the args, taking into account
2943      both registers and memory.  Both of these are already included in
2944      NUM_ARGS.  */
2945
2946   argsize = GEN_INT (NUM_ARGS * UNITS_PER_WORD);
2947
2948   /* For Unix, SETUP_INCOMING_VARARGS moves the starting address base up by 48,
2949      storing fp arg registers in the first 48 bytes, and the integer arg
2950      registers in the next 48 bytes.  This is only done, however, if any
2951      integer registers need to be stored.
2952
2953      If no integer registers need be stored, then we must subtract 48 in
2954      order to account for the integer arg registers which are counted in
2955      argsize above, but which are not actually stored on the stack.  */
2956
2957   if (TARGET_OPEN_VMS)
2958     addr = plus_constant (virtual_incoming_args_rtx,
2959                           NUM_ARGS <= 5 + stdarg
2960                           ? UNITS_PER_WORD : - 6 * UNITS_PER_WORD);
2961   else
2962     addr = (NUM_ARGS <= 5 + stdarg
2963             ? plus_constant (virtual_incoming_args_rtx,
2964                              6 * UNITS_PER_WORD)
2965             : plus_constant (virtual_incoming_args_rtx,
2966                              - (6 * UNITS_PER_WORD)));
2967
2968   /* For VMS, we include the argsize, while on Unix, it's handled as
2969      a separate field.  */
2970   if (TARGET_OPEN_VMS)
2971     addr = plus_constant (addr, INTVAL (argsize));
2972
2973   addr = force_operand (addr, NULL_RTX);
2974
2975 #ifdef POINTERS_EXTEND_UNSIGNED
2976   addr = convert_memory_address (ptr_mode, addr);
2977 #endif
2978
2979   if (TARGET_OPEN_VMS)
2980     return addr;
2981   else
2982     {
2983       /* Allocate the va_list constructor */
2984       block = assign_stack_local (BLKmode, 2 * UNITS_PER_WORD, BITS_PER_WORD);
2985       RTX_UNCHANGING_P (block) = 1;
2986       RTX_UNCHANGING_P (XEXP (block, 0)) = 1;
2987
2988       /* Store the address of the first integer register in the __base
2989          member.  */
2990
2991       dest = change_address (block, ptr_mode, XEXP (block, 0));
2992       emit_move_insn (dest, addr);
2993
2994       if (current_function_check_memory_usage)
2995         emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3,
2996                            dest, ptr_mode,
2997                            GEN_INT (GET_MODE_SIZE (ptr_mode)),
2998                            TYPE_MODE (sizetype),
2999                            GEN_INT (MEMORY_USE_RW), 
3000                            TYPE_MODE (integer_type_node));
3001   
3002       /* Store the argsize as the __va_offset member.  */
3003       dest = change_address (block, TYPE_MODE (integer_type_node),
3004                              plus_constant (XEXP (block, 0),
3005                                             POINTER_SIZE/BITS_PER_UNIT));
3006       emit_move_insn (dest, argsize);
3007
3008       if (current_function_check_memory_usage)
3009         emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3,
3010                            dest, ptr_mode,
3011                            GEN_INT (GET_MODE_SIZE
3012                                     (TYPE_MODE (integer_type_node))),
3013                            TYPE_MODE (sizetype),
3014                            GEN_INT (MEMORY_USE_RW),
3015                            TYPE_MODE (integer_type_node));
3016
3017       /* Return the address of the va_list constructor, but don't put it in a
3018          register.  Doing so would fail when not optimizing and produce worse
3019          code when optimizing.  */
3020       return XEXP (block, 0);
3021     }
3022 }
3023 \f
3024 /* This page contains routines that are used to determine what the function
3025    prologue and epilogue code will do and write them out.  */
3026
3027 /* Compute the size of the save area in the stack.  */
3028
3029 /* These variables are used for communication between the following functions.
3030    They indicate various things about the current function being compiled
3031    that are used to tell what kind of prologue, epilogue and procedure
3032    descriptior to generate. */
3033
3034 /* Nonzero if we need a stack procedure.  */
3035 static int vms_is_stack_procedure;
3036
3037 /* Register number (either FP or SP) that is used to unwind the frame.  */
3038 static int vms_unwind_regno;
3039
3040 /* Register number used to save FP.  We need not have one for RA since
3041    we don't modify it for register procedures.  This is only defined
3042    for register frame procedures.  */
3043 static int vms_save_fp_regno;
3044
3045 /* Register number used to reference objects off our PV.  */
3046 static int vms_base_regno;
3047
3048 /* Compute register masks for saved registers.  */
3049
3050 static void
3051 alpha_sa_mask (imaskP, fmaskP)
3052     unsigned long *imaskP;
3053     unsigned long *fmaskP;
3054 {
3055   unsigned long imask = 0;
3056   unsigned long fmask = 0;
3057   int i;
3058
3059 #ifdef ASM_OUTPUT_MI_THUNK
3060   if (!current_function_is_thunk)
3061 #endif
3062     {
3063       if (TARGET_OPEN_VMS && vms_is_stack_procedure)
3064         imask |= (1L << HARD_FRAME_POINTER_REGNUM);
3065
3066       /* One for every register we have to save.  */
3067       for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
3068         if (! fixed_regs[i] && ! call_used_regs[i]
3069             && regs_ever_live[i] && i != REG_RA)
3070           {
3071             if (i < 32)
3072               imask |= (1L << i);
3073             else
3074               fmask |= (1L << (i - 32));
3075           }
3076
3077       if (imask || fmask || alpha_ra_ever_killed ())
3078         imask |= (1L << REG_RA);
3079     }
3080
3081   *imaskP = imask;
3082   *fmaskP = fmask;
3083 }
3084
3085 int
3086 alpha_sa_size ()
3087 {
3088   int sa_size = 0;
3089   int i;
3090
3091 #ifdef ASM_OUTPUT_MI_THUNK
3092   if (current_function_is_thunk)
3093     sa_size = 0;
3094   else
3095 #endif
3096     {
3097       /* One for every register we have to save.  */
3098       for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
3099         if (! fixed_regs[i] && ! call_used_regs[i]
3100             && regs_ever_live[i] && i != REG_RA)
3101           sa_size++;
3102     }
3103
3104   if (TARGET_OPEN_VMS)
3105     {
3106       /* Start by assuming we can use a register procedure if we don't
3107          make any calls (REG_RA not used) or need to save any
3108          registers and a stack procedure if we do.  */
3109       vms_is_stack_procedure = sa_size != 0 || alpha_ra_ever_killed ();
3110
3111       /* Decide whether to refer to objects off our PV via FP or PV.
3112          If we need FP for something else or if we receive a nonlocal
3113          goto (which expects PV to contain the value), we must use PV.
3114          Otherwise, start by assuming we can use FP.  */
3115       vms_base_regno = (frame_pointer_needed
3116                         || current_function_has_nonlocal_label
3117                         || vms_is_stack_procedure
3118                         || current_function_outgoing_args_size
3119                         ? REG_PV : HARD_FRAME_POINTER_REGNUM);
3120
3121       /* If we want to copy PV into FP, we need to find some register
3122          in which to save FP.  */
3123
3124       vms_save_fp_regno = -1;
3125       if (vms_base_regno == HARD_FRAME_POINTER_REGNUM)
3126         for (i = 0; i < 32; i++)
3127           if (! fixed_regs[i] && call_used_regs[i] && ! regs_ever_live[i])
3128             vms_save_fp_regno = i;
3129
3130       if (vms_save_fp_regno == -1)
3131         vms_base_regno = REG_PV, vms_is_stack_procedure = 1;
3132
3133       /* Stack unwinding should be done via FP unless we use it for PV.  */
3134       vms_unwind_regno = (vms_base_regno == REG_PV
3135                           ? HARD_FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM);
3136
3137       /* If this is a stack procedure, allow space for saving FP and RA.  */
3138       if (vms_is_stack_procedure)
3139         sa_size += 2;
3140     }
3141   else
3142     {
3143       /* If some registers were saved but not RA, RA must also be saved,
3144          so leave space for it.  */
3145       if (sa_size != 0 || alpha_ra_ever_killed ())
3146         sa_size++;
3147
3148       /* Our size must be even (multiple of 16 bytes).  */
3149       if (sa_size & 1)
3150         sa_size++;
3151     }
3152
3153   return sa_size * 8;
3154 }
3155
3156 int
3157 alpha_pv_save_size ()
3158 {
3159   alpha_sa_size ();
3160   return vms_is_stack_procedure ? 8 : 0;
3161 }
3162
3163 int
3164 alpha_using_fp ()
3165 {
3166   alpha_sa_size ();
3167   return vms_unwind_regno == HARD_FRAME_POINTER_REGNUM;
3168 }
3169
3170 int
3171 vms_valid_decl_attribute_p (decl, attributes, identifier, args)
3172      tree decl ATTRIBUTE_UNUSED;
3173      tree attributes ATTRIBUTE_UNUSED;
3174      tree identifier;
3175      tree args;
3176 {
3177   if (is_attribute_p ("overlaid", identifier))
3178     return (args == NULL_TREE);
3179   return 0;
3180 }
3181
3182 static int
3183 alpha_does_function_need_gp ()
3184 {
3185   rtx insn;
3186
3187   /* We never need a GP for Windows/NT or VMS.  */
3188   if (TARGET_WINDOWS_NT || TARGET_OPEN_VMS)
3189     return 0;
3190
3191 #ifdef TARGET_PROFILING_NEEDS_GP
3192   if (profile_flag)
3193     return 1;
3194 #endif
3195
3196 #ifdef ASM_OUTPUT_MI_THUNK
3197   if (current_function_is_thunk)
3198     return 1;
3199 #endif
3200
3201   /* If we need a GP (we have a LDSYM insn or a CALL_INSN), load it first. 
3202      Even if we are a static function, we still need to do this in case
3203      our address is taken and passed to something like qsort.  */
3204
3205   push_topmost_sequence ();
3206   insn = get_insns ();
3207   pop_topmost_sequence ();
3208
3209   for (; insn; insn = NEXT_INSN (insn))
3210     if (GET_RTX_CLASS (GET_CODE (insn)) == 'i'
3211         && GET_CODE (PATTERN (insn)) != USE
3212         && GET_CODE (PATTERN (insn)) != CLOBBER)
3213       {
3214         enum attr_type type = get_attr_type (insn);
3215         if (type == TYPE_LDSYM || type == TYPE_JSR)
3216           return 1;
3217       }
3218
3219   return 0;
3220 }
3221
3222 /* Write a version stamp.  Don't write anything if we are running as a
3223    cross-compiler.  Otherwise, use the versions in /usr/include/stamp.h.  */
3224
3225 #ifdef HAVE_STAMP_H
3226 #include <stamp.h>
3227 #endif
3228
3229 void
3230 alpha_write_verstamp (file)
3231      FILE *file;
3232 {
3233 #ifdef MS_STAMP
3234   fprintf (file, "\t.verstamp %d %d\n", MS_STAMP, LS_STAMP);
3235 #endif
3236 }
3237 \f
3238 /* Helper function to set RTX_FRAME_RELATED_P on instructions, including
3239    sequences.  */
3240
3241 static rtx
3242 set_frame_related_p ()
3243 {
3244   rtx seq = gen_sequence ();
3245   end_sequence ();
3246
3247   if (GET_CODE (seq) == SEQUENCE)
3248     {
3249       int i = XVECLEN (seq, 0);
3250       while (--i >= 0)
3251         RTX_FRAME_RELATED_P (XVECEXP (seq, 0, i)) = 1;
3252      return emit_insn (seq);
3253     }
3254   else
3255     {
3256       seq = emit_insn (seq);
3257       RTX_FRAME_RELATED_P (seq) = 1;
3258       return seq;
3259     }
3260 }
3261
3262 #define FRP(exp)  (start_sequence (), exp, set_frame_related_p ())
3263
3264 /* Write function prologue.  */
3265
3266 /* On vms we have two kinds of functions:
3267
3268    - stack frame (PROC_STACK)
3269         these are 'normal' functions with local vars and which are
3270         calling other functions
3271    - register frame (PROC_REGISTER)
3272         keeps all data in registers, needs no stack
3273
3274    We must pass this to the assembler so it can generate the
3275    proper pdsc (procedure descriptor)
3276    This is done with the '.pdesc' command.
3277
3278    On not-vms, we don't really differentiate between the two, as we can
3279    simply allocate stack without saving registers.  */
3280
3281 void
3282 alpha_expand_prologue ()
3283 {
3284   /* Registers to save.  */
3285   unsigned long imask = 0;
3286   unsigned long fmask = 0;
3287   /* Stack space needed for pushing registers clobbered by us.  */
3288   HOST_WIDE_INT sa_size;
3289   /* Complete stack size needed.  */
3290   HOST_WIDE_INT frame_size;
3291   /* Offset from base reg to register save area.  */
3292   HOST_WIDE_INT reg_offset;
3293   rtx sa_reg, mem;
3294   int i;
3295
3296   sa_size = alpha_sa_size ();
3297
3298   frame_size = get_frame_size ();
3299   if (TARGET_OPEN_VMS)
3300     frame_size = ALPHA_ROUND (sa_size 
3301                               + (vms_is_stack_procedure ? 8 : 0)
3302                               + frame_size
3303                               + current_function_pretend_args_size);
3304   else
3305     frame_size = (ALPHA_ROUND (current_function_outgoing_args_size)
3306                   + sa_size
3307                   + ALPHA_ROUND (frame_size
3308                                  + current_function_pretend_args_size));
3309
3310   if (TARGET_OPEN_VMS)
3311     reg_offset = 8;
3312   else
3313     reg_offset = ALPHA_ROUND (current_function_outgoing_args_size);
3314
3315   alpha_sa_mask (&imask, &fmask);
3316
3317   /* Adjust the stack by the frame size.  If the frame size is > 4096
3318      bytes, we need to be sure we probe somewhere in the first and last
3319      4096 bytes (we can probably get away without the latter test) and
3320      every 8192 bytes in between.  If the frame size is > 32768, we
3321      do this in a loop.  Otherwise, we generate the explicit probe
3322      instructions. 
3323
3324      Note that we are only allowed to adjust sp once in the prologue.  */
3325
3326   if (frame_size <= 32768)
3327     {
3328       if (frame_size > 4096)
3329         {
3330           int probed = 4096;
3331
3332           do
3333             emit_insn (gen_probe_stack (GEN_INT (-probed)));
3334           while ((probed += 8192) < frame_size);
3335
3336           /* We only have to do this probe if we aren't saving registers.  */
3337           if (sa_size == 0 && probed + 4096 < frame_size)
3338             emit_insn (gen_probe_stack (GEN_INT (-frame_size)));
3339         }
3340
3341       if (frame_size != 0)
3342         {
3343           FRP (emit_move_insn (stack_pointer_rtx,
3344                                plus_constant (stack_pointer_rtx, -frame_size)));
3345         }
3346     }
3347   else
3348     {
3349       /* Here we generate code to set R22 to SP + 4096 and set R23 to the
3350          number of 8192 byte blocks to probe.  We then probe each block
3351          in the loop and then set SP to the proper location.  If the
3352          amount remaining is > 4096, we have to do one more probe if we
3353          are not saving any registers.  */
3354
3355       HOST_WIDE_INT blocks = (frame_size + 4096) / 8192;
3356       HOST_WIDE_INT leftover = frame_size + 4096 - blocks * 8192;
3357       rtx ptr = gen_rtx_REG (DImode, 22);
3358       rtx count = gen_rtx_REG (DImode, 23);
3359
3360       emit_move_insn (count, GEN_INT (blocks));
3361       emit_move_insn (ptr, plus_constant (stack_pointer_rtx, 4096));
3362
3363       /* Because of the difficulty in emitting a new basic block this
3364          late in the compilation, generate the loop as a single insn.  */
3365       emit_insn (gen_prologue_stack_probe_loop (count, ptr));
3366
3367       if (leftover > 4096 && sa_size == 0)
3368         {
3369           rtx last = gen_rtx_MEM (DImode, plus_constant (ptr, -leftover));
3370           MEM_VOLATILE_P (last) = 1;
3371           emit_move_insn (last, const0_rtx);
3372         }
3373
3374       ptr = emit_move_insn (stack_pointer_rtx, plus_constant (ptr, -leftover));
3375
3376       /* This alternative is special, because the DWARF code cannot possibly
3377          intuit through the loop above.  So we invent this note it looks at
3378          instead.  */
3379       RTX_FRAME_RELATED_P (ptr) = 1;
3380       REG_NOTES (ptr)
3381         = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
3382                              gen_rtx_SET (VOIDmode, stack_pointer_rtx,
3383                                gen_rtx_PLUS (Pmode, stack_pointer_rtx,
3384                                              GEN_INT (-frame_size))),
3385                              REG_NOTES (ptr));
3386     }
3387
3388   /* Cope with very large offsets to the register save area.  */
3389   sa_reg = stack_pointer_rtx;
3390   if (reg_offset + sa_size > 0x8000)
3391     {
3392       int low = ((reg_offset & 0xffff) ^ 0x8000) - 0x8000;
3393       HOST_WIDE_INT bias;
3394
3395       if (low + sa_size <= 0x8000)
3396         bias = reg_offset - low, reg_offset = low;
3397       else 
3398         bias = reg_offset, reg_offset = 0;
3399
3400       sa_reg = gen_rtx_REG (DImode, 24);
3401       FRP (emit_move_insn (sa_reg, plus_constant (stack_pointer_rtx, bias)));
3402     }
3403     
3404   /* Save regs in stack order.  Beginning with VMS PV.  */
3405   if (TARGET_OPEN_VMS && vms_is_stack_procedure)
3406     {
3407       mem = gen_rtx_MEM (DImode, stack_pointer_rtx);
3408       MEM_ALIAS_SET (mem) = alpha_sr_alias_set;
3409       FRP (emit_move_insn (mem, gen_rtx_REG (DImode, REG_PV)));
3410     }
3411
3412   /* Save register RA next.  */
3413   if (imask & (1L << REG_RA))
3414     {
3415       mem = gen_rtx_MEM (DImode, plus_constant (sa_reg, reg_offset));
3416       MEM_ALIAS_SET (mem) = alpha_sr_alias_set;
3417       FRP (emit_move_insn (mem, gen_rtx_REG (DImode, REG_RA)));
3418       imask &= ~(1L << REG_RA);
3419       reg_offset += 8;
3420     }
3421
3422   /* Now save any other registers required to be saved.  */
3423   for (i = 0; i < 32; i++)
3424     if (imask & (1L << i))
3425       {
3426         mem = gen_rtx_MEM (DImode, plus_constant (sa_reg, reg_offset));
3427         MEM_ALIAS_SET (mem) = alpha_sr_alias_set;
3428         FRP (emit_move_insn (mem, gen_rtx_REG (DImode, i)));
3429         reg_offset += 8;
3430       }
3431
3432   for (i = 0; i < 32; i++)
3433     if (fmask & (1L << i))
3434       {
3435         mem = gen_rtx_MEM (DFmode, plus_constant (sa_reg, reg_offset));
3436         MEM_ALIAS_SET (mem) = alpha_sr_alias_set;
3437         FRP (emit_move_insn (mem, gen_rtx_REG (DFmode, i+32)));
3438         reg_offset += 8;
3439       }
3440
3441   if (TARGET_OPEN_VMS)
3442     {
3443       if (!vms_is_stack_procedure)
3444         {
3445           /* Register frame procedures fave the fp.  */
3446           FRP (emit_move_insn (gen_rtx_REG (DImode, vms_save_fp_regno),
3447                                hard_frame_pointer_rtx));
3448         }
3449
3450       if (vms_base_regno != REG_PV)
3451         FRP (emit_move_insn (gen_rtx_REG (DImode, vms_base_regno),
3452                              gen_rtx_REG (DImode, REG_PV)));
3453
3454       if (vms_unwind_regno == HARD_FRAME_POINTER_REGNUM)
3455         {
3456           FRP (emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx));
3457         }
3458
3459       /* If we have to allocate space for outgoing args, do it now.  */
3460       if (current_function_outgoing_args_size != 0)
3461         {
3462           FRP (emit_move_insn (stack_pointer_rtx, 
3463                 plus_constant (hard_frame_pointer_rtx,
3464                  - ALPHA_ROUND (current_function_outgoing_args_size))));
3465         }
3466     }
3467   else
3468     {
3469       /* If we need a frame pointer, set it from the stack pointer.  */
3470       if (frame_pointer_needed)
3471         {
3472           if (TARGET_CAN_FAULT_IN_PROLOGUE)
3473             FRP (emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx));
3474           else
3475             {
3476               /* This must always be the last instruction in the
3477                  prologue, thus we emit a special move + clobber.  */
3478               FRP (emit_insn (gen_init_fp (hard_frame_pointer_rtx,
3479                                            stack_pointer_rtx, sa_reg)));
3480             }
3481         }
3482     }
3483
3484   /* The ABIs for VMS and OSF/1 say that while we can schedule insns into
3485      the prologue, for exception handling reasons, we cannot do this for
3486      any insn that might fault.  We could prevent this for mems with a
3487      (clobber:BLK (scratch)), but this doesn't work for fp insns.  So we
3488      have to prevent all such scheduling with a blockage.
3489
3490      Linux, on the other hand, never bothered to implement OSF/1's 
3491      exception handling, and so doesn't care about such things.  Anyone
3492      planning to use dwarf2 frame-unwind info can also omit the blockage.  */
3493
3494   if (! TARGET_CAN_FAULT_IN_PROLOGUE)
3495     emit_insn (gen_blockage ());
3496 }
3497
3498 /* Output the textual info surrounding the prologue.  */
3499
3500 void
3501 alpha_start_function (file, fnname, decl)
3502      FILE *file;
3503      char *fnname;
3504      tree decl ATTRIBUTE_UNUSED;
3505 {
3506   unsigned long imask = 0;
3507   unsigned long fmask = 0;
3508   /* Stack space needed for pushing registers clobbered by us.  */
3509   HOST_WIDE_INT sa_size;
3510   /* Complete stack size needed.  */
3511   HOST_WIDE_INT frame_size;
3512   /* Offset from base reg to register save area.  */
3513   HOST_WIDE_INT reg_offset;
3514   char *entry_label = (char *) alloca (strlen (fnname) + 6);
3515   int i;
3516
3517   sa_size = alpha_sa_size ();
3518
3519   frame_size = get_frame_size ();
3520   if (TARGET_OPEN_VMS)
3521     frame_size = ALPHA_ROUND (sa_size 
3522                               + (vms_is_stack_procedure ? 8 : 0)
3523                               + frame_size
3524                               + current_function_pretend_args_size);
3525   else
3526     frame_size = (ALPHA_ROUND (current_function_outgoing_args_size)
3527                   + sa_size
3528                   + ALPHA_ROUND (frame_size
3529                                  + current_function_pretend_args_size));
3530
3531   if (TARGET_OPEN_VMS)
3532     reg_offset = 8;
3533   else
3534     reg_offset = ALPHA_ROUND (current_function_outgoing_args_size);
3535
3536   alpha_sa_mask (&imask, &fmask);
3537
3538   /* Ecoff can handle multiple .file directives, so put out file and lineno.
3539      We have to do that before the .ent directive as we cannot switch
3540      files within procedures with native ecoff because line numbers are
3541      linked to procedure descriptors.
3542      Outputting the lineno helps debugging of one line functions as they
3543      would otherwise get no line number at all. Please note that we would
3544      like to put out last_linenum from final.c, but it is not accessible.  */
3545
3546   if (write_symbols == SDB_DEBUG)
3547     {
3548       ASM_OUTPUT_SOURCE_FILENAME (file,
3549                                   DECL_SOURCE_FILE (current_function_decl));
3550       if (debug_info_level != DINFO_LEVEL_TERSE)
3551         ASM_OUTPUT_SOURCE_LINE (file,
3552                                 DECL_SOURCE_LINE (current_function_decl));
3553     }
3554
3555   /* Issue function start and label.  */
3556   if (TARGET_OPEN_VMS || !flag_inhibit_size_directive)
3557     {
3558       fputs ("\t.ent ", file);
3559       assemble_name (file, fnname);
3560       putc ('\n', file);
3561     }
3562
3563   strcpy (entry_label, fnname);
3564   if (TARGET_OPEN_VMS)
3565     strcat (entry_label, "..en");
3566   ASM_OUTPUT_LABEL (file, entry_label);
3567   inside_function = TRUE;
3568
3569   if (TARGET_OPEN_VMS)
3570     fprintf (file, "\t.base $%d\n", vms_base_regno);
3571
3572   if (!TARGET_OPEN_VMS && TARGET_IEEE_CONFORMANT
3573       && !flag_inhibit_size_directive)
3574     {
3575       /* Set flags in procedure descriptor to request IEEE-conformant
3576          math-library routines.  The value we set it to is PDSC_EXC_IEEE
3577          (/usr/include/pdsc.h). */
3578       fputs ("\t.eflag 48\n", file);
3579     }
3580
3581   /* Set up offsets to alpha virtual arg/local debugging pointer.  */
3582   alpha_auto_offset = -frame_size + current_function_pretend_args_size;
3583   alpha_arg_offset = -frame_size + 48;
3584
3585   /* Describe our frame.  If the frame size is larger than an integer,
3586      print it as zero to avoid an assembler error.  We won't be
3587      properly describing such a frame, but that's the best we can do.  */
3588   if (TARGET_OPEN_VMS)
3589     {
3590       fprintf (file, "\t.frame $%d,", vms_unwind_regno);
3591       fprintf (file, HOST_WIDE_INT_PRINT_DEC,
3592                frame_size >= (1l << 31) ? 0 : frame_size);
3593       fputs (",$26,", file);
3594       fprintf (file, HOST_WIDE_INT_PRINT_DEC, reg_offset);
3595       fputs ("\n", file);
3596     }
3597   else if (!flag_inhibit_size_directive)
3598     {
3599       fprintf (file, "\t.frame $%d,",
3600                (frame_pointer_needed
3601                 ? HARD_FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM));
3602       fprintf (file, HOST_WIDE_INT_PRINT_DEC,
3603                frame_size >= (1l << 31) ? 0 : frame_size);
3604       fprintf (file, ",$26,%d\n", current_function_pretend_args_size);
3605     }
3606
3607   /* Describe which registers were spilled.  */
3608   if (TARGET_OPEN_VMS)
3609     {
3610       if (imask)
3611         /* ??? Does VMS care if mask contains ra?  The old code did'nt
3612            set it, so I don't here.  */
3613         fprintf (file, "\t.mask 0x%lx,0\n", imask & ~(1L << REG_RA));
3614       if (fmask)
3615         fprintf (file, "\t.fmask 0x%lx,0\n", fmask);
3616       if (!vms_is_stack_procedure)
3617         fprintf (file, "\t.fp_save $%d\n", vms_save_fp_regno);
3618     }
3619   else if (!flag_inhibit_size_directive)
3620     {
3621       if (imask)
3622         {
3623           fprintf (file, "\t.mask 0x%lx,", imask);
3624           fprintf (file, HOST_WIDE_INT_PRINT_DEC,
3625                    frame_size >= (1l << 31) ? 0 : reg_offset - frame_size);
3626           putc ('\n', file);
3627
3628           for (i = 0; i < 32; ++i)
3629             if (imask & (1L << i))
3630               reg_offset += 8;
3631         }
3632
3633       if (fmask)
3634         {
3635           fprintf (file, "\t.fmask 0x%lx,", fmask);
3636           fprintf (file, HOST_WIDE_INT_PRINT_DEC,
3637                    frame_size >= (1l << 31) ? 0 : reg_offset - frame_size);
3638           putc ('\n', file);
3639         }
3640     }
3641
3642   /* Emit GP related things.  It is rather unfortunate about the alignment
3643      issues surrounding a CODE_LABEL that forces us to do the label in 
3644      plain text.  */
3645   if (!TARGET_OPEN_VMS && !TARGET_WINDOWS_NT)
3646     {
3647       alpha_function_needs_gp = alpha_does_function_need_gp ();
3648       if (alpha_function_needs_gp)
3649         fputs ("\tldgp $29,0($27)\n", file);
3650
3651       putc ('$', file);
3652       assemble_name (file, fnname);
3653       fputs ("..ng:\n", file);
3654     }
3655
3656 #ifdef OPEN_VMS
3657   /* Ifdef'ed cause readonly_section and link_section are only
3658      available then.  */
3659   readonly_section ();
3660   fprintf (file, "\t.align 3\n");
3661   assemble_name (file, fnname); fputs ("..na:\n", file);
3662   fputs ("\t.ascii \"", file);
3663   assemble_name (file, fnname);
3664   fputs ("\\0\"\n", file);
3665       
3666   link_section ();
3667   fprintf (file, "\t.align 3\n");
3668   fputs ("\t.name ", file);
3669   assemble_name (file, fnname);
3670   fputs ("..na\n", file);
3671   ASM_OUTPUT_LABEL (file, fnname);
3672   fprintf (file, "\t.pdesc ");
3673   assemble_name (file, fnname);
3674   fprintf (file, "..en,%s\n", vms_is_stack_procedure ? "stack" : "reg");
3675   alpha_need_linkage (fnname, 1);
3676   text_section ();
3677 #endif
3678 }
3679
3680 /* Emit the .prologue note at the scheduled end of the prologue.  */
3681
3682 void
3683 output_end_prologue (file)
3684      FILE *file;
3685 {
3686   if (TARGET_OPEN_VMS)
3687     fputs ("\t.prologue\n", file);
3688   else if (TARGET_WINDOWS_NT)
3689     fputs ("\t.prologue 0\n", file);
3690   else if (!flag_inhibit_size_directive)
3691     fprintf (file, "\t.prologue %d\n", alpha_function_needs_gp);
3692 }
3693
3694 /* Write function epilogue.  */
3695
3696 /* ??? At some point we will want to support full unwind, and so will 
3697    need to mark the epilogue as well.  At the moment, we just confuse
3698    dwarf2out.  */
3699 #undef FRP
3700 #define FRP(exp) exp
3701
3702 void
3703 alpha_expand_epilogue ()
3704 {
3705   /* Registers to save.  */
3706   unsigned long imask = 0;
3707   unsigned long fmask = 0;
3708   /* Stack space needed for pushing registers clobbered by us.  */
3709   HOST_WIDE_INT sa_size;
3710   /* Complete stack size needed.  */
3711   HOST_WIDE_INT frame_size;
3712   /* Offset from base reg to register save area.  */
3713   HOST_WIDE_INT reg_offset;
3714   int fp_is_frame_pointer, fp_offset;
3715   rtx sa_reg, sa_reg_exp = NULL;
3716   rtx sp_adj1, sp_adj2, mem;
3717   int i;
3718
3719   sa_size = alpha_sa_size ();
3720
3721   frame_size = get_frame_size ();
3722   if (TARGET_OPEN_VMS)
3723     frame_size = ALPHA_ROUND (sa_size 
3724                               + (vms_is_stack_procedure ? 8 : 0)
3725                               + frame_size
3726                               + current_function_pretend_args_size);
3727   else
3728     frame_size = (ALPHA_ROUND (current_function_outgoing_args_size)
3729                   + sa_size
3730                   + ALPHA_ROUND (frame_size
3731                                  + current_function_pretend_args_size));
3732
3733   if (TARGET_OPEN_VMS)
3734     reg_offset = 8;
3735   else
3736     reg_offset = ALPHA_ROUND (current_function_outgoing_args_size);
3737
3738   alpha_sa_mask (&imask, &fmask);
3739
3740   fp_is_frame_pointer = ((TARGET_OPEN_VMS && vms_is_stack_procedure)
3741                          || (!TARGET_OPEN_VMS && frame_pointer_needed));
3742
3743   if (sa_size)
3744     {
3745       /* If we have a frame pointer, restore SP from it.  */
3746       if ((TARGET_OPEN_VMS
3747            && vms_unwind_regno == HARD_FRAME_POINTER_REGNUM)
3748           || (!TARGET_OPEN_VMS && frame_pointer_needed))
3749         {
3750           FRP (emit_move_insn (stack_pointer_rtx, hard_frame_pointer_rtx));
3751         }
3752
3753       /* Cope with very large offsets to the register save area.  */
3754       sa_reg = stack_pointer_rtx;
3755       if (reg_offset + sa_size > 0x8000)
3756         {
3757           int low = ((reg_offset & 0xffff) ^ 0x8000) - 0x8000;
3758           HOST_WIDE_INT bias;
3759
3760           if (low + sa_size <= 0x8000)
3761             bias = reg_offset - low, reg_offset = low;
3762           else 
3763             bias = reg_offset, reg_offset = 0;
3764
3765           sa_reg = gen_rtx_REG (DImode, 22);
3766           sa_reg_exp = plus_constant (stack_pointer_rtx, bias);
3767
3768           FRP (emit_move_insn (sa_reg, sa_reg_exp));
3769         }
3770           
3771       /* Restore registers in order, excepting a true frame pointer. */
3772
3773       if (! alpha_eh_epilogue_sp_ofs)
3774         {
3775           mem = gen_rtx_MEM (DImode, plus_constant(sa_reg, reg_offset));
3776           MEM_ALIAS_SET (mem) = alpha_sr_alias_set;
3777           FRP (emit_move_insn (gen_rtx_REG (DImode, REG_RA), mem));
3778         }
3779       reg_offset += 8;
3780       imask &= ~(1L << REG_RA);
3781
3782       for (i = 0; i < 32; ++i)
3783         if (imask & (1L << i))
3784           {
3785             if (i == HARD_FRAME_POINTER_REGNUM && fp_is_frame_pointer)
3786               fp_offset = reg_offset;
3787             else
3788               {
3789                 mem = gen_rtx_MEM (DImode, plus_constant(sa_reg, reg_offset));
3790                 MEM_ALIAS_SET (mem) = alpha_sr_alias_set;
3791                 FRP (emit_move_insn (gen_rtx_REG (DImode, i), mem));
3792               }
3793             reg_offset += 8;
3794           }
3795
3796       for (i = 0; i < 32; ++i)
3797         if (fmask & (1L << i))
3798           {
3799             mem = gen_rtx_MEM (DFmode, plus_constant(sa_reg, reg_offset));
3800             MEM_ALIAS_SET (mem) = alpha_sr_alias_set;
3801             FRP (emit_move_insn (gen_rtx_REG (DFmode, i+32), mem));
3802             reg_offset += 8;
3803           }
3804     }
3805
3806   if (frame_size || alpha_eh_epilogue_sp_ofs)
3807     {
3808       sp_adj1 = stack_pointer_rtx;
3809
3810       if (alpha_eh_epilogue_sp_ofs)
3811         {
3812           sp_adj1 = gen_rtx_REG (DImode, 23);
3813           emit_move_insn (sp_adj1,
3814                           gen_rtx_PLUS (Pmode, stack_pointer_rtx,
3815                                         alpha_eh_epilogue_sp_ofs));
3816         }
3817
3818       /* If the stack size is large, begin computation into a temporary
3819          register so as not to interfere with a potential fp restore,
3820          which must be consecutive with an SP restore.  */
3821       if (frame_size < 32768)
3822         sp_adj2 = GEN_INT (frame_size);
3823       else if (frame_size < 0x40007fffL)
3824         {
3825           int low = ((frame_size & 0xffff) ^ 0x8000) - 0x8000;
3826
3827           sp_adj2 = plus_constant (sp_adj1, frame_size - low);
3828           if (sa_reg_exp && rtx_equal_p (sa_reg_exp, sp_adj2))
3829             sp_adj1 = sa_reg;
3830           else
3831             {
3832               sp_adj1 = gen_rtx_REG (DImode, 23);
3833               FRP (emit_move_insn (sp_adj1, sp_adj2));
3834             }
3835           sp_adj2 = GEN_INT (low);
3836         }
3837       else
3838         {
3839           rtx tmp = gen_rtx_REG (DImode, 23);
3840           FRP (sp_adj2 = alpha_emit_set_const (tmp, DImode, frame_size, 3));
3841           if (!sp_adj2)
3842             {
3843               /* We can't drop new things to memory this late, afaik,
3844                  so build it up by pieces.  */
3845               FRP (sp_adj2 = alpha_emit_set_long_const (tmp, frame_size,
3846                                                         -(frame_size < 0)));
3847               if (!sp_adj2)
3848                 abort ();
3849             }
3850         }
3851
3852       /* From now on, things must be in order.  So emit blockages.  */
3853
3854       /* Restore the frame pointer.  */
3855       if (fp_is_frame_pointer)
3856         {
3857           emit_insn (gen_blockage ());
3858           mem = gen_rtx_MEM (DImode, plus_constant(sa_reg, fp_offset));
3859           MEM_ALIAS_SET (mem) = alpha_sr_alias_set;
3860           FRP (emit_move_insn (hard_frame_pointer_rtx, mem));
3861         }
3862       else if (TARGET_OPEN_VMS)
3863         {
3864           emit_insn (gen_blockage ());
3865           FRP (emit_move_insn (hard_frame_pointer_rtx,
3866                                gen_rtx_REG (DImode, vms_save_fp_regno)));
3867         }
3868
3869       /* Restore the stack pointer.  */
3870       emit_insn (gen_blockage ());
3871       FRP (emit_move_insn (stack_pointer_rtx,
3872                            gen_rtx_PLUS (DImode, sp_adj1, sp_adj2)));
3873     }
3874   else 
3875     {
3876       if (TARGET_OPEN_VMS && !vms_is_stack_procedure)
3877         {
3878           emit_insn (gen_blockage ());
3879           FRP (emit_move_insn (hard_frame_pointer_rtx,
3880                                gen_rtx_REG (DImode, vms_save_fp_regno)));
3881         }
3882     }
3883
3884   /* Return.  */
3885   emit_jump_insn (gen_return_internal ());
3886 }
3887
3888 /* Output the rest of the textual info surrounding the epilogue.  */
3889
3890 void
3891 alpha_end_function (file, fnname, decl)
3892      FILE *file;
3893      char *fnname;
3894      tree decl ATTRIBUTE_UNUSED;
3895 {
3896   /* End the function.  */
3897   if (!flag_inhibit_size_directive)
3898     {
3899       fputs ("\t.end ", file);
3900       assemble_name (file, fnname);
3901       putc ('\n', file);
3902     }
3903   inside_function = FALSE;
3904
3905   /* Show that we know this function if it is called again. 
3906
3907      Don't do this for global functions in object files destined for a
3908      shared library because the function may be overridden by the application
3909      or other libraries.
3910      ??? Is this just ELF?  */
3911
3912   if (!flag_pic || !TREE_PUBLIC (current_function_decl))
3913     SYMBOL_REF_FLAG (XEXP (DECL_RTL (current_function_decl), 0)) = 1;
3914 }
3915 \f
3916 /* Debugging support.  */
3917
3918 #include "gstab.h"
3919
3920 /* Count the number of sdb related labels are generated (to find block
3921    start and end boundaries).  */
3922
3923 int sdb_label_count = 0;
3924
3925 /* Next label # for each statement.  */
3926
3927 static int sym_lineno = 0;
3928
3929 /* Count the number of .file directives, so that .loc is up to date.  */
3930
3931 static int num_source_filenames = 0;
3932
3933 /* Name of the file containing the current function.  */
3934
3935 static char *current_function_file = "";
3936
3937 /* Offsets to alpha virtual arg/local debugging pointers.  */
3938
3939 long alpha_arg_offset;
3940 long alpha_auto_offset;
3941 \f
3942 /* Emit a new filename to a stream.  */
3943
3944 void
3945 alpha_output_filename (stream, name)
3946      FILE *stream;
3947      char *name;
3948 {
3949   static int first_time = TRUE;
3950   char ltext_label_name[100];
3951
3952   if (first_time)
3953     {
3954       first_time = FALSE;
3955       ++num_source_filenames;
3956       current_function_file = name;
3957       fprintf (stream, "\t.file\t%d ", num_source_filenames);
3958       output_quoted_string (stream, name);
3959       fprintf (stream, "\n");
3960       if (!TARGET_GAS && write_symbols == DBX_DEBUG)
3961         fprintf (stream, "\t#@stabs\n");
3962     }
3963
3964   else if (write_symbols == DBX_DEBUG)
3965     {
3966       ASM_GENERATE_INTERNAL_LABEL (ltext_label_name, "Ltext", 0);
3967       fprintf (stream, "%s ", ASM_STABS_OP);
3968       output_quoted_string (stream, name);
3969       fprintf (stream, ",%d,0,0,%s\n", N_SOL, &ltext_label_name[1]);
3970     }
3971
3972   else if (name != current_function_file
3973            && strcmp (name, current_function_file) != 0)
3974     {
3975       if (inside_function && ! TARGET_GAS)
3976         fprintf (stream, "\t#.file\t%d ", num_source_filenames);
3977       else
3978         {
3979           ++num_source_filenames;
3980           current_function_file = name;
3981           fprintf (stream, "\t.file\t%d ", num_source_filenames);
3982         }
3983
3984       output_quoted_string (stream, name);
3985       fprintf (stream, "\n");
3986     }
3987 }
3988 \f
3989 /* Emit a linenumber to a stream.  */
3990
3991 void
3992 alpha_output_lineno (stream, line)
3993      FILE *stream;
3994      int line;
3995 {
3996   if (write_symbols == DBX_DEBUG)
3997     {
3998       /* mips-tfile doesn't understand .stabd directives.  */
3999       ++sym_lineno;
4000       fprintf (stream, "$LM%d:\n\t%s %d,0,%d,$LM%d\n",
4001                sym_lineno, ASM_STABN_OP, N_SLINE, line, sym_lineno);
4002     }
4003   else
4004     fprintf (stream, "\n\t.loc\t%d %d\n", num_source_filenames, line);
4005 }
4006 \f
4007 /* Structure to show the current status of registers and memory.  */
4008
4009 struct shadow_summary
4010 {
4011   struct {
4012     unsigned long i     : 31;   /* Mask of int regs */
4013     unsigned long fp    : 31;   /* Mask of fp regs */
4014     unsigned long mem   :  1;   /* mem == imem | fpmem */
4015   } used, defd;
4016 };
4017
4018 static void summarize_insn PROTO((rtx, struct shadow_summary *, int));
4019 static void alpha_handle_trap_shadows PROTO((rtx));
4020
4021 /* Summary the effects of expression X on the machine.  Update SUM, a pointer
4022    to the summary structure.  SET is nonzero if the insn is setting the
4023    object, otherwise zero.  */
4024
4025 static void
4026 summarize_insn (x, sum, set)
4027      rtx x;
4028      struct shadow_summary *sum;
4029      int set;
4030 {
4031   char *format_ptr;
4032   int i, j;
4033
4034   if (x == 0)
4035     return;
4036
4037   switch (GET_CODE (x))
4038     {
4039       /* ??? Note that this case would be incorrect if the Alpha had a
4040          ZERO_EXTRACT in SET_DEST.  */
4041     case SET:
4042       summarize_insn (SET_SRC (x), sum, 0);
4043       summarize_insn (SET_DEST (x), sum, 1);
4044       break;
4045
4046     case CLOBBER:
4047       summarize_insn (XEXP (x, 0), sum, 1);
4048       break;
4049
4050     case USE:
4051       summarize_insn (XEXP (x, 0), sum, 0);
4052       break;
4053
4054     case ASM_OPERANDS:
4055       for (i = ASM_OPERANDS_INPUT_LENGTH (x) - 1; i >= 0; i--)
4056         summarize_insn (ASM_OPERANDS_INPUT (x, i), sum, 0);
4057       break;
4058
4059     case PARALLEL:
4060       for (i = XVECLEN (x, 0) - 1; i >= 0; i--)
4061         summarize_insn (XVECEXP (x, 0, i), sum, 0);
4062       break;
4063
4064     case SUBREG:
4065       summarize_insn (SUBREG_REG (x), sum, 0);
4066       break;
4067
4068     case REG:
4069       {
4070         int regno = REGNO (x);
4071         unsigned long mask = 1UL << (regno % 32);
4072
4073         if (regno == 31 || regno == 63)
4074           break;
4075
4076         if (set)
4077           {
4078             if (regno < 32)
4079               sum->defd.i |= mask;
4080             else
4081               sum->defd.fp |= mask;
4082           }
4083         else
4084           {
4085             if (regno < 32)
4086               sum->used.i  |= mask;
4087             else
4088               sum->used.fp |= mask;
4089           }
4090         }
4091       break;
4092
4093     case MEM:
4094       if (set)
4095         sum->defd.mem = 1;
4096       else
4097         sum->used.mem = 1;
4098
4099       /* Find the regs used in memory address computation: */
4100       summarize_insn (XEXP (x, 0), sum, 0);
4101       break;
4102
4103     case CONST_INT:   case CONST_DOUBLE:
4104     case SYMBOL_REF:  case LABEL_REF:     case CONST:
4105       break;
4106
4107       /* Handle common unary and binary ops for efficiency.  */
4108     case COMPARE:  case PLUS:    case MINUS:   case MULT:      case DIV:
4109     case MOD:      case UDIV:    case UMOD:    case AND:       case IOR:
4110     case XOR:      case ASHIFT:  case ROTATE:  case ASHIFTRT:  case LSHIFTRT:
4111     case ROTATERT: case SMIN:    case SMAX:    case UMIN:      case UMAX:
4112     case NE:       case EQ:      case GE:      case GT:        case LE:
4113     case LT:       case GEU:     case GTU:     case LEU:       case LTU:
4114       summarize_insn (XEXP (x, 0), sum, 0);
4115       summarize_insn (XEXP (x, 1), sum, 0);
4116       break;
4117
4118     case NEG:  case NOT:  case SIGN_EXTEND:  case ZERO_EXTEND:
4119     case TRUNCATE:  case FLOAT_EXTEND:  case FLOAT_TRUNCATE:  case FLOAT:
4120     case FIX:  case UNSIGNED_FLOAT:  case UNSIGNED_FIX:  case ABS:
4121     case SQRT:  case FFS: 
4122       summarize_insn (XEXP (x, 0), sum, 0);
4123       break;
4124
4125     default:
4126       format_ptr = GET_RTX_FORMAT (GET_CODE (x));
4127       for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
4128         switch (format_ptr[i])
4129           {
4130           case 'e':
4131             summarize_insn (XEXP (x, i), sum, 0);
4132             break;
4133
4134           case 'E':
4135             for (j = XVECLEN (x, i) - 1; j >= 0; j--)
4136               summarize_insn (XVECEXP (x, i, j), sum, 0);
4137             break;
4138
4139           case 'i':
4140             break;
4141
4142           default:
4143             abort ();
4144           }
4145     }
4146 }
4147
4148 /* Ensure a sufficient number of `trapb' insns are in the code when
4149    the user requests code with a trap precision of functions or
4150    instructions.
4151
4152    In naive mode, when the user requests a trap-precision of
4153    "instruction", a trapb is needed after every instruction that may
4154    generate a trap.  This ensures that the code is resumption safe but
4155    it is also slow.
4156
4157    When optimizations are turned on, we delay issuing a trapb as long
4158    as possible.  In this context, a trap shadow is the sequence of
4159    instructions that starts with a (potentially) trap generating
4160    instruction and extends to the next trapb or call_pal instruction
4161    (but GCC never generates call_pal by itself).  We can delay (and
4162    therefore sometimes omit) a trapb subject to the following
4163    conditions:
4164
4165    (a) On entry to the trap shadow, if any Alpha register or memory
4166    location contains a value that is used as an operand value by some
4167    instruction in the trap shadow (live on entry), then no instruction
4168    in the trap shadow may modify the register or memory location.
4169
4170    (b) Within the trap shadow, the computation of the base register
4171    for a memory load or store instruction may not involve using the
4172    result of an instruction that might generate an UNPREDICTABLE
4173    result.
4174
4175    (c) Within the trap shadow, no register may be used more than once
4176    as a destination register.  (This is to make life easier for the
4177    trap-handler.)
4178
4179    (d) The trap shadow may not include any branch instructions.  */
4180
4181 static void
4182 alpha_handle_trap_shadows (insns)
4183      rtx insns;
4184 {
4185   struct shadow_summary shadow;
4186   int trap_pending, exception_nesting;
4187   rtx i, n;
4188
4189   trap_pending = 0;
4190   exception_nesting = 0;
4191   shadow.used.i = 0;
4192   shadow.used.fp = 0;
4193   shadow.used.mem = 0;
4194   shadow.defd = shadow.used;
4195   
4196   for (i = insns; i ; i = NEXT_INSN (i))
4197     {
4198       if (GET_CODE (i) == NOTE)
4199         {
4200           switch (NOTE_LINE_NUMBER (i))
4201             {
4202             case NOTE_INSN_EH_REGION_BEG:
4203               exception_nesting++;
4204               if (trap_pending)
4205                 goto close_shadow;
4206               break;
4207
4208             case NOTE_INSN_EH_REGION_END:
4209               exception_nesting--;
4210               if (trap_pending)
4211                 goto close_shadow;
4212               break;
4213
4214             case NOTE_INSN_EPILOGUE_BEG:
4215               if (trap_pending && alpha_tp >= ALPHA_TP_FUNC)
4216                 goto close_shadow;
4217               break;
4218             }
4219         }
4220       else if (trap_pending)
4221         {
4222           if (alpha_tp == ALPHA_TP_FUNC)
4223             {
4224               if (GET_CODE (i) == JUMP_INSN
4225                   && GET_CODE (PATTERN (i)) == RETURN)
4226                 goto close_shadow;
4227             }
4228           else if (alpha_tp == ALPHA_TP_INSN)
4229             {
4230               if (optimize > 0)
4231                 {
4232                   struct shadow_summary sum;
4233
4234                   sum.used.i = 0;
4235                   sum.used.fp = 0;
4236                   sum.used.mem = 0;
4237                   sum.defd = sum.used;
4238
4239                   switch (GET_CODE (i))
4240                     {
4241                     case INSN:
4242                       /* Annoyingly, get_attr_trap will abort on these.  */
4243                       if (GET_CODE (PATTERN (i)) == USE
4244                           || GET_CODE (PATTERN (i)) == CLOBBER)
4245                         break;
4246
4247                       summarize_insn (PATTERN (i), &sum, 0);
4248
4249                       if ((sum.defd.i & shadow.defd.i)
4250                           || (sum.defd.fp & shadow.defd.fp))
4251                         {
4252                           /* (c) would be violated */
4253                           goto close_shadow;
4254                         }
4255
4256                       /* Combine shadow with summary of current insn: */
4257                       shadow.used.i   |= sum.used.i;
4258                       shadow.used.fp  |= sum.used.fp;
4259                       shadow.used.mem |= sum.used.mem;
4260                       shadow.defd.i   |= sum.defd.i;
4261                       shadow.defd.fp  |= sum.defd.fp;
4262                       shadow.defd.mem |= sum.defd.mem;
4263
4264                       if ((sum.defd.i & shadow.used.i)
4265                           || (sum.defd.fp & shadow.used.fp)
4266                           || (sum.defd.mem & shadow.used.mem))
4267                         {
4268                           /* (a) would be violated (also takes care of (b))  */
4269                           if (get_attr_trap (i) == TRAP_YES
4270                               && ((sum.defd.i & sum.used.i)
4271                                   || (sum.defd.fp & sum.used.fp)))
4272                             abort ();
4273
4274                           goto close_shadow;
4275                         }
4276                       break;
4277
4278                     case JUMP_INSN:
4279                     case CALL_INSN:
4280                     case CODE_LABEL:
4281                       goto close_shadow;
4282
4283                     default:
4284                       abort ();
4285                     }
4286                 }
4287               else
4288                 {
4289                 close_shadow:
4290                   n = emit_insn_before (gen_trapb (), i);
4291                   PUT_MODE (n, TImode);
4292                   PUT_MODE (i, TImode);
4293                   trap_pending = 0;
4294                   shadow.used.i = 0;
4295                   shadow.used.fp = 0;
4296                   shadow.used.mem = 0;
4297                   shadow.defd = shadow.used;
4298                 }
4299             }
4300         }
4301
4302       if ((exception_nesting > 0 || alpha_tp >= ALPHA_TP_FUNC)
4303           && GET_CODE (i) == INSN
4304           && GET_CODE (PATTERN (i)) != USE
4305           && GET_CODE (PATTERN (i)) != CLOBBER
4306           && get_attr_trap (i) == TRAP_YES)
4307         {
4308           if (optimize && !trap_pending)
4309             summarize_insn (PATTERN (i), &shadow, 0);
4310           trap_pending = 1;
4311         }
4312     }
4313 }
4314 \f
4315 #ifdef HAIFA
4316 /* Alpha can only issue instruction groups simultaneously if they are
4317    suitibly aligned.  This is very processor-specific.  */
4318
4319 enum alphaev4_pipe {
4320   EV4_STOP = 0,
4321   EV4_IB0 = 1,
4322   EV4_IB1 = 2,
4323   EV4_IBX = 4
4324 };
4325
4326 enum alphaev5_pipe {
4327   EV5_STOP = 0,
4328   EV5_NONE = 1,
4329   EV5_E01 = 2,
4330   EV5_E0 = 4,
4331   EV5_E1 = 8,
4332   EV5_FAM = 16,
4333   EV5_FA = 32,
4334   EV5_FM = 64
4335 };
4336
4337 static enum alphaev4_pipe alphaev4_insn_pipe PROTO((rtx));
4338 static enum alphaev5_pipe alphaev5_insn_pipe PROTO((rtx));
4339 static rtx alphaev4_next_group PROTO((rtx, int*, int*));
4340 static rtx alphaev5_next_group PROTO((rtx, int*, int*));
4341 static rtx alphaev4_next_nop PROTO((int*));
4342 static rtx alphaev5_next_nop PROTO((int*));
4343
4344 static void alpha_align_insns
4345   PROTO((rtx, int, rtx (*)(rtx, int*, int*), rtx (*)(int*), int));
4346
4347 static enum alphaev4_pipe
4348 alphaev4_insn_pipe (insn)
4349      rtx insn;
4350 {
4351   if (recog_memoized (insn) < 0)
4352     return EV4_STOP;
4353   if (get_attr_length (insn) != 4)
4354     return EV4_STOP;
4355
4356   switch (get_attr_type (insn))
4357     {
4358     case TYPE_ILD:
4359     case TYPE_FLD:
4360       return EV4_IBX;
4361
4362     case TYPE_LDSYM:
4363     case TYPE_IADD:
4364     case TYPE_ILOG:
4365     case TYPE_ICMOV:
4366     case TYPE_ICMP:
4367     case TYPE_IST:
4368     case TYPE_FST:
4369     case TYPE_SHIFT:
4370     case TYPE_IMUL:
4371     case TYPE_FBR:
4372       return EV4_IB0;
4373
4374     case TYPE_MISC:
4375     case TYPE_IBR:
4376     case TYPE_JSR:
4377     case TYPE_FCPYS:
4378     case TYPE_FCMOV:
4379     case TYPE_FADD:
4380     case TYPE_FDIV:
4381     case TYPE_FMUL:
4382       return EV4_IB1;
4383
4384     default:
4385       abort();
4386     }
4387 }
4388
4389 static enum alphaev5_pipe
4390 alphaev5_insn_pipe (insn)
4391      rtx insn;
4392 {
4393   if (recog_memoized (insn) < 0)
4394     return EV5_STOP;
4395   if (get_attr_length (insn) != 4)
4396     return EV5_STOP;
4397
4398   switch (get_attr_type (insn))
4399     {
4400     case TYPE_ILD:
4401     case TYPE_FLD:
4402     case TYPE_LDSYM:
4403     case TYPE_IADD:
4404     case TYPE_ILOG:
4405     case TYPE_ICMOV:
4406     case TYPE_ICMP:
4407       return EV5_E01;
4408
4409     case TYPE_IST:
4410     case TYPE_FST:
4411     case TYPE_SHIFT:
4412     case TYPE_IMUL:
4413     case TYPE_MISC:
4414     case TYPE_MVI:
4415       return EV5_E0;
4416
4417     case TYPE_IBR:
4418     case TYPE_JSR:
4419       return EV5_E1;
4420
4421     case TYPE_FCPYS:
4422       return EV5_FAM;
4423
4424     case TYPE_FBR:
4425     case TYPE_FCMOV:
4426     case TYPE_FADD:
4427     case TYPE_FDIV:
4428       return EV5_FA;
4429
4430     case TYPE_FMUL:
4431       return EV5_FM;
4432
4433     default:
4434       abort();
4435     }
4436 }
4437
4438 /* IN_USE is a mask of the slots currently filled within the insn group. 
4439    The mask bits come from alphaev4_pipe above.  If EV4_IBX is set, then
4440    the insn in EV4_IB0 can be swapped by the hardware into EV4_IB1. 
4441
4442    LEN is, of course, the length of the group in bytes.  */
4443
4444 static rtx
4445 alphaev4_next_group (insn, pin_use, plen)
4446      rtx insn;
4447      int *pin_use, *plen;
4448 {
4449   int len, in_use;
4450
4451   len = in_use = 0;
4452
4453   if (GET_RTX_CLASS (GET_CODE (insn)) != 'i'
4454       || GET_CODE (PATTERN (insn)) == CLOBBER
4455       || GET_CODE (PATTERN (insn)) == USE)
4456     goto next_and_done;
4457
4458   while (1)
4459     {
4460       enum alphaev4_pipe pipe;
4461
4462       pipe = alphaev4_insn_pipe (insn);
4463       switch (pipe)
4464         {
4465         case EV4_STOP:
4466           /* Force complex instructions to start new groups.  */
4467           if (in_use)
4468             goto done;
4469
4470           /* If this is a completely unrecognized insn, its an asm.
4471              We don't know how long it is, so record length as -1 to
4472              signal a needed realignment.  */
4473           if (recog_memoized (insn) < 0)
4474             len = -1;
4475           else
4476             len = get_attr_length (insn);
4477           goto next_and_done;
4478
4479         case EV4_IBX:
4480           if (in_use & EV4_IB0)
4481             {
4482               if (in_use & EV4_IB1)
4483                 goto done;
4484               in_use |= EV4_IB1;
4485             }
4486           else
4487             in_use |= EV4_IB0 | EV4_IBX;
4488           break;
4489
4490         case EV4_IB0:
4491           if (in_use & EV4_IB0)
4492             {
4493               if (!(in_use & EV4_IBX) || (in_use & EV4_IB1))
4494                 goto done;
4495               in_use |= EV4_IB1;
4496             }
4497           in_use |= EV4_IB0;
4498           break;
4499
4500         case EV4_IB1:
4501           if (in_use & EV4_IB1)
4502             goto done;
4503           in_use |= EV4_IB1;
4504           break;
4505
4506         default:
4507           abort();
4508         }
4509       len += 4;
4510       
4511       /* Haifa doesn't do well scheduling branches.  */
4512       if (GET_CODE (insn) == JUMP_INSN)
4513         goto next_and_done;
4514
4515     next:
4516       insn = next_nonnote_insn (insn);
4517
4518       if (!insn || GET_RTX_CLASS (GET_CODE (insn)) != 'i')
4519         goto done;
4520
4521       /* Let Haifa tell us where it thinks insn group boundaries are.  */
4522       if (GET_MODE (insn) == TImode)
4523         goto done;
4524
4525       if (GET_CODE (insn) == CLOBBER || GET_CODE (insn) == USE)
4526         goto next;
4527     }
4528
4529  next_and_done:
4530   insn = next_nonnote_insn (insn);
4531
4532  done:
4533   *plen = len;
4534   *pin_use = in_use;
4535   return insn;
4536 }
4537
4538 /* IN_USE is a mask of the slots currently filled within the insn group. 
4539    The mask bits come from alphaev5_pipe above.  If EV5_E01 is set, then
4540    the insn in EV5_E0 can be swapped by the hardware into EV5_E1. 
4541
4542    LEN is, of course, the length of the group in bytes.  */
4543
4544 static rtx
4545 alphaev5_next_group (insn, pin_use, plen)
4546      rtx insn;
4547      int *pin_use, *plen;
4548 {
4549   int len, in_use;
4550
4551   len = in_use = 0;
4552
4553   if (GET_RTX_CLASS (GET_CODE (insn)) != 'i'
4554       || GET_CODE (PATTERN (insn)) == CLOBBER
4555       || GET_CODE (PATTERN (insn)) == USE)
4556     goto next_and_done;
4557
4558   while (1)
4559     {
4560       enum alphaev5_pipe pipe;
4561
4562       pipe = alphaev5_insn_pipe (insn);
4563       switch (pipe)
4564         {
4565         case EV5_STOP:
4566           /* Force complex instructions to start new groups.  */
4567           if (in_use)
4568             goto done;
4569
4570           /* If this is a completely unrecognized insn, its an asm.
4571              We don't know how long it is, so record length as -1 to
4572              signal a needed realignment.  */
4573           if (recog_memoized (insn) < 0)
4574             len = -1;
4575           else
4576             len = get_attr_length (insn);
4577           goto next_and_done;
4578
4579         /* ??? Most of the places below, we would like to abort, as 
4580            it would indicate an error either in Haifa, or in the 
4581            scheduling description.  Unfortunately, Haifa never 
4582            schedules the last instruction of the BB, so we don't
4583            have an accurate TI bit to go off.  */
4584         case EV5_E01:
4585           if (in_use & EV5_E0)
4586             {
4587               if (in_use & EV5_E1)
4588                 goto done;
4589               in_use |= EV5_E1;
4590             }
4591           else
4592             in_use |= EV5_E0 | EV5_E01;
4593           break;
4594
4595         case EV5_E0:
4596           if (in_use & EV5_E0)
4597             {
4598               if (!(in_use & EV5_E01) || (in_use & EV5_E1))
4599                 goto done;
4600               in_use |= EV5_E1;
4601             }
4602           in_use |= EV5_E0;
4603           break;
4604
4605         case EV5_E1:
4606           if (in_use & EV5_E1)
4607             goto done;
4608           in_use |= EV5_E1;
4609           break;
4610
4611         case EV5_FAM:
4612           if (in_use & EV5_FA)
4613             {
4614               if (in_use & EV5_FM)
4615                 goto done;
4616               in_use |= EV5_FM;
4617             }
4618           else
4619             in_use |= EV5_FA | EV5_FAM;
4620           break;
4621
4622         case EV5_FA:
4623           if (in_use & EV5_FA)
4624             goto done;
4625           in_use |= EV5_FA;
4626           break;
4627
4628         case EV5_FM:
4629           if (in_use & EV5_FM)
4630             goto done;
4631           in_use |= EV5_FM;
4632           break;
4633
4634         case EV5_NONE:
4635           break;
4636
4637         default:
4638           abort();
4639         }
4640       len += 4;
4641       
4642       /* Haifa doesn't do well scheduling branches.  */
4643       /* ??? If this is predicted not-taken, slotting continues, except
4644          that no more IBR, FBR, or JSR insns may be slotted.  */
4645       if (GET_CODE (insn) == JUMP_INSN)
4646         goto next_and_done;
4647
4648     next:
4649       insn = next_nonnote_insn (insn);
4650
4651       if (!insn || GET_RTX_CLASS (GET_CODE (insn)) != 'i')
4652         goto done;
4653
4654       /* Let Haifa tell us where it thinks insn group boundaries are.  */
4655       if (GET_MODE (insn) == TImode)
4656         goto done;
4657
4658       if (GET_CODE (insn) == CLOBBER || GET_CODE (insn) == USE)
4659         goto next;
4660     }
4661
4662  next_and_done:
4663   insn = next_nonnote_insn (insn);
4664
4665  done:
4666   *plen = len;
4667   *pin_use = in_use;
4668   return insn;
4669 }
4670
4671 static rtx
4672 alphaev4_next_nop (pin_use)
4673      int *pin_use;
4674 {
4675   int in_use = *pin_use;
4676   rtx nop;
4677
4678   if (!(in_use & EV4_IB0))
4679     {
4680       in_use |= EV4_IB0;
4681       nop = gen_nop ();
4682     }
4683   else if ((in_use & (EV4_IBX|EV4_IB1)) == EV4_IBX)
4684     {
4685       in_use |= EV4_IB1;
4686       nop = gen_nop ();
4687     }
4688   else if (TARGET_FP && !(in_use & EV4_IB1))
4689     {
4690       in_use |= EV4_IB1;
4691       nop = gen_fnop ();
4692     }
4693   else
4694     nop = gen_unop ();
4695
4696   *pin_use = in_use;
4697   return nop;
4698 }
4699
4700 static rtx
4701 alphaev5_next_nop (pin_use)
4702      int *pin_use;
4703 {
4704   int in_use = *pin_use;
4705   rtx nop;
4706
4707   if (!(in_use & EV5_E1))
4708     {
4709       in_use |= EV5_E1;
4710       nop = gen_nop ();
4711     }
4712   else if (TARGET_FP && !(in_use & EV5_FA))
4713     {
4714       in_use |= EV5_FA;
4715       nop = gen_fnop ();
4716     }
4717   else if (TARGET_FP && !(in_use & EV5_FM))
4718     {
4719       in_use |= EV5_FM;
4720       nop = gen_fnop ();
4721     }
4722   else
4723     nop = gen_unop ();
4724
4725   *pin_use = in_use;
4726   return nop;
4727 }
4728
4729 /* The instruction group alignment main loop.  */
4730
4731 static void
4732 alpha_align_insns (insns, max_align, next_group, next_nop, gp_in_use)
4733      rtx insns;
4734      int max_align;
4735      rtx (*next_group) PROTO((rtx, int*, int*));
4736      rtx (*next_nop) PROTO((int*));
4737      int gp_in_use;
4738 {
4739   /* ALIGN is the known alignment for the insn group.  */
4740   int align;
4741   /* OFS is the offset of the current insn in the insn group.  */
4742   int ofs;
4743   int prev_in_use, in_use, len;
4744   rtx i, next;
4745
4746   /* Let shorten branches care for assigning alignments to code labels.  */
4747   shorten_branches (insns);
4748
4749   align = (FUNCTION_BOUNDARY/BITS_PER_UNIT < max_align
4750            ? FUNCTION_BOUNDARY/BITS_PER_UNIT : max_align);
4751
4752   /* Account for the initial GP load, which happens before the scheduled
4753      prologue we emitted as RTL.  */
4754   ofs = prev_in_use = 0;
4755   if (alpha_does_function_need_gp())
4756     {
4757       ofs = 8 & (align - 1);
4758       prev_in_use = gp_in_use;
4759     }
4760
4761   i = insns;
4762   if (GET_CODE (i) == NOTE)
4763     i = next_nonnote_insn (i);
4764
4765   while (i)
4766     {
4767       next = (*next_group)(i, &in_use, &len);
4768
4769       /* When we see a label, resync alignment etc.  */
4770       if (GET_CODE (i) == CODE_LABEL)
4771         {
4772           int new_align = 1 << label_to_alignment (i);
4773           if (new_align >= align)
4774             {
4775               align = new_align < max_align ? new_align : max_align;
4776               ofs = 0;
4777             }
4778           else if (ofs & (new_align-1))
4779             ofs = (ofs | (new_align-1)) + 1;
4780           if (len != 0)
4781             abort();
4782         }
4783
4784       /* Handle complex instructions special.  */
4785       else if (in_use == 0)
4786         {
4787           /* Asms will have length < 0.  This is a signal that we have
4788              lost alignment knowledge.  Assume, however, that the asm
4789              will not mis-align instructions.  */
4790           if (len < 0)
4791             {
4792               ofs = 0;
4793               align = 4;
4794               len = 0;
4795             }
4796         }
4797
4798       /* If the known alignment is smaller than the recognized insn group,
4799          realign the output.  */
4800       else if (align < len)
4801         {
4802           int new_log_align = len > 8 ? 4 : 3;
4803           rtx where;
4804
4805           where = prev_nonnote_insn (i);
4806           if (!where || GET_CODE (where) != CODE_LABEL)
4807             where = i;
4808
4809           emit_insn_before (gen_realign (GEN_INT (new_log_align)), where);
4810           align = 1 << new_log_align;
4811           ofs = 0;
4812         }
4813
4814       /* If the group won't fit in the same INT16 as the previous,
4815          we need to add padding to keep the group together.  Rather
4816          than simply leaving the insn filling to the assembler, we
4817          can make use of the knowledge of what sorts of instructions
4818          were issued in the previous group to make sure that all of
4819          the added nops are really free.  */
4820       else if (ofs + len > align)
4821         {
4822           int nop_count = (align - ofs) / 4;
4823           rtx where;
4824
4825           /* Insert nops before labels and branches to truely merge the
4826              execution of the nops with the previous instruction group.  */
4827           where = prev_nonnote_insn (i);
4828           if (where)
4829             {
4830               if (GET_CODE (where) == CODE_LABEL)
4831                 {
4832                   rtx where2 = prev_nonnote_insn (where);
4833                   if (where2 && GET_CODE (where2) == JUMP_INSN)
4834                     where = where2;
4835                 }
4836               else if (GET_CODE (where) != JUMP_INSN)
4837                 where = i;
4838             }
4839           else
4840             where = i;
4841
4842           do 
4843             emit_insn_before ((*next_nop)(&prev_in_use), where);
4844           while (--nop_count);
4845           ofs = 0;
4846         }
4847
4848       ofs = (ofs + len) & (align - 1);
4849       prev_in_use = in_use;
4850       i = next;
4851     }
4852 }
4853 #endif /* HAIFA */
4854 \f
4855 /* Machine dependant reorg pass.  */
4856
4857 void
4858 alpha_reorg (insns)
4859      rtx insns;
4860 {
4861   if (alpha_tp != ALPHA_TP_PROG || flag_exceptions)
4862     alpha_handle_trap_shadows (insns);
4863
4864 #ifdef HAIFA
4865   /* Due to the number of extra trapb insns, don't bother fixing up
4866      alignment when trap precision is instruction.  Moreover, we can
4867      only do our job when sched2 is run and Haifa is our scheduler.  */
4868   if (optimize && !optimize_size
4869       && alpha_tp != ALPHA_TP_INSN
4870       && flag_schedule_insns_after_reload)
4871     {
4872       if (alpha_cpu == PROCESSOR_EV4)
4873         alpha_align_insns (insns, 8, alphaev4_next_group,
4874                            alphaev4_next_nop, EV4_IB0);
4875       else if (alpha_cpu == PROCESSOR_EV5)
4876         alpha_align_insns (insns, 16, alphaev5_next_group,
4877                            alphaev5_next_nop, EV5_E01 | EV5_E0);
4878     }
4879 #endif
4880 }
4881
4882 \f
4883 /* Check a floating-point value for validity for a particular machine mode.  */
4884
4885 static char * const float_strings[] =
4886 {
4887   /* These are for FLOAT_VAX.  */
4888    "1.70141173319264430e+38", /* 2^127 (2^24 - 1) / 2^24 */
4889   "-1.70141173319264430e+38",
4890    "2.93873587705571877e-39", /* 2^-128 */
4891   "-2.93873587705571877e-39",
4892   /* These are for the default broken IEEE mode, which traps
4893      on infinity or denormal numbers.  */
4894    "3.402823466385288598117e+38", /* 2^128 (1 - 2^-24) */
4895   "-3.402823466385288598117e+38",
4896    "1.1754943508222875079687e-38", /* 2^-126 */
4897   "-1.1754943508222875079687e-38",
4898 };
4899
4900 static REAL_VALUE_TYPE float_values[8];
4901 static int inited_float_values = 0;
4902
4903 int
4904 check_float_value (mode, d, overflow)
4905      enum machine_mode mode;
4906      REAL_VALUE_TYPE *d;
4907      int overflow ATTRIBUTE_UNUSED;
4908 {
4909
4910   if (TARGET_IEEE || TARGET_IEEE_CONFORMANT || TARGET_IEEE_WITH_INEXACT)
4911     return 0;
4912
4913   if (inited_float_values == 0)
4914     {
4915       int i;
4916       for (i = 0; i < 8; i++)
4917         float_values[i] = REAL_VALUE_ATOF (float_strings[i], DFmode);
4918
4919       inited_float_values = 1;
4920     }
4921
4922   if (mode == SFmode)
4923     {
4924       REAL_VALUE_TYPE r;
4925       REAL_VALUE_TYPE *fvptr;
4926
4927       if (TARGET_FLOAT_VAX)
4928         fvptr = &float_values[0];
4929       else
4930         fvptr = &float_values[4];
4931
4932       bcopy ((char *) d, (char *) &r, sizeof (REAL_VALUE_TYPE));
4933       if (REAL_VALUES_LESS (fvptr[0], r))
4934         {
4935           bcopy ((char *) &fvptr[0], (char *) d,
4936                  sizeof (REAL_VALUE_TYPE));
4937           return 1;
4938         }
4939       else if (REAL_VALUES_LESS (r, fvptr[1]))
4940         {
4941           bcopy ((char *) &fvptr[1], (char *) d,
4942                  sizeof (REAL_VALUE_TYPE));
4943           return 1;
4944         }
4945       else if (REAL_VALUES_LESS (dconst0, r)
4946                 && REAL_VALUES_LESS (r, fvptr[2]))
4947         {
4948           bcopy ((char *) &dconst0, (char *) d, sizeof (REAL_VALUE_TYPE));
4949           return 1;
4950         }
4951       else if (REAL_VALUES_LESS (r, dconst0)
4952                 && REAL_VALUES_LESS (fvptr[3], r))
4953         {
4954           bcopy ((char *) &dconst0, (char *) d, sizeof (REAL_VALUE_TYPE));
4955           return 1;
4956         }
4957     }
4958
4959   return 0;
4960 }
4961
4962 #if OPEN_VMS
4963
4964 /* Return the VMS argument type corresponding to MODE.  */
4965
4966 enum avms_arg_type
4967 alpha_arg_type (mode)
4968      enum machine_mode mode;
4969 {
4970   switch (mode)
4971     {
4972     case SFmode:
4973       return TARGET_FLOAT_VAX ? FF : FS;
4974     case DFmode:
4975       return TARGET_FLOAT_VAX ? FD : FT;
4976     default:
4977       return I64;
4978     }
4979 }
4980
4981 /* Return an rtx for an integer representing the VMS Argument Information
4982    register value.  */
4983
4984 struct rtx_def *
4985 alpha_arg_info_reg_val (cum)
4986      CUMULATIVE_ARGS cum;
4987 {
4988   unsigned HOST_WIDE_INT regval = cum.num_args;
4989   int i;
4990
4991   for (i = 0; i < 6; i++)
4992     regval |= ((int) cum.atypes[i]) << (i * 3 + 8);
4993
4994   return GEN_INT (regval);
4995 }
4996 \f
4997 /* Structure to collect function names for final output
4998    in link section.  */
4999
5000 enum links_kind {KIND_UNUSED, KIND_LOCAL, KIND_EXTERN};
5001
5002
5003 struct alpha_links {
5004   struct alpha_links *next;
5005   char *name;
5006   enum links_kind kind;
5007 };
5008
5009 static struct alpha_links *alpha_links_base = 0;
5010
5011 /* Make (or fake) .linkage entry for function call.
5012
5013    IS_LOCAL is 0 if name is used in call, 1 if name is used in definition.  */
5014
5015 void
5016 alpha_need_linkage (name, is_local)
5017     char *name;
5018     int is_local;
5019 {
5020   rtx x;
5021   struct alpha_links *lptr, *nptr;
5022
5023   if (name[0] == '*')
5024     name++;
5025
5026   /* Is this name already defined ?  */
5027
5028   for (lptr = alpha_links_base; lptr; lptr = lptr->next)
5029     if (strcmp (lptr->name, name) == 0)
5030       {
5031         if (is_local)
5032           {
5033             /* Defined here but external assumed.  */
5034             if (lptr->kind == KIND_EXTERN)
5035               lptr->kind = KIND_LOCAL;
5036           }
5037         else
5038           {
5039             /* Used here but unused assumed.  */
5040             if (lptr->kind == KIND_UNUSED)
5041               lptr->kind = KIND_LOCAL;
5042           }
5043         return;
5044       }
5045
5046   nptr = (struct alpha_links *) xmalloc (sizeof (struct alpha_links));
5047   nptr->next = alpha_links_base;
5048   nptr->name = xstrdup (name);
5049
5050   /* Assume external if no definition.  */
5051   nptr->kind = (is_local ? KIND_UNUSED : KIND_EXTERN);
5052
5053   /* Ensure we have an IDENTIFIER so assemble_name can mark is used.  */
5054   get_identifier (name);
5055
5056   alpha_links_base = nptr;
5057
5058   return;
5059 }
5060
5061
5062 void
5063 alpha_write_linkage (stream)
5064     FILE *stream;
5065 {
5066   struct alpha_links *lptr, *nptr;
5067
5068   readonly_section ();
5069
5070   fprintf (stream, "\t.align 3\n");
5071
5072   for (lptr = alpha_links_base; lptr; lptr = nptr)
5073     {
5074       nptr = lptr->next;
5075
5076       if (lptr->kind == KIND_UNUSED
5077           || ! TREE_SYMBOL_REFERENCED (get_identifier (lptr->name)))
5078         continue;
5079
5080       fprintf (stream, "$%s..lk:\n", lptr->name);
5081       if (lptr->kind == KIND_LOCAL)   
5082         {
5083           /*  Local and used, build linkage pair.  */
5084           fprintf (stream, "\t.quad %s..en\n", lptr->name);
5085           fprintf (stream, "\t.quad %s\n", lptr->name);
5086         }
5087       else
5088         /* External and used, request linkage pair.  */
5089         fprintf (stream, "\t.linkage %s\n", lptr->name);
5090     }
5091 }
5092
5093 #else
5094
5095 void
5096 alpha_need_linkage (name, is_local)
5097      char *name ATTRIBUTE_UNUSED;
5098      int is_local ATTRIBUTE_UNUSED;
5099 {
5100 }
5101
5102 #endif /* OPEN_VMS */