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