OSDN Git Service

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