]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/alpha/alpha.c
Merge in gcc2-ss-010999
[thirdparty/gcc.git] / gcc / config / alpha / alpha.c
CommitLineData
a6f12d7c 1/* Subroutines used for code generation on the DEC Alpha.
e03ec28f 2 Copyright (C) 1992, 93-98, 1999 Free Software Foundation, Inc.
d60a05a1 3 Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
a6f12d7c
RK
4
5This file is part of GNU CC.
6
7GNU CC is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2, or (at your option)
10any later version.
11
12GNU CC is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GNU CC; see the file COPYING. If not, write to
38ead7f3
RK
19the Free Software Foundation, 59 Temple Place - Suite 330,
20Boston, MA 02111-1307, USA. */
a6f12d7c
RK
21
22
a6f12d7c 23#include "config.h"
3c303f52 24#include "system.h"
a6f12d7c
RK
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"
eb04ab5a 37#include "tree.h"
a6f12d7c
RK
38#include "expr.h"
39#include "obstack.h"
9ecc37f0
RH
40#include "except.h"
41#include "function.h"
3c303f52 42#include "toplev.h"
9ecc37f0
RH
43
44/* External data. */
45extern char *version_string;
46extern int rtx_equal_function_value_matters;
a6f12d7c 47
da792a68 48/* Specify which cpu to schedule for. */
9ecc37f0 49
9b009d45 50enum processor_type alpha_cpu;
df45c7ea 51static const char * const alpha_cpu_name[] =
bcbbac26
RH
52{
53 "ev4", "ev5", "ev6"
54};
da792a68 55
6245e3df
RK
56/* Specify how accurate floating-point traps need to be. */
57
58enum alpha_trap_precision alpha_tp;
59
60/* Specify the floating-point rounding mode. */
61
62enum alpha_fp_rounding_mode alpha_fprm;
63
64/* Specify which things cause traps. */
65
66enum alpha_fp_trap_mode alpha_fptm;
67
68/* Strings decoded into the above options. */
9ecc37f0 69
df45c7ea
KG
70const char *alpha_cpu_string; /* -mcpu= */
71const char *alpha_tp_string; /* -mtrap-precision=[p|s|i] */
72const char *alpha_fprm_string; /* -mfp-rounding-mode=[n|m|c|d] */
73const char *alpha_fptm_string; /* -mfp-trap-mode=[n|u|su|sui] */
74const char *alpha_mlat_string; /* -mmemory-latency= */
6245e3df 75
a6f12d7c
RK
76/* Save information from a "cmpxx" operation until the branch or scc is
77 emitted. */
78
79rtx alpha_compare_op0, alpha_compare_op1;
80int alpha_compare_fp_p;
81
71038426
RH
82/* Define the information needed to modify the epilogue for EH. */
83
84rtx alpha_eh_epilogue_sp_ofs;
85
48f6bfac
RK
86/* Non-zero if inside of a function, because the Alpha asm can't
87 handle .files inside of functions. */
88
89static int inside_function = FALSE;
90
9ecc37f0
RH
91/* If non-null, this rtx holds the return address for the function. */
92
93static rtx alpha_return_addr_rtx;
d60a05a1 94
bcbbac26
RH
95/* The number of cycles of latency we should assume on memory reads. */
96
97int alpha_memory_latency = 3;
98
9c0e94a5
RH
99/* Whether the function needs the GP. */
100
101static int alpha_function_needs_gp;
102
3873d24b
RH
103/* The alias set for prologue/epilogue register save/restore. */
104
105static int alpha_sr_alias_set;
106
d60a05a1 107/* Declarations of static functions. */
9c0e94a5 108static void alpha_set_memflags_1
80db34d8 109 PROTO((rtx, int, int, int));
9c0e94a5
RH
110static rtx alpha_emit_set_const_1
111 PROTO((rtx, enum machine_mode, HOST_WIDE_INT, int));
112static void alpha_expand_unaligned_load_words
113 PROTO((rtx *out_regs, rtx smem, HOST_WIDE_INT words, HOST_WIDE_INT ofs));
114static void alpha_expand_unaligned_store_words
115 PROTO((rtx *out_regs, rtx smem, HOST_WIDE_INT words, HOST_WIDE_INT ofs));
116static void alpha_sa_mask
117 PROTO((unsigned long *imaskP, unsigned long *fmaskP));
118static int alpha_does_function_need_gp
119 PROTO((void));
120
89cfc2c6 121
e9a25f70
JL
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
26250081 128
26250081
RH
129#define REG_PV 27
130#define REG_RA 26
a6f12d7c 131\f
6245e3df
RK
132/* Parse target option strings. */
133
134void
135override_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 {
10d5c73f
RK
143 alpha_tp = ALPHA_TP_INSN;
144 alpha_fptm = ALPHA_FPTM_SU;
6245e3df
RK
145 }
146
147 if (TARGET_IEEE_WITH_INEXACT)
148 {
10d5c73f
RK
149 alpha_tp = ALPHA_TP_INSN;
150 alpha_fptm = ALPHA_FPTM_SUI;
6245e3df
RK
151 }
152
153 if (alpha_tp_string)
10d5c73f
RK
154 {
155 if (! strcmp (alpha_tp_string, "p"))
6245e3df 156 alpha_tp = ALPHA_TP_PROG;
10d5c73f 157 else if (! strcmp (alpha_tp_string, "f"))
6245e3df 158 alpha_tp = ALPHA_TP_FUNC;
10d5c73f 159 else if (! strcmp (alpha_tp_string, "i"))
6245e3df 160 alpha_tp = ALPHA_TP_INSN;
10d5c73f
RK
161 else
162 error ("bad value `%s' for -mtrap-precision switch", alpha_tp_string);
163 }
6245e3df
RK
164
165 if (alpha_fprm_string)
10d5c73f
RK
166 {
167 if (! strcmp (alpha_fprm_string, "n"))
6245e3df 168 alpha_fprm = ALPHA_FPRM_NORM;
10d5c73f 169 else if (! strcmp (alpha_fprm_string, "m"))
6245e3df 170 alpha_fprm = ALPHA_FPRM_MINF;
10d5c73f 171 else if (! strcmp (alpha_fprm_string, "c"))
6245e3df 172 alpha_fprm = ALPHA_FPRM_CHOP;
10d5c73f 173 else if (! strcmp (alpha_fprm_string,"d"))
6245e3df 174 alpha_fprm = ALPHA_FPRM_DYN;
10d5c73f
RK
175 else
176 error ("bad value `%s' for -mfp-rounding-mode switch",
6245e3df 177 alpha_fprm_string);
10d5c73f 178 }
6245e3df
RK
179
180 if (alpha_fptm_string)
10d5c73f
RK
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 }
6245e3df 193
de4abb91
RH
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")
be78cbc9 201 || ! strcmp (alpha_cpu_string, "ev45")
de4abb91
RH
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);
de4abb91
RH
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. */
6245e3df 240
10d5c73f 241 if ((alpha_fptm == ALPHA_FPTM_SU || alpha_fptm == ALPHA_FPTM_SUI)
c04635cc 242 && alpha_tp != ALPHA_TP_INSN && alpha_cpu != PROCESSOR_EV6)
6245e3df 243 {
10d5c73f 244 warning ("fp software completion requires -mtrap-precision=i");
6245e3df
RK
245 alpha_tp = ALPHA_TP_INSN;
246 }
89cfc2c6 247
981a828e
RH
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
89cfc2c6
RK
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 }
bcbbac26
RH
269
270 {
271 char *end;
272 int lat;
273
274 if (!alpha_mlat_string)
275 alpha_mlat_string = "L1";
276
d1e6b55b 277 if (ISDIGIT ((unsigned char)alpha_mlat_string[0])
bcbbac26
RH
278 && (lat = strtol (alpha_mlat_string, &end, 10), *end == '\0'))
279 ;
280 else if ((alpha_mlat_string[0] == 'L' || alpha_mlat_string[0] == 'l')
d1e6b55b 281 && ISDIGIT ((unsigned char)alpha_mlat_string[1])
bcbbac26
RH
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 */
71d9b493 288 { 3, 13, -1 }, /* ev6 -- Ho hum, doesn't exist yet */
bcbbac26
RH
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 }
bb8ebb7f
RH
315
316 /* Default the definition of "small data" to 8 bytes. */
317 if (!g_switch_set)
318 g_switch_value = 8;
3873d24b
RH
319
320 /* Acquire a unique set number for our register saves and restores. */
321 alpha_sr_alias_set = new_alias_set ();
6245e3df
RK
322}
323\f
a6f12d7c
RK
324/* Returns 1 if VALUE is a mask that contains full bytes of zero or ones. */
325
326int
327zap_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
343int
344reg_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
f4014bfd
RK
351/* Return 1 if OP is a constant in the range of 0-63 (for a shift) or
352 any register. */
353
354int
355reg_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
a6f12d7c
RK
365/* Return 1 if OP is an 8-bit constant or any register. */
366
367int
368reg_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
14edc0e4
TG
377/* Return 1 if OP is an 8-bit constant. */
378
379int
380cint8_operand (op, mode)
381 register rtx op;
3c303f52 382 enum machine_mode mode ATTRIBUTE_UNUSED;
14edc0e4 383{
e3208d53 384 return ((GET_CODE (op) == CONST_INT
eb8da868 385 && (unsigned HOST_WIDE_INT) INTVAL (op) < 0x100));
14edc0e4
TG
386}
387
a6f12d7c
RK
388/* Return 1 if the operand is a valid second operand to an add insn. */
389
390int
391add_operand (op, mode)
392 register rtx op;
393 enum machine_mode mode;
394{
395 if (GET_CODE (op) == CONST_INT)
80df65c9 396 /* Constraints I, J, O and P are covered by K. */
e6118f89 397 return (CONST_OK_FOR_LETTER_P (INTVAL (op), 'K')
80df65c9 398 || CONST_OK_FOR_LETTER_P (INTVAL (op), 'L'));
a6f12d7c
RK
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
406int
407sext_add_operand (op, mode)
408 register rtx op;
409 enum machine_mode mode;
410{
411 if (GET_CODE (op) == CONST_INT)
80df65c9
RH
412 return (CONST_OK_FOR_LETTER_P (INTVAL (op), 'I')
413 || CONST_OK_FOR_LETTER_P (INTVAL (op), 'O'));
a6f12d7c 414
c5c76735 415 return reg_not_elim_operand (op, mode);
a6f12d7c
RK
416}
417
418/* Return 1 if OP is the constant 4 or 8. */
419
420int
421const48_operand (op, mode)
422 register rtx op;
3c303f52 423 enum machine_mode mode ATTRIBUTE_UNUSED;
a6f12d7c
RK
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
431int
432and_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
c7def335 448/* Return 1 if OP is a valid first operand to an IOR or XOR insn. */
8088469d
RK
449
450int
c7def335 451or_operand (op, mode)
8088469d
RK
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
a6f12d7c
RK
462/* Return 1 if OP is a constant that is the width, in bits, of an integral
463 mode smaller than DImode. */
464
465int
466mode_width_operand (op, mode)
467 register rtx op;
3c303f52 468 enum machine_mode mode ATTRIBUTE_UNUSED;
a6f12d7c
RK
469{
470 return (GET_CODE (op) == CONST_INT
6c174fc0
RH
471 && (INTVAL (op) == 8 || INTVAL (op) == 16
472 || INTVAL (op) == 32 || INTVAL (op) == 64));
a6f12d7c
RK
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
478int
479mode_mask_operand (op, mode)
480 register rtx op;
3c303f52 481 enum machine_mode mode ATTRIBUTE_UNUSED;
a6f12d7c
RK
482{
483#if HOST_BITS_PER_WIDE_INT == 32
484 if (GET_CODE (op) == CONST_DOUBLE)
6c174fc0
RH
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);
a6f12d7c
RK
491#endif
492
16b02ae0
RK
493 return (GET_CODE (op) == CONST_INT
494 && (INTVAL (op) == 0xff
495 || INTVAL (op) == 0xffff
3873d24b 496 || INTVAL (op) == (HOST_WIDE_INT)0xffffffff
11ea364a 497#if HOST_BITS_PER_WIDE_INT == 64
3873d24b 498 || INTVAL (op) == -1
a6f12d7c 499#endif
16b02ae0 500 ));
a6f12d7c
RK
501}
502
503/* Return 1 if OP is a multiple of 8 less than 64. */
504
505int
506mul8_operand (op, mode)
507 register rtx op;
3c303f52 508 enum machine_mode mode ATTRIBUTE_UNUSED;
a6f12d7c
RK
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
517int
518fp0_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
528int
529reg_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
4ed43ff8
RH
536/* Return 1 if OP is a hard floating-point register. */
537
538int
539hard_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
a6f12d7c
RK
548/* Return 1 if OP is a register or a constant integer. */
549
550
551int
552reg_or_cint_operand (op, mode)
553 register rtx op;
554 enum machine_mode mode;
555{
e3208d53 556 return (GET_CODE (op) == CONST_INT
e3208d53 557 || register_operand (op, mode));
a6f12d7c
RK
558}
559
8d36d33b
RK
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
563int
564some_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 {
e3208d53 573 case REG: case MEM: case CONST_DOUBLE: case CONST_INT: case LABEL_REF:
eb8da868 574 case SYMBOL_REF: case CONST:
8d36d33b
RK
575 return 1;
576
577 case SUBREG:
578 return some_operand (SUBREG_REG (op), VOIDmode);
1d300e19
KG
579
580 default:
581 break;
8d36d33b
RK
582 }
583
584 return 0;
585}
586
a6f12d7c
RK
587/* Return 1 if OP is a valid operand for the source of a move insn. */
588
589int
590input_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:
e3208d53 605 /* This handles both the Windows/NT and OSF cases. */
7daa56f5 606 return mode == ptr_mode || mode == DImode;
a6f12d7c
RK
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:
e9a25f70 616 return ((TARGET_BWX || (mode != HImode && mode != QImode))
a2574dbe 617 && general_operand (op, mode));
a6f12d7c
RK
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);
1d300e19 624
ee5332b8
RH
625 case CONSTANT_P_RTX:
626 return 1;
627
1d300e19
KG
628 default:
629 break;
a6f12d7c
RK
630 }
631
632 return 0;
633}
634
0f33506c
RK
635/* Return 1 if OP is a SYMBOL_REF for a function known to be in this
636 file. */
a6f12d7c
RK
637
638int
0f33506c 639current_file_function_operand (op, mode)
a6f12d7c 640 rtx op;
3c303f52 641 enum machine_mode mode ATTRIBUTE_UNUSED;
a6f12d7c
RK
642{
643 return (GET_CODE (op) == SYMBOL_REF
d14d353d 644 && ! profile_flag && ! profile_block_flag
0f33506c
RK
645 && (SYMBOL_REF_FLAG (op)
646 || op == XEXP (DECL_RTL (current_function_decl), 0)));
a6f12d7c
RK
647}
648
6bcf5f0a
RK
649/* Return 1 if OP is a valid operand for the MEM of a CALL insn. */
650
651int
652call_operand (op, mode)
653 rtx op;
654 enum machine_mode mode;
655{
656 if (mode != Pmode)
657 return 0;
658
7e277025 659 return (GET_CODE (op) == SYMBOL_REF
202f590e
RH
660 || (GET_CODE (op) == REG
661 && (TARGET_OPEN_VMS || TARGET_WINDOWS_NT || REGNO (op) == 27)));
6bcf5f0a
RK
662}
663
a6f12d7c
RK
664/* Return 1 if OP is a valid Alpha comparison operator. Here we know which
665 comparisons are valid in which insn. */
666
667int
668alpha_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
5bf6c48a
RK
681/* Return 1 if OP is a valid Alpha swapped comparison operator. */
682
683int
684alpha_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
a6f12d7c
RK
698/* Return 1 if OP is a signed comparison operation. */
699
700int
701signed_comparison_operator (op, mode)
702 register rtx op;
3c303f52 703 enum machine_mode mode ATTRIBUTE_UNUSED;
a6f12d7c
RK
704{
705 switch (GET_CODE (op))
706 {
707 case EQ: case NE: case LE: case LT: case GE: case GT:
708 return 1;
1d300e19
KG
709
710 default:
711 break;
a6f12d7c
RK
712 }
713
714 return 0;
715}
716
717/* Return 1 if this is a divide or modulus operator. */
718
719int
720divmod_operator (op, mode)
721 register rtx op;
3c303f52 722 enum machine_mode mode ATTRIBUTE_UNUSED;
a6f12d7c
RK
723{
724 switch (GET_CODE (op))
725 {
726 case DIV: case MOD: case UDIV: case UMOD:
727 return 1;
1d300e19
KG
728
729 default:
730 break;
a6f12d7c
RK
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
96043e7e 740 Take into account what reload will do. */
a6f12d7c
RK
741
742int
743aligned_memory_operand (op, mode)
744 register rtx op;
745 enum machine_mode mode;
746{
4e46365b 747 rtx base;
a6f12d7c 748
96043e7e
RH
749 if (reload_in_progress)
750 {
4e46365b
RH
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 }
96043e7e 761 }
a6f12d7c 762
96043e7e 763 if (GET_CODE (op) != MEM
4e46365b 764 || GET_MODE (op) != mode)
a6f12d7c 765 return 0;
a6f12d7c
RK
766 op = XEXP (op, 0);
767
4e46365b
RH
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 }
a6f12d7c 780
4e46365b
RH
781 return (GET_CODE (base) == REG
782 && REGNO_POINTER_ALIGN (REGNO (base)) >= 4);
a6f12d7c
RK
783}
784
785/* Similar, but return 1 if OP is a MEM which is not alignable. */
786
787int
788unaligned_memory_operand (op, mode)
789 register rtx op;
790 enum machine_mode mode;
791{
4e46365b
RH
792 rtx base;
793
794 if (reload_in_progress)
a6f12d7c 795 {
4e46365b
RH
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 }
a6f12d7c
RK
806 }
807
4e46365b
RH
808 if (GET_CODE (op) != MEM
809 || GET_MODE (op) != mode)
a6f12d7c 810 return 0;
a6f12d7c
RK
811 op = XEXP (op, 0);
812
4e46365b
RH
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 }
a6f12d7c 825
4e46365b
RH
826 return (GET_CODE (base) == REG
827 && REGNO_POINTER_ALIGN (REGNO (base)) < 4);
adb18b68
RK
828}
829
830/* Return 1 if OP is either a register or an unaligned memory location. */
831
832int
833reg_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);
a6f12d7c
RK
838}
839
840/* Return 1 if OP is any memory location. During reload a pseudo matches. */
841
842int
843any_memory_operand (op, mode)
844 register rtx op;
3c303f52 845 enum machine_mode mode ATTRIBUTE_UNUSED;
a6f12d7c
RK
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
40b80dad
RH
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
867int
868reg_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}
9c0e94a5 880
67070f5c 881/* Return 1 is OP is a memory location that is not a reference (using
ab87f8c8
JL
882 an AND) to an unaligned location. Take into account what reload
883 will do. */
884
885int
886normal_memory_operand (op, mode)
887 register rtx op;
df45c7ea 888 enum machine_mode mode ATTRIBUTE_UNUSED;
ab87f8c8 889{
4e46365b 890 if (reload_in_progress)
ab87f8c8 891 {
4e46365b
RH
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)];
ab87f8c8 899
4e46365b
RH
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 }
ab87f8c8
JL
905 }
906
907 return GET_CODE (op) == MEM && GET_CODE (XEXP (op, 0)) != AND;
908}
67070f5c
RH
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
914int
915reg_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}
39157bcc
RH
923\f
924/* Return 1 if this function can directly return via $26. */
925
926int
927direct_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}
ab87f8c8 934
a6f12d7c
RK
935/* REF is an alignable memory location. Place an aligned SImode
936 reference into *PALIGNED_MEM and the number of bits to shift into
96043e7e
RH
937 *PBITNUM. SCRATCH is a free register for use in reloading out
938 of range stack slots. */
a6f12d7c
RK
939
940void
4e46365b
RH
941get_aligned_mem (ref, paligned_mem, pbitnum)
942 rtx ref;
a6f12d7c
RK
943 rtx *paligned_mem, *pbitnum;
944{
945 rtx base;
946 HOST_WIDE_INT offset = 0;
947
4e46365b
RH
948 if (GET_CODE (ref) != MEM)
949 abort ();
a6f12d7c 950
4e46365b
RH
951 if (reload_in_progress
952 && ! memory_address_p (GET_MODE (ref), XEXP (ref, 0)))
96043e7e 953 {
4e46365b
RH
954 base = find_replacement (&XEXP (ref, 0));
955
956 if (! memory_address_p (GET_MODE (ref), base))
957 abort ();
96043e7e 958 }
a6f12d7c 959 else
96043e7e 960 {
96043e7e
RH
961 base = XEXP (ref, 0);
962 }
a6f12d7c
RK
963
964 if (GET_CODE (base) == PLUS)
965 offset += INTVAL (XEXP (base, 1)), base = XEXP (base, 0);
966
80db34d8 967 *paligned_mem = gen_rtx_MEM (SImode, plus_constant (base, offset & ~3));
c6df88cb 968 MEM_COPY_ATTRIBUTES (*paligned_mem, ref);
80db34d8
RH
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); */
a6f12d7c
RK
974
975 *pbitnum = GEN_INT ((offset & 3) * 8);
976}
977
adb18b68
RK
978/* Similar, but just get the address. Handle the two reload cases.
979 Add EXTRA_OFFSET to the address we return. */
a6f12d7c
RK
980
981rtx
adb18b68 982get_unaligned_address (ref, extra_offset)
a6f12d7c 983 rtx ref;
adb18b68 984 int extra_offset;
a6f12d7c
RK
985{
986 rtx base;
987 HOST_WIDE_INT offset = 0;
988
4e46365b
RH
989 if (GET_CODE (ref) != MEM)
990 abort ();
a6f12d7c 991
4e46365b
RH
992 if (reload_in_progress
993 && ! memory_address_p (GET_MODE (ref), XEXP (ref, 0)))
96043e7e 994 {
96043e7e 995 base = find_replacement (&XEXP (ref, 0));
4e46365b
RH
996
997 if (! memory_address_p (GET_MODE (ref), base))
998 abort ();
96043e7e 999 }
a6f12d7c 1000 else
96043e7e 1001 {
96043e7e
RH
1002 base = XEXP (ref, 0);
1003 }
a6f12d7c
RK
1004
1005 if (GET_CODE (base) == PLUS)
1006 offset += INTVAL (XEXP (base, 1)), base = XEXP (base, 0);
1007
adb18b68 1008 return plus_constant (base, offset + extra_offset);
a6f12d7c
RK
1009}
1010\f
1011/* Subfunction of the following function. Update the flags of any MEM
1012 found in part of X. */
1013
1014static void
80db34d8 1015alpha_set_memflags_1 (x, in_struct_p, volatile_p, unchanging_p)
a6f12d7c 1016 rtx x;
80db34d8 1017 int in_struct_p, volatile_p, unchanging_p;
a6f12d7c
RK
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,
80db34d8 1027 unchanging_p);
a6f12d7c
RK
1028 break;
1029
1030 case INSN:
1031 alpha_set_memflags_1 (PATTERN (x), in_struct_p, volatile_p,
80db34d8 1032 unchanging_p);
a6f12d7c
RK
1033 break;
1034
1035 case SET:
1036 alpha_set_memflags_1 (SET_DEST (x), in_struct_p, volatile_p,
80db34d8 1037 unchanging_p);
a6f12d7c 1038 alpha_set_memflags_1 (SET_SRC (x), in_struct_p, volatile_p,
80db34d8 1039 unchanging_p);
a6f12d7c
RK
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;
80db34d8
RH
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; */
a6f12d7c 1052 break;
1d300e19
KG
1053
1054 default:
1055 break;
a6f12d7c
RK
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
1065void
1066alpha_set_memflags (insn, ref)
1067 rtx insn;
1068 rtx ref;
1069{
80db34d8 1070 int in_struct_p, volatile_p, unchanging_p;
3873d24b
RH
1071
1072 if (GET_CODE (ref) != MEM)
a6f12d7c
RK
1073 return;
1074
3873d24b
RH
1075 in_struct_p = MEM_IN_STRUCT_P (ref);
1076 volatile_p = MEM_VOLATILE_P (ref);
1077 unchanging_p = RTX_UNCHANGING_P (ref);
3873d24b
RH
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. */
80db34d8 1082 if (! in_struct_p && ! volatile_p && ! unchanging_p)
3873d24b
RH
1083 return;
1084
80db34d8 1085 alpha_set_memflags_1 (insn, in_struct_p, volatile_p, unchanging_p);
a6f12d7c
RK
1086}
1087\f
1088/* Try to output insns to set TARGET equal to the constant C if it can be
fd94addf
RK
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. */
a6f12d7c 1093
fd94addf
RK
1094rtx
1095alpha_emit_set_const (target, mode, c, n)
a6f12d7c 1096 rtx target;
fd94addf 1097 enum machine_mode mode;
a6f12d7c
RK
1098 HOST_WIDE_INT c;
1099 int n;
9102cd1f
RK
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
1114static rtx
1115alpha_emit_set_const_1 (target, mode, c, n)
1116 rtx target;
1117 enum machine_mode mode;
1118 HOST_WIDE_INT c;
1119 int n;
a6f12d7c
RK
1120{
1121 HOST_WIDE_INT new = c;
1122 int i, bits;
fd94addf
RK
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;
a6f12d7c
RK
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
fd94addf 1134 if (mode == SImode)
a6f12d7c
RK
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
858e4e8c 1140 a sign-extended 32-bit constant when compiling on a narrow machine. */
a6f12d7c 1141
858e4e8c
RH
1142 if (HOST_BITS_PER_WIDE_INT != 64
1143 || c >> 31 == -1 || c >> 31 == 0)
a6f12d7c
RK
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);
a6f12d7c
RK
1149 HOST_WIDE_INT extra = 0;
1150
ab034cfc
RK
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)
a6f12d7c
RK
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))
858e4e8c
RH
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);
38a448ca 1171 emit_insn (gen_rtx_SET (VOIDmode, target, GEN_INT (c)));
858e4e8c
RH
1172 return target;
1173 }
9102cd1f 1174 else if (n >= 2 + (extra != 0))
a6f12d7c 1175 {
fd94addf
RK
1176 temp = copy_to_suggested_reg (GEN_INT (low), subtarget, mode);
1177
a6f12d7c 1178 if (extra != 0)
fd94addf
RK
1179 temp = expand_binop (mode, add_optab, temp, GEN_INT (extra << 16),
1180 subtarget, 0, OPTAB_WIDEN);
a6f12d7c 1181
fd94addf
RK
1182 return expand_binop (mode, add_optab, temp, GEN_INT (high << 16),
1183 target, 0, OPTAB_WIDEN);
a6f12d7c
RK
1184 }
1185 }
1186
0af3ee30 1187 /* If we couldn't do it that way, try some other methods. But if we have
f444f304
RK
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. */
a6f12d7c 1191
f444f304
RK
1192 if (n == 1
1193 || (mode == SImode && ! rtx_equal_function_value_matters))
a6f12d7c
RK
1194 return 0;
1195
0af3ee30 1196#if HOST_BITS_PER_WIDE_INT == 64
a6f12d7c
RK
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
57cfde96
RK
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)
fd94addf
RK
1213 return expand_binop (mode, and_optab, temp, GEN_INT (c | ~ new),
1214 target, 0, OPTAB_WIDEN);
0af3ee30 1215#endif
a6f12d7c 1216
0af3ee30 1217 /* Next, see if we can load a related constant and then shift and possibly
a6f12d7c
RK
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. */
fd94addf
RK
1224 if ((temp = alpha_emit_set_const (subtarget, mode, ~ c, i)) != 0)
1225 return expand_unop (mode, one_cmpl_optab, temp, target, 0);
a6f12d7c 1226
fd94addf 1227 /* Next try to form a constant and do a left shift. We can do this
a6f12d7c
RK
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--)
0af3ee30
RK
1238 if ((temp = (alpha_emit_set_const
1239 (subtarget, mode,
4bd75896 1240 (unsigned HOST_WIDE_INT) (c >> bits), i))) != 0
fd94addf
RK
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);
a6f12d7c
RK
1247
1248 /* Now try high-order zero bits. Here we try the shifted-in bits as
57cfde96
RK
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. */
858e4e8c
RH
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. */
a6f12d7c 1253
57cfde96 1254 if ((bits = (MIN (HOST_BITS_PER_WIDE_INT, GET_MODE_SIZE (mode) * 8)
858e4e8c 1255 - floor_log2 (c) - 1 - (HOST_BITS_PER_WIDE_INT < 64))) > 0)
a6f12d7c 1256 for (; bits > 0; bits--)
fd94addf
RK
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),
57cfde96 1265 target, 1, OPTAB_WIDEN);
a6f12d7c
RK
1266
1267 /* Now try high-order 1 bits. We get that with a sign-extension.
57cfde96
RK
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. */
a6f12d7c 1270
57cfde96
RK
1271 if ((bits = (MIN (HOST_BITS_PER_WIDE_INT, GET_MODE_SIZE (mode) * 8)
1272 - floor_log2 (~ c) - 2)) > 0)
a6f12d7c 1273 for (; bits > 0; bits--)
fd94addf
RK
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);
a6f12d7c
RK
1283 }
1284
1285 return 0;
1286}
758d2c0c 1287
97aea203
RK
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
1293rtx
3fe5612d 1294alpha_emit_set_long_const (target, c1, c2)
97aea203 1295 rtx target;
3fe5612d 1296 HOST_WIDE_INT c1, c2;
97aea203 1297{
97aea203 1298 HOST_WIDE_INT d1, d2, d3, d4;
97aea203
RK
1299
1300 /* Decompose the entire word */
3fe5612d
RH
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
97aea203
RK
1326
1327 /* Construct the high word */
3fe5612d
RH
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 }
97aea203 1334 else
3fe5612d 1335 emit_move_insn (target, GEN_INT (d3));
97aea203
RK
1336
1337 /* Shift it into place */
3fe5612d 1338 emit_move_insn (target, gen_rtx_ASHIFT (DImode, target, GEN_INT (32)));
97aea203 1339
3fe5612d
RH
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)));
97aea203 1345
3fe5612d 1346 return target;
97aea203 1347}
97aea203 1348
f283421d
RH
1349/* Generate the comparison for a conditional branch. */
1350
1351rtx
1352alpha_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;
b771b6b4
RH
1406 branch_code = swap_condition (cmp_code);
1407 cmp_code = NIL;
f283421d
RH
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
758d2c0c
RK
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). */
1470rtx
1471alpha_emit_conditional_move (cmp, mode)
1472 rtx cmp;
1473 enum machine_mode mode;
1474{
1ad2a62d 1475 enum rtx_code code = GET_CODE (cmp);
89b7c471 1476 enum rtx_code cmov_code = NE;
758d2c0c
RK
1477 rtx op0 = alpha_compare_op0;
1478 rtx op1 = alpha_compare_op1;
1ad2a62d
RK
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;
f283421d 1482 enum machine_mode cmov_mode = VOIDmode;
1ad2a62d 1483 rtx tem;
758d2c0c 1484
1ad2a62d 1485 if (alpha_compare_fp_p != FLOAT_MODE_P (mode))
758d2c0c
RK
1486 return 0;
1487
1488 /* We may be able to use a conditional move directly.
1489 This avoids emitting spurious compares. */
1ad2a62d 1490 if (signed_comparison_operator (cmp, cmp_op_mode)
f283421d 1491 && (!alpha_compare_fp_p || flag_fast_math)
1ad2a62d 1492 && (op0 == CONST0_RTX (cmp_mode) || op1 == CONST0_RTX (cmp_mode)))
38a448ca 1493 return gen_rtx_fmt_ee (code, VOIDmode, op0, op1);
758d2c0c
RK
1494
1495 /* We can't put the comparison insides a conditional move;
1496 emit a compare instruction and put that inside the
1ad2a62d
RK
1497 conditional move. Make sure we emit only comparisons we have;
1498 swap or reverse as necessary. */
758d2c0c 1499
758d2c0c
RK
1500 switch (code)
1501 {
1ad2a62d
RK
1502 case EQ: case LE: case LT: case LEU: case LTU:
1503 /* We have these compares: */
758d2c0c 1504 break;
1ad2a62d 1505
758d2c0c 1506 case NE:
1ad2a62d
RK
1507 /* This must be reversed. */
1508 code = reverse_condition (code);
89b7c471 1509 cmov_code = EQ;
758d2c0c 1510 break;
1ad2a62d
RK
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);
758d2c0c 1518 break;
1ad2a62d 1519
758d2c0c 1520 default:
1ad2a62d 1521 abort ();
758d2c0c
RK
1522 }
1523
68aed21b 1524 /* ??? We mark the branch mode to be CCmode to prevent the compare
f283421d
RH
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
1ad2a62d 1530 tem = gen_reg_rtx (cmp_op_mode);
38a448ca 1531 emit_move_insn (tem, gen_rtx_fmt_ee (code, cmp_op_mode, op0, op1));
f283421d 1532 return gen_rtx_fmt_ee (cmov_code, cmov_mode, tem, CONST0_RTX (cmp_op_mode));
758d2c0c 1533}
6c174fc0
RH
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
1562void
1563alpha_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;
4208b40f 1569 enum machine_mode mode;
6c174fc0
RH
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,
38a448ca
RH
1579 gen_rtx_AND (DImode,
1580 plus_constant (XEXP (mem, 0),
1581 ofs),
1582 GEN_INT (-8))));
6c174fc0
RH
1583
1584 emit_move_insn (memh,
1585 change_address (mem, DImode,
38a448ca
RH
1586 gen_rtx_AND (DImode,
1587 plus_constant (XEXP (mem, 0),
1588 ofs + size - 1),
1589 GEN_INT (-8))));
6c174fc0
RH
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
1a7cb241
JW
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);
4208b40f
RH
1602 addr = expand_binop (DImode, ashr_optab, addr, GEN_INT (48),
1603 addr, 1, OPTAB_WIDEN);
6c174fc0 1604 }
4208b40f 1605 else
6c174fc0 1606 {
4208b40f
RH
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;
6c174fc0 1615
4208b40f
RH
1616 case 4:
1617 emit_insn (gen_extlh (exth, memh, addr));
1618 mode = SImode;
1619 break;
6c174fc0 1620
4208b40f
RH
1621 case 8:
1622 emit_insn (gen_extqh (exth, memh, addr));
1623 mode = DImode;
1624 break;
df45c7ea
KG
1625 default:
1626 abort();
4208b40f
RH
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);
6c174fc0
RH
1632 }
1633
4208b40f
RH
1634 if (addr != tgt)
1635 emit_move_insn (tgt, gen_lowpart(GET_MODE (tgt), addr));
6c174fc0
RH
1636}
1637
1638/* Similarly, use ins and msk instructions to perform unaligned stores. */
1639
1640void
1641alpha_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,
38a448ca
RH
1653 gen_rtx_AND (DImode,
1654 plus_constant (XEXP (dst, 0), ofs),
1655 GEN_INT (-8)));
6c174fc0 1656 memh = change_address (dst, DImode,
38a448ca
RH
1657 gen_rtx_AND (DImode,
1658 plus_constant (XEXP (dst, 0),
1659 ofs+size-1),
1660 GEN_INT (-8)));
6c174fc0
RH
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 {
4208b40f
RH
1668 emit_insn (gen_insxh (insh, gen_lowpart (DImode, src),
1669 GEN_INT (size*8), addr));
6c174fc0
RH
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 {
4208b40f
RH
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);
6c174fc0
RH
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
4208b40f
RH
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. */
6c174fc0 1723
4208b40f
RH
1724#define MAX_MOVE_WORDS 8
1725
1726/* Load an integral number of consecutive unaligned quadwords. */
6c174fc0
RH
1727
1728static void
4208b40f
RH
1729alpha_expand_unaligned_load_words (out_regs, smem, words, ofs)
1730 rtx *out_regs;
1731 rtx smem;
1732 HOST_WIDE_INT words, ofs;
6c174fc0
RH
1733{
1734 rtx const im8 = GEN_INT (-8);
1735 rtx const i64 = GEN_INT (64);
4208b40f
RH
1736 rtx ext_tmps[MAX_MOVE_WORDS], data_regs[MAX_MOVE_WORDS+1];
1737 rtx sreg, areg;
6c174fc0
RH
1738 HOST_WIDE_INT i;
1739
1740 /* Generate all the tmp registers we need. */
1741 for (i = 0; i < words; ++i)
4208b40f
RH
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));
6c174fc0
RH
1751
1752 /* Load up all of the source data. */
1753 for (i = 0; i < words; ++i)
1754 {
1755 emit_move_insn (data_regs[i],
4208b40f 1756 change_address (smem, DImode,
38a448ca 1757 gen_rtx_AND (DImode,
4208b40f 1758 plus_constant (XEXP(smem,0),
38a448ca
RH
1759 8*i),
1760 im8)));
6c174fc0
RH
1761 }
1762 emit_move_insn (data_regs[words],
4208b40f 1763 change_address (smem, DImode,
38a448ca 1764 gen_rtx_AND (DImode,
4208b40f 1765 plus_constant (XEXP(smem,0),
38a448ca
RH
1766 8*words - 1),
1767 im8)));
6c174fc0
RH
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
4208b40f
RH
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);
6c174fc0
RH
1776 for (i = 0; i < words; ++i)
1777 {
4208b40f 1778 emit_insn (gen_extxl (data_regs[i], data_regs[i], i64, sreg));
6c174fc0 1779
4208b40f 1780 emit_insn (gen_extqh (ext_tmps[i], data_regs[i+1], sreg));
38a448ca
RH
1781 emit_insn (gen_rtx_SET (VOIDmode, ext_tmps[i],
1782 gen_rtx_IF_THEN_ELSE (DImode,
4208b40f
RH
1783 gen_rtx_EQ (DImode, areg,
1784 const0_rtx),
38a448ca 1785 const0_rtx, ext_tmps[i])));
6c174fc0
RH
1786 }
1787
1788 /* Merge the half-words into whole words. */
1789 for (i = 0; i < words; ++i)
1790 {
4208b40f
RH
1791 out_regs[i] = expand_binop (DImode, ior_optab, data_regs[i],
1792 ext_tmps[i], data_regs[i], 1, OPTAB_WIDEN);
6c174fc0
RH
1793 }
1794}
1795
1796/* Store an integral number of consecutive unaligned quadwords. DATA_REGS
1797 may be NULL to store zeros. */
1798
1799static void
4208b40f 1800alpha_expand_unaligned_store_words (data_regs, dmem, words, ofs)
6c174fc0 1801 rtx *data_regs;
4208b40f
RH
1802 rtx dmem;
1803 HOST_WIDE_INT words, ofs;
6c174fc0
RH
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];
4208b40f 1813 rtx st_tmp_1, st_tmp_2, dreg;
6c174fc0
RH
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
4208b40f
RH
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,
38a448ca 1830 gen_rtx_AND (DImode,
4208b40f 1831 plus_constant (XEXP(dmem,0),
38a448ca 1832 words*8 - 1),
6c174fc0 1833 im8));
4208b40f 1834 st_addr_1 = change_address (dmem, DImode,
38a448ca 1835 gen_rtx_AND (DImode,
4208b40f 1836 XEXP (dmem, 0),
38a448ca 1837 im8));
6c174fc0
RH
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. */
4208b40f 1844 dreg = copy_addr_to_reg (XEXP (dmem, 0));
6c174fc0
RH
1845 if (data_regs != NULL)
1846 {
1847 for (i = words-1; i >= 0; --i)
1848 {
4208b40f
RH
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));
6c174fc0 1851 }
6c174fc0
RH
1852 for (i = words-1; i > 0; --i)
1853 {
4208b40f
RH
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);
6c174fc0
RH
1857 }
1858 }
1859
1860 /* Split and merge the ends with the destination data. */
4208b40f
RH
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));
6c174fc0
RH
1863
1864 if (data_regs != NULL)
1865 {
4208b40f
RH
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);
6c174fc0
RH
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 {
4208b40f 1876 emit_move_insn (change_address (dmem, DImode,
38a448ca 1877 gen_rtx_AND (DImode,
4208b40f 1878 plus_constant(XEXP (dmem,0),
38a448ca 1879 i*8),
6c174fc0
RH
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
1894int
1895alpha_expand_block_move (operands)
1896 rtx operands[];
1897{
1898 rtx bytes_rtx = operands[2];
1899 rtx align_rtx = operands[3];
f35cba21
RH
1900 HOST_WIDE_INT orig_bytes = INTVAL (bytes_rtx);
1901 HOST_WIDE_INT bytes = orig_bytes;
4208b40f
RH
1902 HOST_WIDE_INT src_align = INTVAL (align_rtx);
1903 HOST_WIDE_INT dst_align = src_align;
6c174fc0
RH
1904 rtx orig_src = operands[1];
1905 rtx orig_dst = operands[0];
4208b40f
RH
1906 rtx data_regs[2*MAX_MOVE_WORDS+16];
1907 rtx tmp;
1908 int i, words, ofs, nregs = 0;
6c174fc0
RH
1909
1910 if (bytes <= 0)
1911 return 1;
1912 if (bytes > MAX_MOVE_WORDS*8)
1913 return 0;
1914
4208b40f
RH
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
15389075 1969 if (GET_CODE (XEXP (orig_src, 0)) == ADDRESSOF)
4208b40f
RH
1970 {
1971 enum machine_mode mode;
1972 tmp = XEXP (XEXP (orig_src, 0), 0);
15389075 1973
c576fce7
RH
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. */
f35cba21 1977 mode = mode_for_size (bytes * BITS_PER_UNIT, MODE_INT, 1);
4208b40f 1978 if (mode != BLKmode
c576fce7 1979 && GET_MODE_SIZE (GET_MODE (tmp)) >= bytes)
4208b40f 1980 {
c576fce7
RH
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);
4208b40f
RH
1989 goto src_done;
1990 }
6c174fc0 1991
4208b40f
RH
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)
6c174fc0
RH
1999 {
2000 words = bytes / 8;
2001
6c174fc0 2002 for (i = 0; i < words; ++i)
4208b40f 2003 data_regs[nregs+i] = gen_reg_rtx(DImode);
6c174fc0 2004
6c174fc0
RH
2005 for (i = 0; i < words; ++i)
2006 {
4208b40f 2007 emit_move_insn (data_regs[nregs+i],
c576fce7
RH
2008 change_address (orig_src, DImode,
2009 plus_constant (XEXP (orig_src, 0),
2010 ofs + i*8)));
6c174fc0 2011 }
6c174fc0 2012
4208b40f 2013 nregs += words;
6c174fc0 2014 bytes -= words * 8;
cd36edbd 2015 ofs += words * 8;
6c174fc0 2016 }
4208b40f 2017 if (src_align >= 4 && bytes >= 4)
6c174fc0
RH
2018 {
2019 words = bytes / 4;
2020
6c174fc0 2021 for (i = 0; i < words; ++i)
4208b40f 2022 data_regs[nregs+i] = gen_reg_rtx(SImode);
6c174fc0 2023
6c174fc0
RH
2024 for (i = 0; i < words; ++i)
2025 {
4208b40f 2026 emit_move_insn (data_regs[nregs+i],
c576fce7
RH
2027 change_address (orig_src, SImode,
2028 plus_constant (XEXP (orig_src, 0),
2029 ofs + i*4)));
6c174fc0 2030 }
6c174fc0 2031
4208b40f 2032 nregs += words;
6c174fc0 2033 bytes -= words * 4;
cd36edbd 2034 ofs += words * 4;
6c174fc0
RH
2035 }
2036 if (bytes >= 16)
2037 {
2038 words = bytes / 8;
2039
6c174fc0 2040 for (i = 0; i < words+1; ++i)
4208b40f 2041 data_regs[nregs+i] = gen_reg_rtx(DImode);
6c174fc0 2042
c576fce7
RH
2043 alpha_expand_unaligned_load_words (data_regs + nregs, orig_src,
2044 words, ofs);
6c174fc0 2045
4208b40f 2046 nregs += words;
6c174fc0 2047 bytes -= words * 8;
cd36edbd 2048 ofs += words * 8;
6c174fc0 2049 }
6c174fc0
RH
2050 if (!TARGET_BWX && bytes >= 8)
2051 {
4208b40f 2052 data_regs[nregs++] = tmp = gen_reg_rtx (DImode);
6c174fc0 2053 alpha_expand_unaligned_load (tmp, orig_src, 8, ofs, 0);
6c174fc0
RH
2054 bytes -= 8;
2055 ofs += 8;
2056 }
2057 if (!TARGET_BWX && bytes >= 4)
2058 {
4208b40f 2059 data_regs[nregs++] = tmp = gen_reg_rtx (SImode);
6c174fc0 2060 alpha_expand_unaligned_load (tmp, orig_src, 4, ofs, 0);
6c174fc0
RH
2061 bytes -= 4;
2062 ofs += 4;
2063 }
2064 if (bytes >= 2)
2065 {
4208b40f 2066 if (src_align >= 2)
6c174fc0
RH
2067 {
2068 do {
4208b40f
RH
2069 data_regs[nregs++] = tmp = gen_reg_rtx (HImode);
2070 emit_move_insn (tmp,
6c174fc0
RH
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 {
4208b40f 2080 data_regs[nregs++] = tmp = gen_reg_rtx (HImode);
6c174fc0 2081 alpha_expand_unaligned_load (tmp, orig_src, 2, ofs, 0);
6c174fc0
RH
2082 bytes -= 2;
2083 ofs += 2;
2084 }
2085 }
2086 while (bytes > 0)
2087 {
4208b40f
RH
2088 data_regs[nregs++] = tmp = gen_reg_rtx (QImode);
2089 emit_move_insn (tmp,
6c174fc0
RH
2090 change_address (orig_src, QImode,
2091 plus_constant (XEXP (orig_src, 0),
2092 ofs)));
2093 bytes -= 1;
2094 ofs += 1;
2095 }
4208b40f
RH
2096 src_done:
2097
3873d24b 2098 if (nregs > (int)(sizeof(data_regs)/sizeof(*data_regs)))
4208b40f
RH
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
f35cba21 2112 mode = mode_for_size (orig_bytes * BITS_PER_UNIT, MODE_INT, 1);
c576fce7 2113 if (GET_MODE (tmp) == mode)
4208b40f 2114 {
c576fce7
RH
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]);
34cea4e9 2137 seq = get_insns ();
c576fce7
RH
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 }
4208b40f
RH
2147 }
2148
2149 /* ??? If nregs > 1, consider reconstructing the word in regs. */
2150 /* ??? Optimize mode < dst_mode with strict_low_part. */
f35cba21
RH
2151
2152 /* No appropriate mode; fall back on memory. We can speed things
2153 up by recognizing extra alignment information. */
4208b40f
RH
2154 orig_dst = change_address (orig_dst, GET_MODE (orig_dst),
2155 copy_addr_to_reg (XEXP (orig_dst, 0)));
f35cba21 2156 dst_align = GET_MODE_SIZE (GET_MODE (tmp));
4208b40f
RH
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 {
c576fce7
RH
2164 emit_move_insn (change_address (orig_dst, DImode,
2165 plus_constant (XEXP (orig_dst, 0),
2166 ofs)),
4208b40f
RH
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
c576fce7
RH
2181 emit_move_insn (change_address (orig_dst, SImode,
2182 plus_constant (XEXP (orig_dst, 0),
2183 ofs)),
4208b40f 2184 gen_lowpart (SImode, data_regs[i]));
c576fce7
RH
2185 emit_move_insn (change_address (orig_dst, SImode,
2186 plus_constant (XEXP (orig_dst, 0),
2187 ofs+4)),
4208b40f
RH
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();
6c174fc0
RH
2260
2261 return 1;
2262}
2263
2264int
2265alpha_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];
4208b40f 2273 rtx tmp;
6c174fc0
RH
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
4208b40f
RH
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 }
c576fce7
RH
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 }
4208b40f 2322
6c174fc0
RH
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),
cd36edbd 2333 ofs + i*8)),
6c174fc0
RH
2334 const0_rtx);
2335 }
2336
2337 bytes -= words * 8;
cd36edbd 2338 ofs += words * 8;
6c174fc0 2339 }
cd36edbd 2340 if (align >= 4 && bytes >= 4)
6c174fc0
RH
2341 {
2342 words = bytes / 4;
2343
2344 for (i = 0; i < words; ++i)
2345 {
c576fce7
RH
2346 emit_move_insn (change_address (orig_dst, SImode,
2347 plus_constant (XEXP (orig_dst, 0),
2348 ofs + i*4)),
6c174fc0
RH
2349 const0_rtx);
2350 }
2351
2352 bytes -= words * 4;
cd36edbd 2353 ofs += words * 4;
6c174fc0 2354 }
cd36edbd 2355 if (bytes >= 16)
6c174fc0
RH
2356 {
2357 words = bytes / 8;
2358
cd36edbd 2359 alpha_expand_unaligned_store_words (NULL, orig_dst, words, ofs);
6c174fc0
RH
2360
2361 bytes -= words * 8;
cd36edbd 2362 ofs += words * 8;
6c174fc0
RH
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
a6f12d7c
RK
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
2417int
2418alpha_adjust_cost (insn, link, dep_insn, cost)
2419 rtx insn;
2420 rtx link;
2421 rtx dep_insn;
2422 int cost;
2423{
74835ed8 2424 rtx set, set_src;
26250081 2425 enum attr_type insn_type, dep_insn_type;
a6f12d7c
RK
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
26250081
RH
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
bcbbac26 2441 /* Bring in the user-defined memory latency. */
71d9b493
RH
2442 if (dep_insn_type == TYPE_ILD
2443 || dep_insn_type == TYPE_FLD
2444 || dep_insn_type == TYPE_LDSYM)
bcbbac26
RH
2445 cost += alpha_memory_latency-1;
2446
71d9b493 2447 switch (alpha_cpu)
74835ed8 2448 {
71d9b493 2449 case PROCESSOR_EV4:
74835ed8
RH
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
71d9b493 2453 if ((insn_type == TYPE_IST || insn_type == TYPE_FST)
74835ed8
RH
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 {
26250081 2458 switch (dep_insn_type)
74835ed8 2459 {
71d9b493
RH
2460 case TYPE_ILD:
2461 case TYPE_FLD:
74835ed8
RH
2462 /* No savings here. */
2463 return cost;
2464
71d9b493 2465 case TYPE_IMUL:
74835ed8
RH
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
71d9b493 2478 for the address in loads, stores, and jumps. */
74835ed8 2479
26250081 2480 if (dep_insn_type == TYPE_IADD || dep_insn_type == TYPE_ILOG)
74835ed8 2481 {
26250081 2482 switch (insn_type)
74835ed8 2483 {
71d9b493
RH
2484 case TYPE_ILD:
2485 case TYPE_IST:
2486 case TYPE_FLD:
2487 case TYPE_FST:
2488 case TYPE_JSR:
74835ed8
RH
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
26250081 2498 if (dep_insn_type == TYPE_ICMP && insn_type == TYPE_IBR)
da792a68 2499 return 1;
71d9b493
RH
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;
74835ed8 2556 }
a6f12d7c
RK
2557
2558 /* Otherwise, return the default cost. */
a6f12d7c
RK
2559 return cost;
2560}
9ecc37f0
RH
2561\f
2562/* Functions to save and restore alpha_return_addr_rtx. */
2563
2564struct machine_function
2565{
2566 rtx ra_rtx;
2567};
2568
2569static void
2570alpha_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
2580static void
2581alpha_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
2594void
2595alpha_init_expanders ()
2596{
2597 alpha_return_addr_rtx = NULL_RTX;
71038426 2598 alpha_eh_epilogue_sp_ofs = NULL_RTX;
9ecc37f0
RH
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
2607rtx
2608alpha_return_addr (count, frame)
2609 int count;
3c303f52 2610 rtx frame ATTRIBUTE_UNUSED;
9ecc37f0 2611{
2514cbc9 2612 rtx init;
9ecc37f0
RH
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);
3fe5612d 2622 init = gen_rtx_SET (VOIDmode, alpha_return_addr_rtx,
38a448ca 2623 gen_rtx_REG (Pmode, REG_RA));
9ecc37f0
RH
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
2633static int
2634alpha_ra_ever_killed ()
2635{
6abc6f40
RH
2636 rtx top;
2637
acd92049
RH
2638#ifdef ASM_OUTPUT_MI_THUNK
2639 if (current_function_is_thunk)
2640 return 0;
2641#endif
9ecc37f0
RH
2642 if (!alpha_return_addr_rtx)
2643 return regs_ever_live[REG_RA];
2644
6abc6f40
RH
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);
9ecc37f0
RH
2650}
2651
a6f12d7c
RK
2652\f
2653/* Print an operand. Recognize special options, documented below. */
2654
2655void
2656print_operand (file, x, code)
2657 FILE *file;
2658 rtx x;
2659 char code;
2660{
2661 int i;
2662
2663 switch (code)
2664 {
6245e3df
RK
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). */
981a828e 2688 if (alpha_fptm >= ALPHA_FPTM_SU)
6245e3df
RK
2689 fputs ("su", file);
2690 break;
2691
e83015a9
RH
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
0022a940
DMT
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:
556ccd9b 2716 break;
0022a940
DMT
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
6245e3df
RK
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 {
e83015a9
RH
2754 case ALPHA_FPTM_N:
2755 case ALPHA_FPTM_U:
6245e3df
RK
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
89cfc2c6
RK
2764 case ',':
2765 /* Generates single precision instruction suffix. */
e9a25f70 2766 fprintf (file, "%c", (TARGET_FLOAT_VAX ? 'f' : 's'));
89cfc2c6
RK
2767 break;
2768
2769 case '-':
2770 /* Generates double precision instruction suffix. */
e9a25f70 2771 fprintf (file, "%c", (TARGET_FLOAT_VAX ? 'g' : 't'));
89cfc2c6
RK
2772 break;
2773
a6f12d7c
RK
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
0bc8ae6e 2801 fprintf (file, HOST_WIDE_INT_PRINT_DEC, ~ INTVAL (x));
a6f12d7c
RK
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
0bc8ae6e 2809 fprintf (file, HOST_WIDE_INT_PRINT_DEC, (HOST_WIDE_INT) 1 << INTVAL (x));
a6f12d7c
RK
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
0bc8ae6e 2817 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x) >> 16);
a6f12d7c
RK
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
0bc8ae6e
RK
2825 fprintf (file, HOST_WIDE_INT_PRINT_DEC,
2826 (INTVAL (x) & 0xffff) - 2 * (INTVAL (x) & 0x8000));
a6f12d7c
RK
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
0bc8ae6e 2848 fprintf (file, HOST_WIDE_INT_PRINT_DEC, mask & 0xff);
a6f12d7c
RK
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
0bc8ae6e 2859 fprintf (file, HOST_WIDE_INT_PRINT_DEC, mask);
a6f12d7c
RK
2860 }
2861 else
2862 output_operand_lossage ("invalid %%m value");
2863 break;
2864
2865 case 'M':
6c174fc0 2866 /* 'b', 'w', 'l', or 'q' as the value of the constant. */
a6f12d7c 2867 if (GET_CODE (x) != CONST_INT
6c174fc0
RH
2868 || (INTVAL (x) != 8 && INTVAL (x) != 16
2869 && INTVAL (x) != 32 && INTVAL (x) != 64))
a6f12d7c
RK
2870 output_operand_lossage ("invalid %%M value");
2871
2872 fprintf (file, "%s",
6c174fc0
RH
2873 (INTVAL (x) == 8 ? "b"
2874 : INTVAL (x) == 16 ? "w"
2875 : INTVAL (x) == 32 ? "l"
2876 : "q"));
a6f12d7c
RK
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");
11ea364a
JW
2885 else if (GET_CODE (x) == CONST_INT && INTVAL (x) == 0xffffffff)
2886 fprintf (file, "l");
a6f12d7c
RK
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");
6c174fc0
RH
2892 else if (GET_CODE (x) == CONST_DOUBLE
2893 && CONST_DOUBLE_HIGH (x) == -1
2894 && CONST_DOUBLE_LOW (x) == -1)
2895 fprintf (file, "q");
a6f12d7c 2896#else
3873d24b 2897 else if (GET_CODE (x) == CONST_INT && INTVAL (x) == -1)
6c174fc0
RH
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");
a6f12d7c
RK
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
0bc8ae6e 2915 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x) / 8);
a6f12d7c
RK
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
0bc8ae6e 2926 fprintf (file, HOST_WIDE_INT_PRINT_DEC, (64 - INTVAL (x)) / 8);
a6f12d7c
RK
2927 break;
2928
bdd4c95a 2929 case 'C': case 'D': case 'c': case 'd':
a6f12d7c 2930 /* Write out comparison name. */
bdd4c95a
RK
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 }
ab561e66
RK
2951 break;
2952
a6f12d7c
RK
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
a6f12d7c
RK
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}
714b019c
RH
2994
2995void
2996print_operand_address (file, addr)
2997 FILE *file;
2998 rtx addr;
2999{
e03ec28f 3000 int basereg = 31;
714b019c
RH
3001 HOST_WIDE_INT offset = 0;
3002
3003 if (GET_CODE (addr) == AND)
3004 addr = XEXP (addr, 0);
714b019c 3005
e03ec28f
RH
3006 if (GET_CODE (addr) == PLUS
3007 && GET_CODE (XEXP (addr, 1)) == CONST_INT)
714b019c
RH
3008 {
3009 offset = INTVAL (XEXP (addr, 1));
e03ec28f 3010 addr = XEXP (addr, 0);
714b019c 3011 }
e03ec28f
RH
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);
714b019c
RH
3019 else
3020 abort ();
3021
3022 fprintf (file, HOST_WIDE_INT_PRINT_DEC, offset);
e03ec28f 3023 fprintf (file, "($%d)", basereg);
714b019c 3024}
a6f12d7c 3025\f
9ec36da5
JL
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.
c714f03d
RH
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
9ec36da5
JL
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
3039void
c714f03d
RH
3040alpha_initialize_trampoline (tramp, fnaddr, cxt, fnofs, cxtofs, jmpofs)
3041 rtx tramp, fnaddr, cxt;
3042 int fnofs, cxtofs, jmpofs;
9ec36da5
JL
3043{
3044 rtx temp, temp1, addr;
d2692ef8 3045 /* VMS really uses DImode pointers in memory at this point. */
d420e567 3046 enum machine_mode mode = TARGET_OPEN_VMS ? Pmode : ptr_mode;
9ec36da5 3047
d2692ef8
DT
3048#ifdef POINTERS_EXTEND_UNSIGNED
3049 fnaddr = convert_memory_address (mode, fnaddr);
3050 cxt = convert_memory_address (mode, cxt);
3051#endif
3052
9ec36da5 3053 /* Store function address and CXT. */
d420e567 3054 addr = memory_address (mode, plus_constant (tramp, fnofs));
c5c76735 3055 emit_move_insn (gen_rtx_MEM (mode, addr), fnaddr);
d420e567 3056 addr = memory_address (mode, plus_constant (tramp, cxtofs));
c5c76735 3057 emit_move_insn (gen_rtx_MEM (mode, addr), cxt);
c714f03d
RH
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));
c5c76735 3073 temp1 = force_reg (SImode, gen_rtx_MEM (SImode, addr));
c714f03d
RH
3074 temp1 = expand_and (temp1, GEN_INT (0xffffc000), NULL_RTX);
3075 temp1 = expand_binop (SImode, ior_optab, temp1, temp, temp1, 1,
3076 OPTAB_WIDEN);
c5c76735 3077 emit_move_insn (gen_rtx_MEM (SImode, addr), temp1);
c714f03d 3078 }
9ec36da5
JL
3079
3080#ifdef TRANSFER_FROM_TRAMPOLINE
c5c76735 3081 emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__enable_execute_stack"),
9ec36da5
JL
3082 0, VOIDmode, 1, addr, Pmode);
3083#endif
3084
c714f03d
RH
3085 if (jmpofs >= 0)
3086 emit_insn (gen_imb ());
9ec36da5
JL
3087}
3088\f
63966b3b
RH
3089tree
3090alpha_build_va_list ()
a6f12d7c 3091{
63966b3b 3092 tree base, ofs, record;
a6f12d7c 3093
63966b3b
RH
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); */
a6f12d7c 3099
63966b3b
RH
3100 ofs = build_decl (FIELD_DECL, get_identifier ("__offset"),
3101 integer_type_node);
3102 DECL_FIELD_CONTEXT (ofs) = record;
29587b1c 3103
63966b3b
RH
3104 base = build_decl (FIELD_DECL, get_identifier ("__base"),
3105 ptr_type_node);
3106 DECL_FIELD_CONTEXT (base) = record;
3107 TREE_CHAIN (base) = ofs;
29587b1c 3108
63966b3b
RH
3109 TYPE_FIELDS (record) = base;
3110 layout_type (record);
3111
3112 return record;
3113}
3114
3115void
3116alpha_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;
29587b1c 3123
89cfc2c6 3124 if (TARGET_OPEN_VMS)
63966b3b
RH
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;
89cfc2c6 3138 else
63966b3b
RH
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
3161rtx
3162alpha_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
89cfc2c6 3171 if (TARGET_OPEN_VMS)
63966b3b 3172 return std_expand_builtin_va_arg (valist, type);
a6f12d7c 3173
63966b3b 3174 tsize = ((TREE_INT_CST_LOW (TYPE_SIZE (type)) / BITS_PER_UNIT + 7) / 8) * 8;
1d783d31 3175
63966b3b
RH
3176 base_field = TYPE_FIELDS (TREE_TYPE (valist));
3177 offset_field = TREE_CHAIN (base_field);
1d783d31 3178
63966b3b
RH
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))
89cfc2c6 3189 {
63966b3b 3190 tree fpaddend, cond;
89cfc2c6 3191
63966b3b
RH
3192 fpaddend = fold (build (PLUS_EXPR, TREE_TYPE (addend),
3193 addend, build_int_2 (-6*8, 0)));
89cfc2c6 3194
63966b3b
RH
3195 cond = fold (build (LT_EXPR, integer_type_node,
3196 wide_ofs, build_int_2 (6*8, 0)));
89cfc2c6 3197
63966b3b
RH
3198 addend = fold (build (COND_EXPR, TREE_TYPE (addend), cond,
3199 fpaddend, addend));
89cfc2c6 3200 }
63966b3b
RH
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;
a6f12d7c
RK
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
89cfc2c6
RK
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. */
9c0e94a5 3228static int vms_is_stack_procedure;
89cfc2c6
RK
3229
3230/* Register number (either FP or SP) that is used to unwind the frame. */
9c0e94a5 3231static int vms_unwind_regno;
89cfc2c6
RK
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. */
9c0e94a5 3236static int vms_save_fp_regno;
89cfc2c6
RK
3237
3238/* Register number used to reference objects off our PV. */
9c0e94a5 3239static int vms_base_regno;
89cfc2c6 3240
acd92049 3241/* Compute register masks for saved registers. */
89cfc2c6
RK
3242
3243static void
3244alpha_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
acd92049
RH
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);
89cfc2c6 3258
acd92049
RH
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 }
89cfc2c6 3269
acd92049
RH
3270 if (imask || fmask || alpha_ra_ever_killed ())
3271 imask |= (1L << REG_RA);
3272 }
9c0e94a5 3273
89cfc2c6
RK
3274 *imaskP = imask;
3275 *fmaskP = fmask;
89cfc2c6
RK
3276}
3277
3278int
3279alpha_sa_size ()
3280{
3281 int sa_size = 0;
89cfc2c6
RK
3282 int i;
3283
acd92049
RH
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 }
89cfc2c6 3296
9c0e94a5
RH
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 }
89cfc2c6
RK
3345
3346 return sa_size * 8;
3347}
3348
3349int
3350alpha_pv_save_size ()
3351{
3352 alpha_sa_size ();
9c0e94a5 3353 return vms_is_stack_procedure ? 8 : 0;
89cfc2c6
RK
3354}
3355
3356int
3357alpha_using_fp ()
3358{
3359 alpha_sa_size ();
9c0e94a5 3360 return vms_unwind_regno == HARD_FRAME_POINTER_REGNUM;
89cfc2c6
RK
3361}
3362
a6f12d7c 3363int
9c0e94a5 3364vms_valid_decl_attribute_p (decl, attributes, identifier, args)
3c303f52
KG
3365 tree decl ATTRIBUTE_UNUSED;
3366 tree attributes ATTRIBUTE_UNUSED;
9c0e94a5
RH
3367 tree identifier;
3368 tree args;
a6f12d7c 3369{
9c0e94a5
RH
3370 if (is_attribute_p ("overlaid", identifier))
3371 return (args == NULL_TREE);
3372 return 0;
3373}
a6f12d7c 3374
9c0e94a5
RH
3375static int
3376alpha_does_function_need_gp ()
3377{
3378 rtx insn;
a6f12d7c 3379
9c0e94a5
RH
3380 /* We never need a GP for Windows/NT or VMS. */
3381 if (TARGET_WINDOWS_NT || TARGET_OPEN_VMS)
3382 return 0;
a6f12d7c 3383
9c0e94a5
RH
3384#ifdef TARGET_PROFILING_NEEDS_GP
3385 if (profile_flag)
3386 return 1;
3387#endif
d60a05a1 3388
acd92049
RH
3389#ifdef ASM_OUTPUT_MI_THUNK
3390 if (current_function_is_thunk)
3391 return 1;
3392#endif
3393
9c0e94a5
RH
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. */
a6f12d7c 3397
9c0e94a5
RH
3398 push_topmost_sequence ();
3399 insn = get_insns ();
3400 pop_topmost_sequence ();
89cfc2c6 3401
9c0e94a5
RH
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 }
a6f12d7c 3411
9c0e94a5 3412 return 0;
a6f12d7c
RK
3413}
3414
0f33506c
RK
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
9d654bba 3418#ifdef HAVE_STAMP_H
0f33506c
RK
3419#include <stamp.h>
3420#endif
3421
3422void
3423alpha_write_verstamp (file)
4c020733 3424 FILE *file ATTRIBUTE_UNUSED;
0f33506c
RK
3425{
3426#ifdef MS_STAMP
aec4ca5e 3427 fprintf (file, "\t.verstamp %d %d\n", MS_STAMP, LS_STAMP);
0f33506c
RK
3428#endif
3429}
ec6840c1 3430\f
6abc6f40
RH
3431/* Helper function to set RTX_FRAME_RELATED_P on instructions, including
3432 sequences. */
3433
3434static rtx
3435set_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
a6f12d7c
RK
3457/* Write function prologue. */
3458
89cfc2c6
RK
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
9c0e94a5
RH
3471 On not-vms, we don't really differentiate between the two, as we can
3472 simply allocate stack without saving registers. */
89cfc2c6
RK
3473
3474void
9c0e94a5 3475alpha_expand_prologue ()
89cfc2c6 3476{
9c0e94a5 3477 /* Registers to save. */
89cfc2c6
RK
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. */
9c0e94a5 3485 HOST_WIDE_INT reg_offset;
3873d24b 3486 rtx sa_reg, mem;
89cfc2c6
RK
3487 int i;
3488
3489 sa_size = alpha_sa_size ();
89cfc2c6 3490
9c0e94a5
RH
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));
89cfc2c6 3502
9c0e94a5
RH
3503 if (TARGET_OPEN_VMS)
3504 reg_offset = 8;
3505 else
3506 reg_offset = ALPHA_ROUND (current_function_outgoing_args_size);
89cfc2c6 3507
9c0e94a5 3508 alpha_sa_mask (&imask, &fmask);
89cfc2c6
RK
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
9c0e94a5 3519 if (frame_size <= 32768)
89cfc2c6
RK
3520 {
3521 if (frame_size > 4096)
3522 {
3523 int probed = 4096;
3524
9c0e94a5
RH
3525 do
3526 emit_insn (gen_probe_stack (GEN_INT (-probed)));
3527 while ((probed += 8192) < frame_size);
89cfc2c6
RK
3528
3529 /* We only have to do this probe if we aren't saving registers. */
3530 if (sa_size == 0 && probed + 4096 < frame_size)
9c0e94a5 3531 emit_insn (gen_probe_stack (GEN_INT (-frame_size)));
89cfc2c6
RK
3532 }
3533
3534 if (frame_size != 0)
9c0e94a5 3535 {
f9d7e5cd
RH
3536 FRP (emit_insn (gen_adddi3 (stack_pointer_rtx, stack_pointer_rtx,
3537 GEN_INT (-frame_size))));
9c0e94a5 3538 }
89cfc2c6
RK
3539 }
3540 else
3541 {
9c0e94a5 3542 /* Here we generate code to set R22 to SP + 4096 and set R23 to the
89cfc2c6
RK
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;
9c0e94a5
RH
3550 rtx ptr = gen_rtx_REG (DImode, 22);
3551 rtx count = gen_rtx_REG (DImode, 23);
37679e06 3552 rtx seq;
89cfc2c6 3553
9c0e94a5 3554 emit_move_insn (count, GEN_INT (blocks));
f9d7e5cd 3555 emit_insn (gen_adddi3 (ptr, stack_pointer_rtx, GEN_INT (4096)));
89cfc2c6 3556
9c0e94a5
RH
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));
89cfc2c6
RK
3560
3561 if (leftover > 4096 && sa_size == 0)
9c0e94a5
RH
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 }
89cfc2c6 3567
f9d7e5cd
RH
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
37679e06
RH
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. */
f9d7e5cd
RH
3578
3579 HOST_WIDE_INT lo, hi;
14eecd34
RH
3580 lo = ((frame_size & 0xffff) ^ 0x8000) - 0x8000;
3581 hi = frame_size - lo;
6abc6f40 3582
37679e06
RH
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));
f9d7e5cd
RH
3587 }
3588 else
3589 {
f9d7e5cd
RH
3590 seq = emit_insn (gen_adddi3 (stack_pointer_rtx, ptr,
3591 GEN_INT (-leftover)));
f9d7e5cd 3592 }
37679e06
RH
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));
89cfc2c6
RK
3604 }
3605
9c0e94a5
RH
3606 /* Cope with very large offsets to the register save area. */
3607 sa_reg = stack_pointer_rtx;
3608 if (reg_offset + sa_size > 0x8000)
89cfc2c6 3609 {
9c0e94a5
RH
3610 int low = ((reg_offset & 0xffff) ^ 0x8000) - 0x8000;
3611 HOST_WIDE_INT bias;
89cfc2c6 3612
9c0e94a5
RH
3613 if (low + sa_size <= 0x8000)
3614 bias = reg_offset - low, reg_offset = low;
3615 else
3616 bias = reg_offset, reg_offset = 0;
89cfc2c6 3617
9c0e94a5 3618 sa_reg = gen_rtx_REG (DImode, 24);
f9d7e5cd 3619 FRP (emit_insn (gen_adddi3 (sa_reg, stack_pointer_rtx, GEN_INT (bias))));
89cfc2c6 3620 }
9c0e94a5
RH
3621
3622 /* Save regs in stack order. Beginning with VMS PV. */
3623 if (TARGET_OPEN_VMS && vms_is_stack_procedure)
89cfc2c6 3624 {
3873d24b
RH
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)));
89cfc2c6
RK
3628 }
3629
9c0e94a5
RH
3630 /* Save register RA next. */
3631 if (imask & (1L << REG_RA))
3632 {
3873d24b
RH
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)));
9c0e94a5
RH
3636 imask &= ~(1L << REG_RA);
3637 reg_offset += 8;
3638 }
89cfc2c6 3639
9c0e94a5
RH
3640 /* Now save any other registers required to be saved. */
3641 for (i = 0; i < 32; i++)
3642 if (imask & (1L << i))
3643 {
3873d24b
RH
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)));
9c0e94a5
RH
3647 reg_offset += 8;
3648 }
89cfc2c6 3649
9c0e94a5
RH
3650 for (i = 0; i < 32; i++)
3651 if (fmask & (1L << i))
3652 {
3873d24b
RH
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)));
9c0e94a5
RH
3656 reg_offset += 8;
3657 }
89cfc2c6 3658
9c0e94a5 3659 if (TARGET_OPEN_VMS)
89cfc2c6 3660 {
9c0e94a5 3661 if (!vms_is_stack_procedure)
89cfc2c6 3662 {
9c0e94a5 3663 /* Register frame procedures fave the fp. */
6abc6f40
RH
3664 FRP (emit_move_insn (gen_rtx_REG (DImode, vms_save_fp_regno),
3665 hard_frame_pointer_rtx));
9c0e94a5 3666 }
89cfc2c6 3667
9c0e94a5 3668 if (vms_base_regno != REG_PV)
6abc6f40
RH
3669 FRP (emit_move_insn (gen_rtx_REG (DImode, vms_base_regno),
3670 gen_rtx_REG (DImode, REG_PV)));
89cfc2c6 3671
9c0e94a5
RH
3672 if (vms_unwind_regno == HARD_FRAME_POINTER_REGNUM)
3673 {
6abc6f40 3674 FRP (emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx));
89cfc2c6 3675 }
89cfc2c6 3676
9c0e94a5
RH
3677 /* If we have to allocate space for outgoing args, do it now. */
3678 if (current_function_outgoing_args_size != 0)
89cfc2c6 3679 {
6abc6f40
RH
3680 FRP (emit_move_insn (stack_pointer_rtx,
3681 plus_constant (hard_frame_pointer_rtx,
3682 - ALPHA_ROUND (current_function_outgoing_args_size))));
9c0e94a5
RH
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)
6abc6f40 3691 FRP (emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx));
89cfc2c6
RK
3692 else
3693 {
9c0e94a5
RH
3694 /* This must always be the last instruction in the
3695 prologue, thus we emit a special move + clobber. */
6abc6f40
RH
3696 FRP (emit_insn (gen_init_fp (hard_frame_pointer_rtx,
3697 stack_pointer_rtx, sa_reg)));
89cfc2c6
RK
3698 }
3699 }
89cfc2c6
RK
3700 }
3701
9c0e94a5
RH
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.
89cfc2c6 3707
9c0e94a5
RH
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. */
89cfc2c6 3711
9c0e94a5
RH
3712 if (! TARGET_CAN_FAULT_IN_PROLOGUE)
3713 emit_insn (gen_blockage ());
ef86d2ee
WL
3714}
3715
acd92049 3716/* Output the textual info surrounding the prologue. */
89cfc2c6 3717
9c0e94a5 3718void
acd92049 3719alpha_start_function (file, fnname, decl)
9c0e94a5 3720 FILE *file;
acd92049 3721 char *fnname;
3c303f52 3722 tree decl ATTRIBUTE_UNUSED;
9ecc37f0 3723{
9c0e94a5
RH
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;
acd92049 3732 char *entry_label = (char *) alloca (strlen (fnname) + 6);
9c0e94a5 3733 int i;
9ecc37f0 3734
9c0e94a5 3735 sa_size = alpha_sa_size ();
9ecc37f0 3736
9c0e94a5
RH
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));
9ecc37f0 3748
9c0e94a5
RH
3749 if (TARGET_OPEN_VMS)
3750 reg_offset = 8;
3751 else
3752 reg_offset = ALPHA_ROUND (current_function_outgoing_args_size);
9ecc37f0 3753
9c0e94a5 3754 alpha_sa_mask (&imask, &fmask);
a6f12d7c 3755
d60a05a1 3756 /* Ecoff can handle multiple .file directives, so put out file and lineno.
48f6bfac
RK
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
ddd5a7c1 3762 like to put out last_linenum from final.c, but it is not accessible. */
48f6bfac
RK
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)
d60a05a1
RK
3769 ASM_OUTPUT_SOURCE_LINE (file,
3770 DECL_SOURCE_LINE (current_function_decl));
48f6bfac
RK
3771 }
3772
9c0e94a5
RH
3773 /* Issue function start and label. */
3774 if (TARGET_OPEN_VMS || !flag_inhibit_size_directive)
33d01c33 3775 {
9c0e94a5 3776 fputs ("\t.ent ", file);
acd92049 3777 assemble_name (file, fnname);
9c0e94a5 3778 putc ('\n', file);
33d01c33 3779 }
48f6bfac 3780
acd92049 3781 strcpy (entry_label, fnname);
9c0e94a5
RH
3782 if (TARGET_OPEN_VMS)
3783 strcat (entry_label, "..en");
3784 ASM_OUTPUT_LABEL (file, entry_label);
3785 inside_function = TRUE;
48f6bfac 3786
9c0e94a5
RH
3787 if (TARGET_OPEN_VMS)
3788 fprintf (file, "\t.base $%d\n", vms_base_regno);
a6f12d7c 3789
9c0e94a5
RH
3790 if (!TARGET_OPEN_VMS && TARGET_IEEE_CONFORMANT
3791 && !flag_inhibit_size_directive)
9973f4a2 3792 {
9c0e94a5
RH
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);
9973f4a2 3797 }
a6f12d7c 3798
9c0e94a5
RH
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;
c97e3db7 3802
9c0e94a5
RH
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)
a6f12d7c 3807 {
9c0e94a5
RH
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);
3c303f52
KG
3811 fputs (",$26,", file);
3812 fprintf (file, HOST_WIDE_INT_PRINT_DEC, reg_offset);
3813 fputs ("\n", file);
a6f12d7c 3814 }
9c0e94a5 3815 else if (!flag_inhibit_size_directive)
33d01c33 3816 {
5665caa2 3817 fprintf (file, "\t.frame $%d,",
33d01c33 3818 (frame_pointer_needed
9c0e94a5 3819 ? HARD_FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM));
5665caa2 3820 fprintf (file, HOST_WIDE_INT_PRINT_DEC,
9c0e94a5 3821 frame_size >= (1l << 31) ? 0 : frame_size);
5665caa2 3822 fprintf (file, ",$26,%d\n", current_function_pretend_args_size);
33d01c33 3823 }
0d24ff5d 3824
9c0e94a5
RH
3825 /* Describe which registers were spilled. */
3826 if (TARGET_OPEN_VMS)
0d24ff5d 3827 {
9c0e94a5
RH
3828 if (imask)
3829 /* ??? Does VMS care if mask contains ra? The old code did'nt
3830 set it, so I don't here. */
3c303f52 3831 fprintf (file, "\t.mask 0x%lx,0\n", imask & ~(1L << REG_RA));
9c0e94a5 3832 if (fmask)
3c303f52 3833 fprintf (file, "\t.fmask 0x%lx,0\n", fmask);
9c0e94a5
RH
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)
0d24ff5d 3840 {
3c303f52 3841 fprintf (file, "\t.mask 0x%lx,", imask);
9c0e94a5
RH
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;
0d24ff5d 3849 }
9c0e94a5
RH
3850
3851 if (fmask)
0d24ff5d 3852 {
3c303f52 3853 fprintf (file, "\t.fmask 0x%lx,", fmask);
9c0e94a5
RH
3854 fprintf (file, HOST_WIDE_INT_PRINT_DEC,
3855 frame_size >= (1l << 31) ? 0 : reg_offset - frame_size);
3856 putc ('\n', file);
0d24ff5d 3857 }
a6f12d7c
RK
3858 }
3859
9c0e94a5
RH
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)
5665caa2 3864 {
9c0e94a5
RH
3865 alpha_function_needs_gp = alpha_does_function_need_gp ();
3866 if (alpha_function_needs_gp)
3867 fputs ("\tldgp $29,0($27)\n", file);
a6f12d7c 3868
9c0e94a5 3869 putc ('$', file);
acd92049 3870 assemble_name (file, fnname);
9c0e94a5
RH
3871 fputs ("..ng:\n", file);
3872 }
a6f12d7c 3873
9c0e94a5
RH
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");
acd92049 3879 assemble_name (file, fnname); fputs ("..na:\n", file);
9c0e94a5 3880 fputs ("\t.ascii \"", file);
acd92049 3881 assemble_name (file, fnname);
9c0e94a5
RH
3882 fputs ("\\0\"\n", file);
3883
3884 link_section ();
3885 fprintf (file, "\t.align 3\n");
3886 fputs ("\t.name ", file);
acd92049 3887 assemble_name (file, fnname);
9c0e94a5 3888 fputs ("..na\n", file);
acd92049 3889 ASM_OUTPUT_LABEL (file, fnname);
9c0e94a5 3890 fprintf (file, "\t.pdesc ");
acd92049 3891 assemble_name (file, fnname);
9c0e94a5 3892 fprintf (file, "..en,%s\n", vms_is_stack_procedure ? "stack" : "reg");
acd92049 3893 alpha_need_linkage (fnname, 1);
9c0e94a5
RH
3894 text_section ();
3895#endif
3896}
a6f12d7c 3897
9c0e94a5 3898/* Emit the .prologue note at the scheduled end of the prologue. */
0f33506c 3899
9c0e94a5
RH
3900void
3901output_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)
33d01c33 3909 fprintf (file, "\t.prologue %d\n", alpha_function_needs_gp);
a6f12d7c
RK
3910}
3911
3912/* Write function epilogue. */
3913
6abc6f40
RH
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
a6f12d7c 3920void
9c0e94a5 3921alpha_expand_epilogue ()
a6f12d7c 3922{
9c0e94a5
RH
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;
3873d24b 3934 rtx sp_adj1, sp_adj2, mem;
a6f12d7c
RK
3935 int i;
3936
9c0e94a5 3937 sa_size = alpha_sa_size ();
a6f12d7c 3938
9c0e94a5
RH
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));
a6f12d7c 3950
9c0e94a5
RH
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))
0d24ff5d 3967 {
6abc6f40 3968 FRP (emit_move_insn (stack_pointer_rtx, hard_frame_pointer_rtx));
0d24ff5d
RH
3969 }
3970
9c0e94a5
RH
3971 /* Cope with very large offsets to the register save area. */
3972 sa_reg = stack_pointer_rtx;
3973 if (reg_offset + sa_size > 0x8000)
a6f12d7c 3974 {
9c0e94a5
RH
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
6abc6f40 3986 FRP (emit_move_insn (sa_reg, sa_reg_exp));
a6f12d7c 3987 }
9c0e94a5
RH
3988
3989 /* Restore registers in order, excepting a true frame pointer. */
a6f12d7c 3990
71038426
RH
3991 if (! alpha_eh_epilogue_sp_ofs)
3992 {
3873d24b
RH
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));
71038426 3996 }
9c0e94a5
RH
3997 reg_offset += 8;
3998 imask &= ~(1L << REG_RA);
0f33506c 3999
9c0e94a5
RH
4000 for (i = 0; i < 32; ++i)
4001 if (imask & (1L << i))
a6f12d7c 4002 {
9c0e94a5 4003 if (i == HARD_FRAME_POINTER_REGNUM && fp_is_frame_pointer)
0f33506c
RK
4004 fp_offset = reg_offset;
4005 else
9c0e94a5 4006 {
3873d24b
RH
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));
9c0e94a5 4010 }
a6f12d7c
RK
4011 reg_offset += 8;
4012 }
4013
9c0e94a5
RH
4014 for (i = 0; i < 32; ++i)
4015 if (fmask & (1L << i))
a6f12d7c 4016 {
3873d24b
RH
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));
a6f12d7c
RK
4020 reg_offset += 8;
4021 }
9c0e94a5 4022 }
a6f12d7c 4023
71038426 4024 if (frame_size || alpha_eh_epilogue_sp_ofs)
9c0e94a5 4025 {
71038426
RH
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
9c0e94a5
RH
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)
71038426 4040 sp_adj2 = GEN_INT (frame_size);
9c0e94a5
RH
4041 else if (frame_size < 0x40007fffL)
4042 {
4043 int low = ((frame_size & 0xffff) ^ 0x8000) - 0x8000;
4044
71038426 4045 sp_adj2 = plus_constant (sp_adj1, frame_size - low);
9c0e94a5
RH
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);
6abc6f40 4051 FRP (emit_move_insn (sp_adj1, sp_adj2));
9c0e94a5
RH
4052 }
4053 sp_adj2 = GEN_INT (low);
4054 }
d60a05a1 4055 else
9c0e94a5 4056 {
71038426
RH
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)
9c0e94a5
RH
4060 {
4061 /* We can't drop new things to memory this late, afaik,
4062 so build it up by pieces. */
3fe5612d
RH
4063 FRP (sp_adj2 = alpha_emit_set_long_const (tmp, frame_size,
4064 -(frame_size < 0)));
71038426 4065 if (!sp_adj2)
9c0e94a5 4066 abort ();
9c0e94a5 4067 }
9c0e94a5 4068 }
a6f12d7c 4069
9c0e94a5
RH
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 ());
3873d24b
RH
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));
9c0e94a5
RH
4079 }
4080 else if (TARGET_OPEN_VMS)
4081 {
4082 emit_insn (gen_blockage ());
6abc6f40
RH
4083 FRP (emit_move_insn (hard_frame_pointer_rtx,
4084 gen_rtx_REG (DImode, vms_save_fp_regno)));
9c0e94a5
RH
4085 }
4086
4087 /* Restore the stack pointer. */
4088 emit_insn (gen_blockage ());
6abc6f40
RH
4089 FRP (emit_move_insn (stack_pointer_rtx,
4090 gen_rtx_PLUS (DImode, sp_adj1, sp_adj2)));
9c0e94a5
RH
4091 }
4092 else
4093 {
4094 if (TARGET_OPEN_VMS && !vms_is_stack_procedure)
4095 {
4096 emit_insn (gen_blockage ());
6abc6f40
RH
4097 FRP (emit_move_insn (hard_frame_pointer_rtx,
4098 gen_rtx_REG (DImode, vms_save_fp_regno)));
9c0e94a5 4099 }
a6f12d7c
RK
4100 }
4101
9c0e94a5
RH
4102 /* Return. */
4103 emit_jump_insn (gen_return_internal ());
4104}
4105
4106/* Output the rest of the textual info surrounding the epilogue. */
4107
4108void
acd92049 4109alpha_end_function (file, fnname, decl)
9c0e94a5 4110 FILE *file;
acd92049 4111 char *fnname;
3c303f52 4112 tree decl ATTRIBUTE_UNUSED;
9c0e94a5 4113{
a6f12d7c 4114 /* End the function. */
33d01c33
RK
4115 if (!flag_inhibit_size_directive)
4116 {
9c0e94a5 4117 fputs ("\t.end ", file);
acd92049 4118 assemble_name (file, fnname);
9c0e94a5 4119 putc ('\n', file);
33d01c33 4120 }
48f6bfac 4121 inside_function = FALSE;
9973f4a2 4122
60593797
RH
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
5e62dee5 4127 or other libraries. Similarly, don't do this for weak functions. */
60593797 4128
5e62dee5
RH
4129 if (!DECL_WEAK (current_function_decl)
4130 && (!flag_pic || !TREE_PUBLIC (current_function_decl)))
60593797 4131 SYMBOL_REF_FLAG (XEXP (DECL_RTL (current_function_decl), 0)) = 1;
a6f12d7c 4132}
48f6bfac
RK
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
4141int sdb_label_count = 0;
4142
4143/* Next label # for each statement. */
4144
4145static int sym_lineno = 0;
4146
4147/* Count the number of .file directives, so that .loc is up to date. */
4148
4149static int num_source_filenames = 0;
4150
4151/* Name of the file containing the current function. */
4152
df45c7ea 4153static const char *current_function_file = "";
48f6bfac
RK
4154
4155/* Offsets to alpha virtual arg/local debugging pointers. */
4156
4157long alpha_arg_offset;
4158long alpha_auto_offset;
4159\f
4160/* Emit a new filename to a stream. */
4161
4162void
4163alpha_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
6af601b3 4182 else if (write_symbols == DBX_DEBUG)
48f6bfac
RK
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
5665caa2 4191 && strcmp (name, current_function_file) != 0)
48f6bfac
RK
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
4209void
4210alpha_output_lineno (stream, line)
4211 FILE *stream;
4212 int line;
4213{
6af601b3 4214 if (write_symbols == DBX_DEBUG)
48f6bfac
RK
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
40828e35 4222 fprintf (stream, "\n\t.loc\t%d %d\n", num_source_filenames, line);
48f6bfac 4223}
6245e3df
RK
4224\f
4225/* Structure to show the current status of registers and memory. */
4226
4227struct shadow_summary
4228{
4229 struct {
2ea844d3
RH
4230 unsigned long i : 31; /* Mask of int regs */
4231 unsigned long fp : 31; /* Mask of fp regs */
6245e3df
RK
4232 unsigned long mem : 1; /* mem == imem | fpmem */
4233 } used, defd;
4234};
4235
9c0e94a5
RH
4236static void summarize_insn PROTO((rtx, struct shadow_summary *, int));
4237static void alpha_handle_trap_shadows PROTO((rtx));
4238
6245e3df
RK
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
4243static void
4244summarize_insn (x, sum, set)
4245 rtx x;
4246 struct shadow_summary *sum;
4247 int set;
4248{
6f7d635c 4249 const char *format_ptr;
6245e3df
RK
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
f4e31cf5
RH
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
6245e3df 4277 case PARALLEL:
8fed04e5 4278 for (i = XVECLEN (x, 0) - 1; i >= 0; i--)
6245e3df
RK
4279 summarize_insn (XVECEXP (x, 0, i), sum, 0);
4280 break;
4281
f4e31cf5 4282 case SUBREG:
9c0e94a5
RH
4283 summarize_insn (SUBREG_REG (x), sum, 0);
4284 break;
f4e31cf5 4285
6245e3df
RK
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
8ba46994
RK
4321 case CONST_INT: case CONST_DOUBLE:
4322 case SYMBOL_REF: case LABEL_REF: case CONST:
4323 break;
4324
6245e3df
RK
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));
8fed04e5 4345 for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
bed95fa1 4346 switch (format_ptr[i])
6245e3df
RK
4347 {
4348 case 'e':
4349 summarize_insn (XEXP (x, i), sum, 0);
4350 break;
4351
4352 case 'E':
8fed04e5 4353 for (j = XVECLEN (x, i) - 1; j >= 0; j--)
6245e3df
RK
4354 summarize_insn (XVECEXP (x, i, j), sum, 0);
4355 break;
4356
2b01d264
RH
4357 case 'i':
4358 break;
4359
6245e3df
RK
4360 default:
4361 abort ();
4362 }
4363 }
4364}
6245e3df 4365
9c0e94a5
RH
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.)
6245e3df 4396
2ea844d3 4397 (d) The trap shadow may not include any branch instructions. */
6245e3df 4398
2ea844d3
RH
4399static void
4400alpha_handle_trap_shadows (insns)
4401 rtx insns;
6245e3df 4402{
2ea844d3
RH
4403 struct shadow_summary shadow;
4404 int trap_pending, exception_nesting;
68aed21b 4405 rtx i, n;
6245e3df 4406
2ea844d3
RH
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;
f4e31cf5 4455 sum.defd = sum.used;
2ea844d3
RH
4456
4457 switch (GET_CODE (i))
4458 {
4459 case INSN:
bb02e7ea
RH
4460 /* Annoyingly, get_attr_trap will abort on these. */
4461 if (GET_CODE (PATTERN (i)) == USE
4462 || GET_CODE (PATTERN (i)) == CLOBBER)
2ea844d3
RH
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:
6245e3df 4502 abort ();
2ea844d3
RH
4503 }
4504 }
4505 else
4506 {
4507 close_shadow:
68aed21b
RH
4508 n = emit_insn_before (gen_trapb (), i);
4509 PUT_MODE (n, TImode);
4510 PUT_MODE (i, TImode);
2ea844d3
RH
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 }
6245e3df 4519
4f3f5e9f
RH
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 }
6245e3df
RK
4530 }
4531}
68aed21b
RH
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
3873d24b
RH
4537enum alphaev4_pipe {
4538 EV4_STOP = 0,
4539 EV4_IB0 = 1,
4540 EV4_IB1 = 2,
4541 EV4_IBX = 4
4542};
4543
68aed21b
RH
4544enum 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
3873d24b
RH
4555static enum alphaev4_pipe alphaev4_insn_pipe PROTO((rtx));
4556static enum alphaev5_pipe alphaev5_insn_pipe PROTO((rtx));
4557static rtx alphaev4_next_group PROTO((rtx, int*, int*));
4558static rtx alphaev5_next_group PROTO((rtx, int*, int*));
4559static rtx alphaev4_next_nop PROTO((int*));
4560static rtx alphaev5_next_nop PROTO((int*));
4561
4562static void alpha_align_insns
4563 PROTO((rtx, int, rtx (*)(rtx, int*, int*), rtx (*)(int*), int));
4564
4565static enum alphaev4_pipe
4566alphaev4_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
68aed21b
RH
4607static enum alphaev5_pipe
4608alphaev5_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;
2c01018f
RH
4650
4651 default:
4652 abort();
68aed21b 4653 }
68aed21b
RH
4654}
4655
3873d24b
RH
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
4662static rtx
4663alphaev4_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.
68aed21b
RH
4759
4760 LEN is, of course, the length of the group in bytes. */
4761
4762static rtx
4763alphaev5_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
2c01018f
RH
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;
68aed21b 4775
2c01018f 4776 while (1)
68aed21b
RH
4777 {
4778 enum alphaev5_pipe pipe;
68aed21b
RH
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);
2c01018f 4795 goto next_and_done;
68aed21b
RH
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 {
3873d24b 4816 if (!(in_use & EV5_E01) || (in_use & EV5_E1))
68aed21b
RH
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)
2c01018f 4864 goto next_and_done;
68aed21b 4865
2c01018f 4866 next:
68aed21b
RH
4867 insn = next_nonnote_insn (insn);
4868
2c01018f 4869 if (!insn || GET_RTX_CLASS (GET_CODE (insn)) != 'i')
68aed21b 4870 goto done;
a874dd18 4871
68aed21b
RH
4872 /* Let Haifa tell us where it thinks insn group boundaries are. */
4873 if (GET_MODE (insn) == TImode)
4874 goto done;
4875
2c01018f
RH
4876 if (GET_CODE (insn) == CLOBBER || GET_CODE (insn) == USE)
4877 goto next;
68aed21b 4878 }
2c01018f
RH
4879
4880 next_and_done:
4881 insn = next_nonnote_insn (insn);
68aed21b
RH
4882
4883 done:
4884 *plen = len;
4885 *pin_use = in_use;
4886 return insn;
68aed21b
RH
4887}
4888
3873d24b
RH
4889static rtx
4890alphaev4_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
4918static rtx
4919alphaev5_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
68aed21b 4949static void
3873d24b 4950alpha_align_insns (insns, max_align, next_group, next_nop, gp_in_use)
68aed21b 4951 rtx insns;
3873d24b
RH
4952 int max_align;
4953 rtx (*next_group) PROTO((rtx, int*, int*));
4954 rtx (*next_nop) PROTO((int*));
4955 int gp_in_use;
68aed21b
RH
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
80db34d8
RH
4967 align = (FUNCTION_BOUNDARY/BITS_PER_UNIT < max_align
4968 ? FUNCTION_BOUNDARY/BITS_PER_UNIT : max_align);
4969
3873d24b
RH
4970 /* Account for the initial GP load, which happens before the scheduled
4971 prologue we emitted as RTL. */
68aed21b
RH
4972 ofs = prev_in_use = 0;
4973 if (alpha_does_function_need_gp())
4974 {
80db34d8 4975 ofs = 8 & (align - 1);
3873d24b 4976 prev_in_use = gp_in_use;
68aed21b 4977 }
3873d24b 4978
68aed21b
RH
4979 i = insns;
4980 if (GET_CODE (i) == NOTE)
4981 i = next_nonnote_insn (i);
4982
4983 while (i)
4984 {
3873d24b 4985 next = (*next_group)(i, &in_use, &len);
68aed21b
RH
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 {
3873d24b 4993 align = new_align < max_align ? new_align : max_align;
68aed21b
RH
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
3873d24b
RH
5043 /* Insert nops before labels and branches to truely merge the
5044 execution of the nops with the previous instruction group. */
68aed21b 5045 where = prev_nonnote_insn (i);
3873d24b 5046 if (where)
68aed21b 5047 {
3873d24b 5048 if (GET_CODE (where) == CODE_LABEL)
68aed21b 5049 {
3873d24b
RH
5050 rtx where2 = prev_nonnote_insn (where);
5051 if (where2 && GET_CODE (where2) == JUMP_INSN)
5052 where = where2;
68aed21b 5053 }
3873d24b
RH
5054 else if (GET_CODE (where) != JUMP_INSN)
5055 where = i;
68aed21b 5056 }
3873d24b
RH
5057 else
5058 where = i;
5059
5060 do
5061 emit_insn_before ((*next_nop)(&prev_in_use), where);
68aed21b
RH
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
2ea844d3
RH
5073/* Machine dependant reorg pass. */
5074
5075void
5076alpha_reorg (insns)
5077 rtx insns;
5078{
68aed21b
RH
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 {
3873d24b
RH
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);
68aed21b
RH
5096 }
5097#endif
2ea844d3
RH
5098}
5099
5100\f
a874dd18
RK
5101/* Check a floating-point value for validity for a particular machine mode. */
5102
9c0e94a5 5103static char * const float_strings[] =
a874dd18 5104{
39d78b32 5105 /* These are for FLOAT_VAX. */
a874dd18
RK
5106 "1.70141173319264430e+38", /* 2^127 (2^24 - 1) / 2^24 */
5107 "-1.70141173319264430e+38",
5108 "2.93873587705571877e-39", /* 2^-128 */
39d78b32
RK
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",
a874dd18
RK
5116};
5117
39d78b32 5118static REAL_VALUE_TYPE float_values[8];
a874dd18
RK
5119static int inited_float_values = 0;
5120
5121int
5122check_float_value (mode, d, overflow)
5123 enum machine_mode mode;
5124 REAL_VALUE_TYPE *d;
3c303f52 5125 int overflow ATTRIBUTE_UNUSED;
a874dd18
RK
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;
39d78b32 5134 for (i = 0; i < 8; i++)
a874dd18
RK
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;
39d78b32
RK
5143 REAL_VALUE_TYPE *fvptr;
5144
5145 if (TARGET_FLOAT_VAX)
5146 fvptr = &float_values[0];
5147 else
5148 fvptr = &float_values[4];
a874dd18 5149
acbdd7dd 5150 bcopy ((char *) d, (char *) &r, sizeof (REAL_VALUE_TYPE));
39d78b32 5151 if (REAL_VALUES_LESS (fvptr[0], r))
a874dd18 5152 {
39d78b32 5153 bcopy ((char *) &fvptr[0], (char *) d,
acbdd7dd 5154 sizeof (REAL_VALUE_TYPE));
a874dd18
RK
5155 return 1;
5156 }
39d78b32 5157 else if (REAL_VALUES_LESS (r, fvptr[1]))
a874dd18 5158 {
39d78b32 5159 bcopy ((char *) &fvptr[1], (char *) d,
acbdd7dd 5160 sizeof (REAL_VALUE_TYPE));
a874dd18
RK
5161 return 1;
5162 }
5163 else if (REAL_VALUES_LESS (dconst0, r)
39d78b32 5164 && REAL_VALUES_LESS (r, fvptr[2]))
a874dd18 5165 {
acbdd7dd 5166 bcopy ((char *) &dconst0, (char *) d, sizeof (REAL_VALUE_TYPE));
a874dd18
RK
5167 return 1;
5168 }
5169 else if (REAL_VALUES_LESS (r, dconst0)
39d78b32 5170 && REAL_VALUES_LESS (fvptr[3], r))
a874dd18 5171 {
acbdd7dd 5172 bcopy ((char *) &dconst0, (char *) d, sizeof (REAL_VALUE_TYPE));
a874dd18
RK
5173 return 1;
5174 }
5175 }
5176
5177 return 0;
5178}
89cfc2c6
RK
5179
5180#if OPEN_VMS
5181
e9a25f70 5182/* Return the VMS argument type corresponding to MODE. */
89cfc2c6 5183
e9a25f70
JL
5184enum avms_arg_type
5185alpha_arg_type (mode)
5186 enum machine_mode mode;
5187{
5188 switch (mode)
89cfc2c6 5189 {
e9a25f70
JL
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;
89cfc2c6 5196 }
e9a25f70 5197}
89cfc2c6 5198
e9a25f70
JL
5199/* Return an rtx for an integer representing the VMS Argument Information
5200 register value. */
89cfc2c6 5201
e9a25f70
JL
5202struct rtx_def *
5203alpha_arg_info_reg_val (cum)
5204 CUMULATIVE_ARGS cum;
5205{
5206 unsigned HOST_WIDE_INT regval = cum.num_args;
5207 int i;
89cfc2c6 5208
e9a25f70
JL
5209 for (i = 0; i < 6; i++)
5210 regval |= ((int) cum.atypes[i]) << (i * 3 + 8);
89cfc2c6 5211
e9a25f70
JL
5212 return GEN_INT (regval);
5213}
5214\f
89cfc2c6
RK
5215/* Structure to collect function names for final output
5216 in link section. */
5217
5218enum links_kind {KIND_UNUSED, KIND_LOCAL, KIND_EXTERN};
5219
5220
5221struct alpha_links {
5222 struct alpha_links *next;
5223 char *name;
5224 enum links_kind kind;
5225};
5226
5227static 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
5233void
5234alpha_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 {
9398dc27 5251 /* Defined here but external assumed. */
89cfc2c6
RK
5252 if (lptr->kind == KIND_EXTERN)
5253 lptr->kind = KIND_LOCAL;
5254 }
5255 else
5256 {
9398dc27 5257 /* Used here but unused assumed. */
89cfc2c6
RK
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
9398dc27
RK
5271 /* Ensure we have an IDENTIFIER so assemble_name can mark is used. */
5272 get_identifier (name);
5273
89cfc2c6
RK
5274 alpha_links_base = nptr;
5275
5276 return;
5277}
5278
5279
5280void
5281alpha_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
531ea24e 5298 fprintf (stream, "$%s..lk:\n", lptr->name);
89cfc2c6
RK
5299 if (lptr->kind == KIND_LOCAL)
5300 {
5301 /* Local and used, build linkage pair. */
eeeb91c5 5302 fprintf (stream, "\t.quad %s..en\n", lptr->name);
89cfc2c6
RK
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
5313void
5314alpha_need_linkage (name, is_local)
3c303f52
KG
5315 char *name ATTRIBUTE_UNUSED;
5316 int is_local ATTRIBUTE_UNUSED;
89cfc2c6
RK
5317{
5318}
5319
5320#endif /* OPEN_VMS */