OSDN Git Service

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