OSDN Git Service

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