]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/alpha/alpha.c
osf5.h (MD_UNWIND_SUPPORT): Define.
[thirdparty/gcc.git] / gcc / config / alpha / alpha.c
CommitLineData
a6f12d7c 1/* Subroutines used for code generation on the DEC Alpha.
b6e46ca1 2 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
c75c517d 3 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
c0f64575 4 Free Software Foundation, Inc.
d60a05a1 5 Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
a6f12d7c 6
7ec022b2 7This file is part of GCC.
a6f12d7c 8
7ec022b2 9GCC is free software; you can redistribute it and/or modify
a6f12d7c 10it under the terms of the GNU General Public License as published by
2f83c7d6 11the Free Software Foundation; either version 3, or (at your option)
a6f12d7c
RK
12any later version.
13
7ec022b2 14GCC is distributed in the hope that it will be useful,
a6f12d7c
RK
15but WITHOUT ANY WARRANTY; without even the implied warranty of
16MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17GNU General Public License for more details.
18
19You should have received a copy of the GNU General Public License
2f83c7d6
NC
20along with GCC; see the file COPYING3. If not see
21<http://www.gnu.org/licenses/>. */
a6f12d7c
RK
22
23
a6f12d7c 24#include "config.h"
3c303f52 25#include "system.h"
4977bab6
ZW
26#include "coretypes.h"
27#include "tm.h"
a6f12d7c 28#include "rtl.h"
e78d8e51 29#include "tree.h"
a6f12d7c
RK
30#include "regs.h"
31#include "hard-reg-set.h"
a6f12d7c
RK
32#include "insn-config.h"
33#include "conditions.h"
a6f12d7c
RK
34#include "output.h"
35#include "insn-attr.h"
36#include "flags.h"
37#include "recog.h"
a6f12d7c 38#include "expr.h"
e78d8e51
ZW
39#include "optabs.h"
40#include "reload.h"
a6f12d7c 41#include "obstack.h"
9ecc37f0
RH
42#include "except.h"
43#include "function.h"
718f9c0f 44#include "diagnostic-core.h"
3c303f52 45#include "toplev.h"
01439aee 46#include "ggc.h"
b91055dd 47#include "integrate.h"
aead1ca3 48#include "tm_p.h"
672a6f42
NB
49#include "target.h"
50#include "target-def.h"
14691f8d 51#include "debug.h"
f1e639b1 52#include "langhooks.h"
17211ab5 53#include <splay-tree.h>
117dca74 54#include "cfglayout.h"
726a989a 55#include "gimple.h"
9d30f3c1
JJ
56#include "tree-flow.h"
57#include "tree-stdarg.h"
dfcbeaa5 58#include "tm-constrs.h"
6fb5fa3c 59#include "df.h"
5e3fef6c 60#include "libfuncs.h"
9ecc37f0 61
285a5742 62/* Specify which cpu to schedule for. */
8bea7f7c 63enum processor_type alpha_tune;
9ecc37f0 64
8bea7f7c 65/* Which cpu we're generating code for. */
9b009d45 66enum processor_type alpha_cpu;
8bea7f7c 67
f676971a 68static const char * const alpha_cpu_name[] =
bcbbac26
RH
69{
70 "ev4", "ev5", "ev6"
71};
da792a68 72
6245e3df
RK
73/* Specify how accurate floating-point traps need to be. */
74
75enum alpha_trap_precision alpha_tp;
76
77/* Specify the floating-point rounding mode. */
78
79enum alpha_fp_rounding_mode alpha_fprm;
80
81/* Specify which things cause traps. */
82
83enum alpha_fp_trap_mode alpha_fptm;
84
825dda42 85/* Nonzero if inside of a function, because the Alpha asm can't
48f6bfac
RK
86 handle .files inside of functions. */
87
88static int inside_function = FALSE;
89
bcbbac26
RH
90/* The number of cycles of latency we should assume on memory reads. */
91
92int alpha_memory_latency = 3;
93
9c0e94a5
RH
94/* Whether the function needs the GP. */
95
96static int alpha_function_needs_gp;
97
3873d24b
RH
98/* The alias set for prologue/epilogue register save/restore. */
99
4862826d 100static GTY(()) alias_set_type alpha_sr_alias_set;
3873d24b 101
941cc05a
RK
102/* The assembler name of the current function. */
103
104static const char *alpha_fnname;
105
1eb356b9 106/* The next explicit relocation sequence number. */
f030826a 107extern GTY(()) int alpha_next_sequence_number;
1eb356b9
RH
108int alpha_next_sequence_number = 1;
109
110/* The literal and gpdisp sequence numbers for this insn, as printed
111 by %# and %* respectively. */
f030826a
RH
112extern GTY(()) int alpha_this_literal_sequence_number;
113extern GTY(()) int alpha_this_gpdisp_sequence_number;
1eb356b9
RH
114int alpha_this_literal_sequence_number;
115int alpha_this_gpdisp_sequence_number;
116
3c50106f
RH
117/* Costs of various operations on the different architectures. */
118
119struct alpha_rtx_cost_data
120{
121 unsigned char fp_add;
122 unsigned char fp_mult;
123 unsigned char fp_div_sf;
124 unsigned char fp_div_df;
125 unsigned char int_mult_si;
126 unsigned char int_mult_di;
127 unsigned char int_shift;
128 unsigned char int_cmov;
8260c194 129 unsigned short int_div;
3c50106f
RH
130};
131
132static struct alpha_rtx_cost_data const alpha_rtx_cost_data[PROCESSOR_MAX] =
133{
134 { /* EV4 */
135 COSTS_N_INSNS (6), /* fp_add */
136 COSTS_N_INSNS (6), /* fp_mult */
137 COSTS_N_INSNS (34), /* fp_div_sf */
138 COSTS_N_INSNS (63), /* fp_div_df */
139 COSTS_N_INSNS (23), /* int_mult_si */
140 COSTS_N_INSNS (23), /* int_mult_di */
141 COSTS_N_INSNS (2), /* int_shift */
142 COSTS_N_INSNS (2), /* int_cmov */
9b4f6a07 143 COSTS_N_INSNS (97), /* int_div */
3c50106f
RH
144 },
145 { /* EV5 */
146 COSTS_N_INSNS (4), /* fp_add */
147 COSTS_N_INSNS (4), /* fp_mult */
148 COSTS_N_INSNS (15), /* fp_div_sf */
149 COSTS_N_INSNS (22), /* fp_div_df */
150 COSTS_N_INSNS (8), /* int_mult_si */
151 COSTS_N_INSNS (12), /* int_mult_di */
152 COSTS_N_INSNS (1) + 1, /* int_shift */
153 COSTS_N_INSNS (1), /* int_cmov */
9b4f6a07 154 COSTS_N_INSNS (83), /* int_div */
3c50106f
RH
155 },
156 { /* EV6 */
157 COSTS_N_INSNS (4), /* fp_add */
158 COSTS_N_INSNS (4), /* fp_mult */
159 COSTS_N_INSNS (12), /* fp_div_sf */
160 COSTS_N_INSNS (15), /* fp_div_df */
161 COSTS_N_INSNS (7), /* int_mult_si */
162 COSTS_N_INSNS (7), /* int_mult_di */
163 COSTS_N_INSNS (1), /* int_shift */
164 COSTS_N_INSNS (2), /* int_cmov */
9b4f6a07 165 COSTS_N_INSNS (86), /* int_div */
3c50106f
RH
166 },
167};
168
8260c194
RH
169/* Similar but tuned for code size instead of execution latency. The
170 extra +N is fractional cost tuning based on latency. It's used to
171 encourage use of cheaper insns like shift, but only if there's just
172 one of them. */
173
174static struct alpha_rtx_cost_data const alpha_rtx_cost_size =
175{
176 COSTS_N_INSNS (1), /* fp_add */
177 COSTS_N_INSNS (1), /* fp_mult */
178 COSTS_N_INSNS (1), /* fp_div_sf */
179 COSTS_N_INSNS (1) + 1, /* fp_div_df */
180 COSTS_N_INSNS (1) + 1, /* int_mult_si */
181 COSTS_N_INSNS (1) + 2, /* int_mult_di */
182 COSTS_N_INSNS (1), /* int_shift */
183 COSTS_N_INSNS (1), /* int_cmov */
184 COSTS_N_INSNS (6), /* int_div */
185};
186
e9a25f70 187/* Get the number of args of a function in one of two ways. */
30102605 188#if TARGET_ABI_OPEN_VMS || TARGET_ABI_UNICOSMK
38173d38 189#define NUM_ARGS crtl->args.info.num_args
e9a25f70 190#else
38173d38 191#define NUM_ARGS crtl->args.info
e9a25f70 192#endif
26250081 193
26250081
RH
194#define REG_PV 27
195#define REG_RA 26
6d8fd7bb 196
a5c24926
RH
197/* Declarations of static functions. */
198static struct machine_function *alpha_init_machine_status (void);
0da4e73a 199static rtx alpha_emit_xfloating_compare (enum rtx_code *, rtx, rtx);
4977bab6 200
a5c24926
RH
201#if TARGET_ABI_OPEN_VMS
202static void alpha_write_linkage (FILE *, const char *, tree);
dfe6ba6d 203static bool vms_valid_pointer_mode (enum machine_mode);
c590b625
RH
204#endif
205
a5c24926
RH
206static void unicosmk_output_deferred_case_vectors (FILE *);
207static void unicosmk_gen_dsib (unsigned long *);
208static void unicosmk_output_ssib (FILE *, const char *);
209static int unicosmk_need_dex (rtx);
672a6f42 210\f
8bea7f7c
RH
211/* Implement TARGET_HANDLE_OPTION. */
212
213static bool
214alpha_handle_option (size_t code, const char *arg, int value)
215{
216 switch (code)
217 {
34251c0e
JM
218 case OPT_G:
219 g_switch_value = value;
220 g_switch_set = true;
221 break;
222
8bea7f7c
RH
223 case OPT_mfp_regs:
224 if (value == 0)
225 target_flags |= MASK_SOFT_FP;
226 break;
227
228 case OPT_mieee:
229 case OPT_mieee_with_inexact:
230 target_flags |= MASK_IEEE_CONFORMANT;
231 break;
232
8bea7f7c 233 case OPT_mtls_size_:
55bea00a 234 if (value != 16 && value != 32 && value != 64)
8bea7f7c
RH
235 error ("bad value %qs for -mtls-size switch", arg);
236 break;
237 }
238
239 return true;
240}
241
7269aee7 242#ifdef TARGET_ALTERNATE_LONG_DOUBLE_MANGLING
608063c3 243/* Implement TARGET_MANGLE_TYPE. */
7269aee7
AH
244
245static const char *
3101faab 246alpha_mangle_type (const_tree type)
7269aee7
AH
247{
248 if (TYPE_MAIN_VARIANT (type) == long_double_type_node
249 && TARGET_LONG_DOUBLE_128)
250 return "g";
251
252 /* For all other types, use normal C++ mangling. */
253 return NULL;
254}
255#endif
256
285a5742 257/* Parse target option strings. */
6245e3df
RK
258
259void
a5c24926 260override_options (void)
6245e3df 261{
8b60264b
KG
262 static const struct cpu_table {
263 const char *const name;
264 const enum processor_type processor;
265 const int flags;
a3b815cb 266 } cpu_table[] = {
a3b815cb
JJ
267 { "ev4", PROCESSOR_EV4, 0 },
268 { "ev45", PROCESSOR_EV4, 0 },
269 { "21064", PROCESSOR_EV4, 0 },
8bea7f7c
RH
270 { "ev5", PROCESSOR_EV5, 0 },
271 { "21164", PROCESSOR_EV5, 0 },
272 { "ev56", PROCESSOR_EV5, MASK_BWX },
273 { "21164a", PROCESSOR_EV5, MASK_BWX },
274 { "pca56", PROCESSOR_EV5, MASK_BWX|MASK_MAX },
275 { "21164PC",PROCESSOR_EV5, MASK_BWX|MASK_MAX },
276 { "21164pc",PROCESSOR_EV5, MASK_BWX|MASK_MAX },
277 { "ev6", PROCESSOR_EV6, MASK_BWX|MASK_MAX|MASK_FIX },
278 { "21264", PROCESSOR_EV6, MASK_BWX|MASK_MAX|MASK_FIX },
279 { "ev67", PROCESSOR_EV6, MASK_BWX|MASK_MAX|MASK_FIX|MASK_CIX },
8224166e 280 { "21264a", PROCESSOR_EV6, MASK_BWX|MASK_MAX|MASK_FIX|MASK_CIX }
a3b815cb 281 };
f676971a 282
8224166e 283 int const ct_size = ARRAY_SIZE (cpu_table);
8bea7f7c
RH
284 int i;
285
30102605
RH
286 /* Unicos/Mk doesn't have shared libraries. */
287 if (TARGET_ABI_UNICOSMK && flag_pic)
288 {
d4ee4d25 289 warning (0, "-f%s ignored for Unicos/Mk (not supported)",
30102605
RH
290 (flag_pic > 1) ? "PIC" : "pic");
291 flag_pic = 0;
292 }
293
f676971a 294 /* On Unicos/Mk, the native compiler consistently generates /d suffices for
30102605
RH
295 floating-point instructions. Make that the default for this target. */
296 if (TARGET_ABI_UNICOSMK)
297 alpha_fprm = ALPHA_FPRM_DYN;
298 else
299 alpha_fprm = ALPHA_FPRM_NORM;
300
6245e3df 301 alpha_tp = ALPHA_TP_PROG;
6245e3df
RK
302 alpha_fptm = ALPHA_FPTM_N;
303
f676971a 304 /* We cannot use su and sui qualifiers for conversion instructions on
30102605
RH
305 Unicos/Mk. I'm not sure if this is due to assembler or hardware
306 limitations. Right now, we issue a warning if -mieee is specified
307 and then ignore it; eventually, we should either get it right or
308 disable the option altogether. */
309
6245e3df
RK
310 if (TARGET_IEEE)
311 {
30102605 312 if (TARGET_ABI_UNICOSMK)
d4ee4d25 313 warning (0, "-mieee not supported on Unicos/Mk");
30102605
RH
314 else
315 {
316 alpha_tp = ALPHA_TP_INSN;
317 alpha_fptm = ALPHA_FPTM_SU;
318 }
6245e3df
RK
319 }
320
321 if (TARGET_IEEE_WITH_INEXACT)
322 {
30102605 323 if (TARGET_ABI_UNICOSMK)
d4ee4d25 324 warning (0, "-mieee-with-inexact not supported on Unicos/Mk");
30102605
RH
325 else
326 {
327 alpha_tp = ALPHA_TP_INSN;
328 alpha_fptm = ALPHA_FPTM_SUI;
329 }
6245e3df
RK
330 }
331
332 if (alpha_tp_string)
10d5c73f
RK
333 {
334 if (! strcmp (alpha_tp_string, "p"))
6245e3df 335 alpha_tp = ALPHA_TP_PROG;
10d5c73f 336 else if (! strcmp (alpha_tp_string, "f"))
6245e3df 337 alpha_tp = ALPHA_TP_FUNC;
10d5c73f 338 else if (! strcmp (alpha_tp_string, "i"))
6245e3df 339 alpha_tp = ALPHA_TP_INSN;
10d5c73f 340 else
9e637a26 341 error ("bad value %qs for -mtrap-precision switch", alpha_tp_string);
10d5c73f 342 }
6245e3df
RK
343
344 if (alpha_fprm_string)
10d5c73f
RK
345 {
346 if (! strcmp (alpha_fprm_string, "n"))
6245e3df 347 alpha_fprm = ALPHA_FPRM_NORM;
10d5c73f 348 else if (! strcmp (alpha_fprm_string, "m"))
6245e3df 349 alpha_fprm = ALPHA_FPRM_MINF;
10d5c73f 350 else if (! strcmp (alpha_fprm_string, "c"))
6245e3df 351 alpha_fprm = ALPHA_FPRM_CHOP;
10d5c73f 352 else if (! strcmp (alpha_fprm_string,"d"))
6245e3df 353 alpha_fprm = ALPHA_FPRM_DYN;
10d5c73f 354 else
9e637a26 355 error ("bad value %qs for -mfp-rounding-mode switch",
6245e3df 356 alpha_fprm_string);
10d5c73f 357 }
6245e3df
RK
358
359 if (alpha_fptm_string)
10d5c73f
RK
360 {
361 if (strcmp (alpha_fptm_string, "n") == 0)
362 alpha_fptm = ALPHA_FPTM_N;
363 else if (strcmp (alpha_fptm_string, "u") == 0)
364 alpha_fptm = ALPHA_FPTM_U;
365 else if (strcmp (alpha_fptm_string, "su") == 0)
366 alpha_fptm = ALPHA_FPTM_SU;
367 else if (strcmp (alpha_fptm_string, "sui") == 0)
368 alpha_fptm = ALPHA_FPTM_SUI;
369 else
9e637a26 370 error ("bad value %qs for -mfp-trap-mode switch", alpha_fptm_string);
10d5c73f 371 }
6245e3df 372
de4abb91
RH
373 if (alpha_cpu_string)
374 {
8224166e 375 for (i = 0; i < ct_size; i++)
a3b815cb
JJ
376 if (! strcmp (alpha_cpu_string, cpu_table [i].name))
377 {
8bea7f7c
RH
378 alpha_tune = alpha_cpu = cpu_table [i].processor;
379 target_flags &= ~ (MASK_BWX | MASK_MAX | MASK_FIX | MASK_CIX);
a3b815cb
JJ
380 target_flags |= cpu_table [i].flags;
381 break;
382 }
8224166e 383 if (i == ct_size)
9e637a26 384 error ("bad value %qs for -mcpu switch", alpha_cpu_string);
de4abb91
RH
385 }
386
a3b815cb
JJ
387 if (alpha_tune_string)
388 {
8224166e 389 for (i = 0; i < ct_size; i++)
a3b815cb
JJ
390 if (! strcmp (alpha_tune_string, cpu_table [i].name))
391 {
8bea7f7c 392 alpha_tune = cpu_table [i].processor;
a3b815cb
JJ
393 break;
394 }
8224166e 395 if (i == ct_size)
02d43000 396 error ("bad value %qs for -mtune switch", alpha_tune_string);
a3b815cb
JJ
397 }
398
285a5742 399 /* Do some sanity checks on the above options. */
6245e3df 400
30102605
RH
401 if (TARGET_ABI_UNICOSMK && alpha_fptm != ALPHA_FPTM_N)
402 {
d4ee4d25 403 warning (0, "trap mode not supported on Unicos/Mk");
30102605
RH
404 alpha_fptm = ALPHA_FPTM_N;
405 }
406
10d5c73f 407 if ((alpha_fptm == ALPHA_FPTM_SU || alpha_fptm == ALPHA_FPTM_SUI)
8bea7f7c 408 && alpha_tp != ALPHA_TP_INSN && alpha_cpu != PROCESSOR_EV6)
6245e3df 409 {
d4ee4d25 410 warning (0, "fp software completion requires -mtrap-precision=i");
6245e3df
RK
411 alpha_tp = ALPHA_TP_INSN;
412 }
89cfc2c6 413
8bea7f7c 414 if (alpha_cpu == PROCESSOR_EV6)
981a828e
RH
415 {
416 /* Except for EV6 pass 1 (not released), we always have precise
417 arithmetic traps. Which means we can do software completion
418 without minding trap shadows. */
419 alpha_tp = ALPHA_TP_PROG;
420 }
421
89cfc2c6
RK
422 if (TARGET_FLOAT_VAX)
423 {
424 if (alpha_fprm == ALPHA_FPRM_MINF || alpha_fprm == ALPHA_FPRM_DYN)
425 {
d4ee4d25 426 warning (0, "rounding mode not supported for VAX floats");
89cfc2c6
RK
427 alpha_fprm = ALPHA_FPRM_NORM;
428 }
429 if (alpha_fptm == ALPHA_FPTM_SUI)
430 {
d4ee4d25 431 warning (0, "trap mode not supported for VAX floats");
89cfc2c6
RK
432 alpha_fptm = ALPHA_FPTM_SU;
433 }
0f15adbd 434 if (target_flags_explicit & MASK_LONG_DOUBLE_128)
d4ee4d25 435 warning (0, "128-bit long double not supported for VAX floats");
0f15adbd 436 target_flags &= ~MASK_LONG_DOUBLE_128;
89cfc2c6 437 }
bcbbac26
RH
438
439 {
440 char *end;
441 int lat;
442
443 if (!alpha_mlat_string)
444 alpha_mlat_string = "L1";
445
d1e6b55b 446 if (ISDIGIT ((unsigned char)alpha_mlat_string[0])
bcbbac26
RH
447 && (lat = strtol (alpha_mlat_string, &end, 10), *end == '\0'))
448 ;
449 else if ((alpha_mlat_string[0] == 'L' || alpha_mlat_string[0] == 'l')
d1e6b55b 450 && ISDIGIT ((unsigned char)alpha_mlat_string[1])
bcbbac26
RH
451 && alpha_mlat_string[2] == '\0')
452 {
f676971a 453 static int const cache_latency[][4] =
bcbbac26
RH
454 {
455 { 3, 30, -1 }, /* ev4 -- Bcache is a guess */
456 { 2, 12, 38 }, /* ev5 -- Bcache from PC164 LMbench numbers */
285a5742 457 { 3, 12, 30 }, /* ev6 -- Bcache from DS20 LMbench. */
bcbbac26
RH
458 };
459
460 lat = alpha_mlat_string[1] - '0';
8bea7f7c 461 if (lat <= 0 || lat > 3 || cache_latency[alpha_tune][lat-1] == -1)
bcbbac26 462 {
d4ee4d25 463 warning (0, "L%d cache latency unknown for %s",
8bea7f7c 464 lat, alpha_cpu_name[alpha_tune]);
bcbbac26
RH
465 lat = 3;
466 }
467 else
8bea7f7c 468 lat = cache_latency[alpha_tune][lat-1];
bcbbac26
RH
469 }
470 else if (! strcmp (alpha_mlat_string, "main"))
471 {
472 /* Most current memories have about 370ns latency. This is
473 a reasonable guess for a fast cpu. */
474 lat = 150;
475 }
476 else
477 {
d4ee4d25 478 warning (0, "bad value %qs for -mmemory-latency", alpha_mlat_string);
bcbbac26
RH
479 lat = 3;
480 }
481
482 alpha_memory_latency = lat;
483 }
bb8ebb7f
RH
484
485 /* Default the definition of "small data" to 8 bytes. */
486 if (!g_switch_set)
487 g_switch_value = 8;
3873d24b 488
133d3133
RH
489 /* Infer TARGET_SMALL_DATA from -fpic/-fPIC. */
490 if (flag_pic == 1)
491 target_flags |= MASK_SMALL_DATA;
492 else if (flag_pic == 2)
493 target_flags &= ~MASK_SMALL_DATA;
494
c176c051
RH
495 /* Align labels and loops for optimal branching. */
496 /* ??? Kludge these by not doing anything if we don't optimize and also if
285a5742 497 we are writing ECOFF symbols to work around a bug in DEC's assembler. */
c176c051
RH
498 if (optimize > 0 && write_symbols != SDB_DEBUG)
499 {
500 if (align_loops <= 0)
501 align_loops = 16;
502 if (align_jumps <= 0)
503 align_jumps = 16;
504 }
505 if (align_functions <= 0)
506 align_functions = 16;
507
3873d24b
RH
508 /* Acquire a unique set number for our register saves and restores. */
509 alpha_sr_alias_set = new_alias_set ();
30102605
RH
510
511 /* Register variables and functions with the garbage collector. */
512
30102605
RH
513 /* Set up function hooks. */
514 init_machine_status = alpha_init_machine_status;
3dc85dfb
RH
515
516 /* Tell the compiler when we're using VAX floating point. */
517 if (TARGET_FLOAT_VAX)
518 {
70a01792
ZW
519 REAL_MODE_FORMAT (SFmode) = &vax_f_format;
520 REAL_MODE_FORMAT (DFmode) = &vax_g_format;
521 REAL_MODE_FORMAT (TFmode) = NULL;
3dc85dfb 522 }
ed965309
JJ
523
524#ifdef TARGET_DEFAULT_LONG_DOUBLE_128
525 if (!(target_flags_explicit & MASK_LONG_DOUBLE_128))
526 target_flags |= MASK_LONG_DOUBLE_128;
527#endif
d7bd8aeb
JJ
528
529 /* If using typedef char *va_list, signal that __builtin_va_start (&ap, 0)
530 can be optimized to ap = __builtin_next_arg (0). */
531 if (TARGET_ABI_UNICOSMK)
532 targetm.expand_builtin_va_start = NULL;
6245e3df
RK
533}
534\f
a6f12d7c
RK
535/* Returns 1 if VALUE is a mask that contains full bytes of zero or ones. */
536
537int
a5c24926 538zap_mask (HOST_WIDE_INT value)
a6f12d7c
RK
539{
540 int i;
541
542 for (i = 0; i < HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR;
543 i++, value >>= 8)
544 if ((value & 0xff) != 0 && (value & 0xff) != 0xff)
545 return 0;
546
547 return 1;
548}
549
f676971a 550/* Return true if OP is valid for a particular TLS relocation.
201312c2 551 We are already guaranteed that OP is a CONST. */
a6f12d7c
RK
552
553int
201312c2 554tls_symbolic_operand_1 (rtx op, int size, int unspec)
a6f12d7c 555{
6f9b006d
RH
556 op = XEXP (op, 0);
557
558 if (GET_CODE (op) != UNSPEC || XINT (op, 1) != unspec)
559 return 0;
560 op = XVECEXP (op, 0, 0);
561
562 if (GET_CODE (op) != SYMBOL_REF)
563 return 0;
6f9b006d 564
d055668e 565 switch (SYMBOL_REF_TLS_MODEL (op))
3094247f 566 {
d055668e 567 case TLS_MODEL_LOCAL_DYNAMIC:
f6326c19 568 return unspec == UNSPEC_DTPREL && size == alpha_tls_size;
d055668e 569 case TLS_MODEL_INITIAL_EXEC:
3094247f 570 return unspec == UNSPEC_TPREL && size == 64;
d055668e 571 case TLS_MODEL_LOCAL_EXEC:
f6326c19 572 return unspec == UNSPEC_TPREL && size == alpha_tls_size;
3094247f 573 default:
56daab84 574 gcc_unreachable ();
3094247f 575 }
6f9b006d
RH
576}
577
201312c2
RH
578/* Used by aligned_memory_operand and unaligned_memory_operand to
579 resolve what reload is going to do with OP if it's a register. */
8f4773ea 580
201312c2
RH
581rtx
582resolve_reload_operand (rtx op)
a6f12d7c 583{
4e46365b 584 if (reload_in_progress)
a6f12d7c 585 {
4e46365b
RH
586 rtx tmp = op;
587 if (GET_CODE (tmp) == SUBREG)
588 tmp = SUBREG_REG (tmp);
7d83f4f5 589 if (REG_P (tmp)
4e46365b
RH
590 && REGNO (tmp) >= FIRST_PSEUDO_REGISTER)
591 {
592 op = reg_equiv_memory_loc[REGNO (tmp)];
593 if (op == 0)
594 return 0;
595 }
a6f12d7c 596 }
201312c2 597 return op;
3611aef0
RH
598}
599
6dd53648
RH
600/* The scalar modes supported differs from the default check-what-c-supports
601 version in that sometimes TFmode is available even when long double
602 indicates only DFmode. On unicosmk, we have the situation that HImode
603 doesn't map to any C type, but of course we still support that. */
604
605static bool
606alpha_scalar_mode_supported_p (enum machine_mode mode)
607{
608 switch (mode)
609 {
610 case QImode:
611 case HImode:
612 case SImode:
613 case DImode:
614 case TImode: /* via optabs.c */
615 return true;
616
617 case SFmode:
618 case DFmode:
619 return true;
620
621 case TFmode:
622 return TARGET_HAS_XFLOATING_LIBS;
623
624 default:
625 return false;
626 }
627}
628
629/* Alpha implements a couple of integer vector mode operations when
e2ea71ea
RH
630 TARGET_MAX is enabled. We do not check TARGET_MAX here, however,
631 which allows the vectorizer to operate on e.g. move instructions,
632 or when expand_vector_operations can do something useful. */
6dd53648 633
f676971a
EC
634static bool
635alpha_vector_mode_supported_p (enum machine_mode mode)
636{
e2ea71ea 637 return mode == V8QImode || mode == V4HImode || mode == V2SImode;
f676971a
EC
638}
639
39157bcc
RH
640/* Return 1 if this function can directly return via $26. */
641
642int
a5c24926 643direct_return (void)
39157bcc 644{
30102605 645 return (! TARGET_ABI_OPEN_VMS && ! TARGET_ABI_UNICOSMK
be7b80f4
RH
646 && reload_completed
647 && alpha_sa_size () == 0
39157bcc 648 && get_frame_size () == 0
38173d38
JH
649 && crtl->outgoing_args_size == 0
650 && crtl->args.pretend_args_size == 0);
39157bcc 651}
25e21aed
RH
652
653/* Return the ADDR_VEC associated with a tablejump insn. */
654
655rtx
a5c24926 656alpha_tablejump_addr_vec (rtx insn)
25e21aed
RH
657{
658 rtx tmp;
659
660 tmp = JUMP_LABEL (insn);
661 if (!tmp)
662 return NULL_RTX;
663 tmp = NEXT_INSN (tmp);
664 if (!tmp)
665 return NULL_RTX;
7d83f4f5 666 if (JUMP_P (tmp)
25e21aed
RH
667 && GET_CODE (PATTERN (tmp)) == ADDR_DIFF_VEC)
668 return PATTERN (tmp);
669 return NULL_RTX;
670}
671
672/* Return the label of the predicted edge, or CONST0_RTX if we don't know. */
673
674rtx
a5c24926 675alpha_tablejump_best_label (rtx insn)
25e21aed
RH
676{
677 rtx jump_table = alpha_tablejump_addr_vec (insn);
678 rtx best_label = NULL_RTX;
679
680 /* ??? Once the CFG doesn't keep getting completely rebuilt, look
681 there for edge frequency counts from profile data. */
682
683 if (jump_table)
684 {
685 int n_labels = XVECLEN (jump_table, 1);
686 int best_count = -1;
687 int i, j;
688
689 for (i = 0; i < n_labels; i++)
690 {
691 int count = 1;
692
693 for (j = i + 1; j < n_labels; j++)
694 if (XEXP (XVECEXP (jump_table, 1, i), 0)
695 == XEXP (XVECEXP (jump_table, 1, j), 0))
696 count++;
697
698 if (count > best_count)
699 best_count = count, best_label = XVECEXP (jump_table, 1, i);
700 }
701 }
702
703 return best_label ? best_label : const0_rtx;
704}
6f9b006d
RH
705
706/* Return the TLS model to use for SYMBOL. */
707
708static enum tls_model
a5c24926 709tls_symbolic_operand_type (rtx symbol)
6f9b006d 710{
d055668e 711 enum tls_model model;
6f9b006d
RH
712
713 if (GET_CODE (symbol) != SYMBOL_REF)
8224166e 714 return TLS_MODEL_NONE;
d055668e 715 model = SYMBOL_REF_TLS_MODEL (symbol);
6f9b006d 716
d055668e
RH
717 /* Local-exec with a 64-bit size is the same code as initial-exec. */
718 if (model == TLS_MODEL_LOCAL_EXEC && alpha_tls_size == 64)
719 model = TLS_MODEL_INITIAL_EXEC;
6f9b006d 720
d055668e 721 return model;
6f9b006d 722}
3611aef0 723\f
3094247f
RH
724/* Return true if the function DECL will share the same GP as any
725 function in the current unit of translation. */
726
727static bool
3101faab 728decl_has_samegp (const_tree decl)
3094247f
RH
729{
730 /* Functions that are not local can be overridden, and thus may
731 not share the same gp. */
732 if (!(*targetm.binds_local_p) (decl))
733 return false;
734
735 /* If -msmall-data is in effect, assume that there is only one GP
736 for the module, and so any local symbol has this property. We
737 need explicit relocations to be able to enforce this for symbols
738 not defined in this unit of translation, however. */
739 if (TARGET_EXPLICIT_RELOCS && TARGET_SMALL_DATA)
740 return true;
741
742 /* Functions that are not external are defined in this UoT. */
7f24e7c5
RH
743 /* ??? Irritatingly, static functions not yet emitted are still
744 marked "external". Apply this to non-static functions only. */
745 return !TREE_PUBLIC (decl) || !DECL_EXTERNAL (decl);
3094247f
RH
746}
747
ae46c4e0
RH
748/* Return true if EXP should be placed in the small data section. */
749
750static bool
3101faab 751alpha_in_small_data_p (const_tree exp)
ae46c4e0 752{
34a6c2ec
RH
753 /* We want to merge strings, so we never consider them small data. */
754 if (TREE_CODE (exp) == STRING_CST)
755 return false;
756
7179b6db
RH
757 /* Functions are never in the small data area. Duh. */
758 if (TREE_CODE (exp) == FUNCTION_DECL)
759 return false;
760
ae46c4e0
RH
761 if (TREE_CODE (exp) == VAR_DECL && DECL_SECTION_NAME (exp))
762 {
763 const char *section = TREE_STRING_POINTER (DECL_SECTION_NAME (exp));
764 if (strcmp (section, ".sdata") == 0
765 || strcmp (section, ".sbss") == 0)
766 return true;
767 }
768 else
769 {
770 HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (exp));
771
772 /* If this is an incomplete type with size 0, then we can't put it
773 in sdata because it might be too big when completed. */
307b599c 774 if (size > 0 && (unsigned HOST_WIDE_INT) size <= g_switch_value)
ae46c4e0
RH
775 return true;
776 }
777
778 return false;
779}
780
1330f7d5 781#if TARGET_ABI_OPEN_VMS
dfe6ba6d
DR
782static bool
783vms_valid_pointer_mode (enum machine_mode mode)
784{
785 return (mode == SImode || mode == DImode);
786}
787
1330f7d5 788static bool
a5c24926 789alpha_linkage_symbol_p (const char *symname)
1330f7d5
DR
790{
791 int symlen = strlen (symname);
792
793 if (symlen > 4)
794 return strcmp (&symname [symlen - 4], "..lk") == 0;
795
796 return false;
797}
798
799#define LINKAGE_SYMBOL_REF_P(X) \
800 ((GET_CODE (X) == SYMBOL_REF \
801 && alpha_linkage_symbol_p (XSTR (X, 0))) \
802 || (GET_CODE (X) == CONST \
803 && GET_CODE (XEXP (X, 0)) == PLUS \
804 && GET_CODE (XEXP (XEXP (X, 0), 0)) == SYMBOL_REF \
805 && alpha_linkage_symbol_p (XSTR (XEXP (XEXP (X, 0), 0), 0))))
806#endif
807
a39bdefc
RH
808/* legitimate_address_p recognizes an RTL expression that is a valid
809 memory address for an instruction. The MODE argument is the
810 machine mode for the MEM expression that wants to use this address.
811
812 For Alpha, we have either a constant address or the sum of a
813 register and a constant address, or just a register. For DImode,
814 any of those forms can be surrounded with an AND that clear the
815 low-order three bits; this is an "unaligned" access. */
816
c6c3dba9
PB
817static bool
818alpha_legitimate_address_p (enum machine_mode mode, rtx x, bool strict)
a39bdefc
RH
819{
820 /* If this is an ldq_u type address, discard the outer AND. */
821 if (mode == DImode
822 && GET_CODE (x) == AND
7d83f4f5 823 && CONST_INT_P (XEXP (x, 1))
a39bdefc
RH
824 && INTVAL (XEXP (x, 1)) == -8)
825 x = XEXP (x, 0);
826
827 /* Discard non-paradoxical subregs. */
828 if (GET_CODE (x) == SUBREG
829 && (GET_MODE_SIZE (GET_MODE (x))
830 < GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))))
831 x = SUBREG_REG (x);
832
833 /* Unadorned general registers are valid. */
834 if (REG_P (x)
835 && (strict
836 ? STRICT_REG_OK_FOR_BASE_P (x)
837 : NONSTRICT_REG_OK_FOR_BASE_P (x)))
838 return true;
839
840 /* Constant addresses (i.e. +/- 32k) are valid. */
841 if (CONSTANT_ADDRESS_P (x))
842 return true;
843
1330f7d5
DR
844#if TARGET_ABI_OPEN_VMS
845 if (LINKAGE_SYMBOL_REF_P (x))
846 return true;
847#endif
848
a39bdefc
RH
849 /* Register plus a small constant offset is valid. */
850 if (GET_CODE (x) == PLUS)
851 {
852 rtx ofs = XEXP (x, 1);
853 x = XEXP (x, 0);
854
855 /* Discard non-paradoxical subregs. */
856 if (GET_CODE (x) == SUBREG
857 && (GET_MODE_SIZE (GET_MODE (x))
858 < GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))))
859 x = SUBREG_REG (x);
860
861 if (REG_P (x))
862 {
863 if (! strict
864 && NONSTRICT_REG_OK_FP_BASE_P (x)
7d83f4f5 865 && CONST_INT_P (ofs))
a39bdefc
RH
866 return true;
867 if ((strict
868 ? STRICT_REG_OK_FOR_BASE_P (x)
869 : NONSTRICT_REG_OK_FOR_BASE_P (x))
870 && CONSTANT_ADDRESS_P (ofs))
871 return true;
872 }
a39bdefc
RH
873 }
874
26d5bf5b
UB
875 /* If we're managing explicit relocations, LO_SUM is valid, as are small
876 data symbols. Avoid explicit relocations of modes larger than word
877 mode since i.e. $LC0+8($1) can fold around +/- 32k offset. */
878 else if (TARGET_EXPLICIT_RELOCS
879 && GET_MODE_SIZE (mode) <= UNITS_PER_WORD)
1eb356b9 880 {
551cc6fd 881 if (small_symbolic_operand (x, Pmode))
1eb356b9 882 return true;
551cc6fd
RH
883
884 if (GET_CODE (x) == LO_SUM)
885 {
886 rtx ofs = XEXP (x, 1);
887 x = XEXP (x, 0);
888
889 /* Discard non-paradoxical subregs. */
890 if (GET_CODE (x) == SUBREG
891 && (GET_MODE_SIZE (GET_MODE (x))
892 < GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))))
893 x = SUBREG_REG (x);
894
895 /* Must have a valid base register. */
896 if (! (REG_P (x)
897 && (strict
898 ? STRICT_REG_OK_FOR_BASE_P (x)
899 : NONSTRICT_REG_OK_FOR_BASE_P (x))))
900 return false;
901
902 /* The symbol must be local. */
6f9b006d
RH
903 if (local_symbolic_operand (ofs, Pmode)
904 || dtp32_symbolic_operand (ofs, Pmode)
905 || tp32_symbolic_operand (ofs, Pmode))
551cc6fd
RH
906 return true;
907 }
1eb356b9
RH
908 }
909
a39bdefc
RH
910 return false;
911}
912
d055668e
RH
913/* Build the SYMBOL_REF for __tls_get_addr. */
914
915static GTY(()) rtx tls_get_addr_libfunc;
916
917static rtx
a5c24926 918get_tls_get_addr (void)
d055668e
RH
919{
920 if (!tls_get_addr_libfunc)
921 tls_get_addr_libfunc = init_one_libfunc ("__tls_get_addr");
922 return tls_get_addr_libfunc;
923}
924
aead1ca3
RH
925/* Try machine-dependent ways of modifying an illegitimate address
926 to be legitimate. If we find one, return the new, valid address. */
927
506d7b68
PB
928static rtx
929alpha_legitimize_address_1 (rtx x, rtx scratch, enum machine_mode mode)
aead1ca3
RH
930{
931 HOST_WIDE_INT addend;
932
933 /* If the address is (plus reg const_int) and the CONST_INT is not a
934 valid offset, compute the high part of the constant and add it to
935 the register. Then our address is (plus temp low-part-const). */
936 if (GET_CODE (x) == PLUS
7d83f4f5
UB
937 && REG_P (XEXP (x, 0))
938 && CONST_INT_P (XEXP (x, 1))
aead1ca3
RH
939 && ! CONSTANT_ADDRESS_P (XEXP (x, 1)))
940 {
941 addend = INTVAL (XEXP (x, 1));
942 x = XEXP (x, 0);
943 goto split_addend;
944 }
945
946 /* If the address is (const (plus FOO const_int)), find the low-order
947 part of the CONST_INT. Then load FOO plus any high-order part of the
948 CONST_INT into a register. Our address is (plus reg low-part-const).
949 This is done to reduce the number of GOT entries. */
b3a13419 950 if (can_create_pseudo_p ()
551cc6fd 951 && GET_CODE (x) == CONST
aead1ca3 952 && GET_CODE (XEXP (x, 0)) == PLUS
7d83f4f5 953 && CONST_INT_P (XEXP (XEXP (x, 0), 1)))
aead1ca3
RH
954 {
955 addend = INTVAL (XEXP (XEXP (x, 0), 1));
956 x = force_reg (Pmode, XEXP (XEXP (x, 0), 0));
957 goto split_addend;
958 }
959
960 /* If we have a (plus reg const), emit the load as in (2), then add
961 the two registers, and finally generate (plus reg low-part-const) as
962 our address. */
b3a13419 963 if (can_create_pseudo_p ()
551cc6fd 964 && GET_CODE (x) == PLUS
7d83f4f5 965 && REG_P (XEXP (x, 0))
aead1ca3
RH
966 && GET_CODE (XEXP (x, 1)) == CONST
967 && GET_CODE (XEXP (XEXP (x, 1), 0)) == PLUS
7d83f4f5 968 && CONST_INT_P (XEXP (XEXP (XEXP (x, 1), 0), 1)))
aead1ca3
RH
969 {
970 addend = INTVAL (XEXP (XEXP (XEXP (x, 1), 0), 1));
971 x = expand_simple_binop (Pmode, PLUS, XEXP (x, 0),
972 XEXP (XEXP (XEXP (x, 1), 0), 0),
973 NULL_RTX, 1, OPTAB_LIB_WIDEN);
974 goto split_addend;
975 }
976
26d5bf5b
UB
977 /* If this is a local symbol, split the address into HIGH/LO_SUM parts.
978 Avoid modes larger than word mode since i.e. $LC0+8($1) can fold
979 around +/- 32k offset. */
980 if (TARGET_EXPLICIT_RELOCS
981 && GET_MODE_SIZE (mode) <= UNITS_PER_WORD
982 && symbolic_operand (x, Pmode))
1eb356b9 983 {
6f9b006d
RH
984 rtx r0, r16, eqv, tga, tp, insn, dest, seq;
985
986 switch (tls_symbolic_operand_type (x))
987 {
6cb718e4
RH
988 case TLS_MODEL_NONE:
989 break;
990
6f9b006d
RH
991 case TLS_MODEL_GLOBAL_DYNAMIC:
992 start_sequence ();
993
994 r0 = gen_rtx_REG (Pmode, 0);
995 r16 = gen_rtx_REG (Pmode, 16);
d055668e 996 tga = get_tls_get_addr ();
6f9b006d
RH
997 dest = gen_reg_rtx (Pmode);
998 seq = GEN_INT (alpha_next_sequence_number++);
f676971a 999
6f9b006d
RH
1000 emit_insn (gen_movdi_er_tlsgd (r16, pic_offset_table_rtx, x, seq));
1001 insn = gen_call_value_osf_tlsgd (r0, tga, seq);
1002 insn = emit_call_insn (insn);
becfd6e5 1003 RTL_CONST_CALL_P (insn) = 1;
6f9b006d
RH
1004 use_reg (&CALL_INSN_FUNCTION_USAGE (insn), r16);
1005
1006 insn = get_insns ();
1007 end_sequence ();
1008
1009 emit_libcall_block (insn, dest, r0, x);
1010 return dest;
1011
1012 case TLS_MODEL_LOCAL_DYNAMIC:
1013 start_sequence ();
1014
1015 r0 = gen_rtx_REG (Pmode, 0);
1016 r16 = gen_rtx_REG (Pmode, 16);
d055668e 1017 tga = get_tls_get_addr ();
6f9b006d
RH
1018 scratch = gen_reg_rtx (Pmode);
1019 seq = GEN_INT (alpha_next_sequence_number++);
1020
1021 emit_insn (gen_movdi_er_tlsldm (r16, pic_offset_table_rtx, seq));
1022 insn = gen_call_value_osf_tlsldm (r0, tga, seq);
1023 insn = emit_call_insn (insn);
becfd6e5 1024 RTL_CONST_CALL_P (insn) = 1;
6f9b006d
RH
1025 use_reg (&CALL_INSN_FUNCTION_USAGE (insn), r16);
1026
1027 insn = get_insns ();
1028 end_sequence ();
1029
1030 eqv = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx),
1031 UNSPEC_TLSLDM_CALL);
1032 emit_libcall_block (insn, scratch, r0, eqv);
1033
1034 eqv = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, x), UNSPEC_DTPREL);
1035 eqv = gen_rtx_CONST (Pmode, eqv);
1036
1037 if (alpha_tls_size == 64)
1038 {
1039 dest = gen_reg_rtx (Pmode);
1040 emit_insn (gen_rtx_SET (VOIDmode, dest, eqv));
1041 emit_insn (gen_adddi3 (dest, dest, scratch));
1042 return dest;
1043 }
1044 if (alpha_tls_size == 32)
1045 {
1046 insn = gen_rtx_HIGH (Pmode, eqv);
1047 insn = gen_rtx_PLUS (Pmode, scratch, insn);
1048 scratch = gen_reg_rtx (Pmode);
1049 emit_insn (gen_rtx_SET (VOIDmode, scratch, insn));
1050 }
1051 return gen_rtx_LO_SUM (Pmode, scratch, eqv);
1052
1053 case TLS_MODEL_INITIAL_EXEC:
1054 eqv = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, x), UNSPEC_TPREL);
1055 eqv = gen_rtx_CONST (Pmode, eqv);
1056 tp = gen_reg_rtx (Pmode);
1057 scratch = gen_reg_rtx (Pmode);
1058 dest = gen_reg_rtx (Pmode);
1059
1060 emit_insn (gen_load_tp (tp));
1061 emit_insn (gen_rtx_SET (VOIDmode, scratch, eqv));
1062 emit_insn (gen_adddi3 (dest, tp, scratch));
1063 return dest;
1064
1065 case TLS_MODEL_LOCAL_EXEC:
1066 eqv = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, x), UNSPEC_TPREL);
1067 eqv = gen_rtx_CONST (Pmode, eqv);
1068 tp = gen_reg_rtx (Pmode);
1069
1070 emit_insn (gen_load_tp (tp));
1071 if (alpha_tls_size == 32)
1072 {
1073 insn = gen_rtx_HIGH (Pmode, eqv);
1074 insn = gen_rtx_PLUS (Pmode, tp, insn);
1075 tp = gen_reg_rtx (Pmode);
1076 emit_insn (gen_rtx_SET (VOIDmode, tp, insn));
1077 }
1078 return gen_rtx_LO_SUM (Pmode, tp, eqv);
6cb718e4
RH
1079
1080 default:
1081 gcc_unreachable ();
6f9b006d
RH
1082 }
1083
e2c9fb9b
RH
1084 if (local_symbolic_operand (x, Pmode))
1085 {
1086 if (small_symbolic_operand (x, Pmode))
551cc6fd 1087 return x;
e2c9fb9b
RH
1088 else
1089 {
b3a13419 1090 if (can_create_pseudo_p ())
551cc6fd
RH
1091 scratch = gen_reg_rtx (Pmode);
1092 emit_insn (gen_rtx_SET (VOIDmode, scratch,
1093 gen_rtx_HIGH (Pmode, x)));
1094 return gen_rtx_LO_SUM (Pmode, scratch, x);
e2c9fb9b 1095 }
133d3133 1096 }
1eb356b9
RH
1097 }
1098
aead1ca3
RH
1099 return NULL;
1100
1101 split_addend:
1102 {
551cc6fd
RH
1103 HOST_WIDE_INT low, high;
1104
1105 low = ((addend & 0xffff) ^ 0x8000) - 0x8000;
1106 addend -= low;
1107 high = ((addend & 0xffffffff) ^ 0x80000000) - 0x80000000;
1108 addend -= high;
1109
1110 if (addend)
1111 x = expand_simple_binop (Pmode, PLUS, x, GEN_INT (addend),
b3a13419 1112 (!can_create_pseudo_p () ? scratch : NULL_RTX),
551cc6fd
RH
1113 1, OPTAB_LIB_WIDEN);
1114 if (high)
1115 x = expand_simple_binop (Pmode, PLUS, x, GEN_INT (high),
b3a13419 1116 (!can_create_pseudo_p () ? scratch : NULL_RTX),
551cc6fd
RH
1117 1, OPTAB_LIB_WIDEN);
1118
1119 return plus_constant (x, low);
aead1ca3
RH
1120 }
1121}
1122
506d7b68
PB
1123
1124/* Try machine-dependent ways of modifying an illegitimate address
1125 to be legitimate. Return X or the new, valid address. */
1126
1127static rtx
1128alpha_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
1129 enum machine_mode mode)
1130{
1131 rtx new_x = alpha_legitimize_address_1 (x, NULL_RTX, mode);
1132 return new_x ? new_x : x;
1133}
1134
04886dc0
RH
1135/* Primarily this is required for TLS symbols, but given that our move
1136 patterns *ought* to be able to handle any symbol at any time, we
1137 should never be spilling symbolic operands to the constant pool, ever. */
1138
1139static bool
1140alpha_cannot_force_const_mem (rtx x)
1141{
1142 enum rtx_code code = GET_CODE (x);
1143 return code == SYMBOL_REF || code == LABEL_REF || code == CONST;
1144}
1145
4977bab6 1146/* We do not allow indirect calls to be optimized into sibling calls, nor
3094247f
RH
1147 can we allow a call to a function with a different GP to be optimized
1148 into a sibcall. */
1149
4977bab6 1150static bool
a5c24926 1151alpha_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED)
4977bab6 1152{
3094247f
RH
1153 /* Can't do indirect tail calls, since we don't know if the target
1154 uses the same GP. */
1155 if (!decl)
1156 return false;
1157
1158 /* Otherwise, we can make a tail call if the target function shares
1159 the same GP. */
1160 return decl_has_samegp (decl);
4977bab6
ZW
1161}
1162
04161e2b
RH
1163int
1164some_small_symbolic_operand_int (rtx *px, void *data ATTRIBUTE_UNUSED)
1e7e480e
RH
1165{
1166 rtx x = *px;
551cc6fd 1167
a615ca3e
RH
1168 /* Don't re-split. */
1169 if (GET_CODE (x) == LO_SUM)
1170 return -1;
1e7e480e 1171
a615ca3e 1172 return small_symbolic_operand (x, Pmode) != 0;
551cc6fd
RH
1173}
1174
1e7e480e 1175static int
a5c24926 1176split_small_symbolic_operand_1 (rtx *px, void *data ATTRIBUTE_UNUSED)
1e7e480e
RH
1177{
1178 rtx x = *px;
51c561e3 1179
a615ca3e
RH
1180 /* Don't re-split. */
1181 if (GET_CODE (x) == LO_SUM)
1182 return -1;
551cc6fd 1183
1e7e480e
RH
1184 if (small_symbolic_operand (x, Pmode))
1185 {
1186 x = gen_rtx_LO_SUM (Pmode, pic_offset_table_rtx, x);
1187 *px = x;
a615ca3e 1188 return -1;
1e7e480e
RH
1189 }
1190
a615ca3e 1191 return 0;
551cc6fd
RH
1192}
1193
a5c24926
RH
1194rtx
1195split_small_symbolic_operand (rtx x)
1196{
1197 x = copy_insn (x);
1198 for_each_rtx (&x, split_small_symbolic_operand_1, NULL);
1199 return x;
1200}
1201
0b077eac
RH
1202/* Indicate that INSN cannot be duplicated. This is true for any insn
1203 that we've marked with gpdisp relocs, since those have to stay in
1204 1-1 correspondence with one another.
1205
093354e0 1206 Technically we could copy them if we could set up a mapping from one
0b077eac
RH
1207 sequence number to another, across the set of insns to be duplicated.
1208 This seems overly complicated and error-prone since interblock motion
501e79ef
RH
1209 from sched-ebb could move one of the pair of insns to a different block.
1210
1211 Also cannot allow jsr insns to be duplicated. If they throw exceptions,
1212 then they'll be in a different block from their ldgp. Which could lead
1213 the bb reorder code to think that it would be ok to copy just the block
1214 containing the call and branch to the block containing the ldgp. */
0b077eac
RH
1215
1216static bool
a5c24926 1217alpha_cannot_copy_insn_p (rtx insn)
0b077eac 1218{
0b077eac
RH
1219 if (!reload_completed || !TARGET_EXPLICIT_RELOCS)
1220 return false;
501e79ef
RH
1221 if (recog_memoized (insn) >= 0)
1222 return get_attr_cannot_copy (insn);
1223 else
0b077eac 1224 return false;
0b077eac
RH
1225}
1226
f676971a 1227
aead1ca3
RH
1228/* Try a machine-dependent way of reloading an illegitimate address
1229 operand. If we find one, push the reload and return the new rtx. */
f676971a 1230
aead1ca3 1231rtx
a5c24926
RH
1232alpha_legitimize_reload_address (rtx x,
1233 enum machine_mode mode ATTRIBUTE_UNUSED,
1234 int opnum, int type,
1235 int ind_levels ATTRIBUTE_UNUSED)
aead1ca3
RH
1236{
1237 /* We must recognize output that we have already generated ourselves. */
1238 if (GET_CODE (x) == PLUS
1239 && GET_CODE (XEXP (x, 0)) == PLUS
7d83f4f5
UB
1240 && REG_P (XEXP (XEXP (x, 0), 0))
1241 && CONST_INT_P (XEXP (XEXP (x, 0), 1))
1242 && CONST_INT_P (XEXP (x, 1)))
aead1ca3
RH
1243 {
1244 push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL,
1245 BASE_REG_CLASS, GET_MODE (x), VOIDmode, 0, 0,
bf758008 1246 opnum, (enum reload_type) type);
aead1ca3
RH
1247 return x;
1248 }
1249
1250 /* We wish to handle large displacements off a base register by
1251 splitting the addend across an ldah and the mem insn. This
1252 cuts number of extra insns needed from 3 to 1. */
1253 if (GET_CODE (x) == PLUS
7d83f4f5 1254 && REG_P (XEXP (x, 0))
aead1ca3
RH
1255 && REGNO (XEXP (x, 0)) < FIRST_PSEUDO_REGISTER
1256 && REGNO_OK_FOR_BASE_P (REGNO (XEXP (x, 0)))
1257 && GET_CODE (XEXP (x, 1)) == CONST_INT)
1258 {
1259 HOST_WIDE_INT val = INTVAL (XEXP (x, 1));
1260 HOST_WIDE_INT low = ((val & 0xffff) ^ 0x8000) - 0x8000;
1261 HOST_WIDE_INT high
1262 = (((val - low) & 0xffffffff) ^ 0x80000000) - 0x80000000;
1263
1264 /* Check for 32-bit overflow. */
1265 if (high + low != val)
1266 return NULL_RTX;
1267
1268 /* Reload the high part into a base reg; leave the low part
1269 in the mem directly. */
1270 x = gen_rtx_PLUS (GET_MODE (x),
1271 gen_rtx_PLUS (GET_MODE (x), XEXP (x, 0),
1272 GEN_INT (high)),
1273 GEN_INT (low));
1274
1275 push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL,
1276 BASE_REG_CLASS, GET_MODE (x), VOIDmode, 0, 0,
bf758008 1277 opnum, (enum reload_type) type);
aead1ca3
RH
1278 return x;
1279 }
1280
1281 return NULL_RTX;
1282}
1283\f
3c50106f
RH
1284/* Compute a (partial) cost for rtx X. Return true if the complete
1285 cost has been computed, and false if subexpressions should be
1286 scanned. In either case, *TOTAL contains the cost result. */
1287
1288static bool
f40751dd
JH
1289alpha_rtx_costs (rtx x, int code, int outer_code, int *total,
1290 bool speed)
3c50106f
RH
1291{
1292 enum machine_mode mode = GET_MODE (x);
1293 bool float_mode_p = FLOAT_MODE_P (mode);
8260c194
RH
1294 const struct alpha_rtx_cost_data *cost_data;
1295
f40751dd 1296 if (!speed)
8260c194
RH
1297 cost_data = &alpha_rtx_cost_size;
1298 else
8bea7f7c 1299 cost_data = &alpha_rtx_cost_data[alpha_tune];
3c50106f
RH
1300
1301 switch (code)
1302 {
8260c194 1303 case CONST_INT:
3c50106f
RH
1304 /* If this is an 8-bit constant, return zero since it can be used
1305 nearly anywhere with no cost. If it is a valid operand for an
1306 ADD or AND, likewise return 0 if we know it will be used in that
1307 context. Otherwise, return 2 since it might be used there later.
1308 All other constants take at least two insns. */
3c50106f
RH
1309 if (INTVAL (x) >= 0 && INTVAL (x) < 256)
1310 {
1311 *total = 0;
1312 return true;
1313 }
5efb1046 1314 /* FALLTHRU */
3c50106f
RH
1315
1316 case CONST_DOUBLE:
1317 if (x == CONST0_RTX (mode))
1318 *total = 0;
1319 else if ((outer_code == PLUS && add_operand (x, VOIDmode))
1320 || (outer_code == AND && and_operand (x, VOIDmode)))
1321 *total = 0;
1322 else if (add_operand (x, VOIDmode) || and_operand (x, VOIDmode))
1323 *total = 2;
1324 else
1325 *total = COSTS_N_INSNS (2);
1326 return true;
f676971a 1327
3c50106f
RH
1328 case CONST:
1329 case SYMBOL_REF:
1330 case LABEL_REF:
1331 if (TARGET_EXPLICIT_RELOCS && small_symbolic_operand (x, VOIDmode))
1332 *total = COSTS_N_INSNS (outer_code != MEM);
1333 else if (TARGET_EXPLICIT_RELOCS && local_symbolic_operand (x, VOIDmode))
1334 *total = COSTS_N_INSNS (1 + (outer_code != MEM));
1335 else if (tls_symbolic_operand_type (x))
1336 /* Estimate of cost for call_pal rduniq. */
8260c194 1337 /* ??? How many insns do we emit here? More than one... */
3c50106f
RH
1338 *total = COSTS_N_INSNS (15);
1339 else
1340 /* Otherwise we do a load from the GOT. */
f40751dd 1341 *total = COSTS_N_INSNS (!speed ? 1 : alpha_memory_latency);
3c50106f 1342 return true;
f676971a 1343
72910a0b
RH
1344 case HIGH:
1345 /* This is effectively an add_operand. */
1346 *total = 2;
1347 return true;
1348
3c50106f
RH
1349 case PLUS:
1350 case MINUS:
1351 if (float_mode_p)
8260c194 1352 *total = cost_data->fp_add;
3c50106f
RH
1353 else if (GET_CODE (XEXP (x, 0)) == MULT
1354 && const48_operand (XEXP (XEXP (x, 0), 1), VOIDmode))
1355 {
bf758008
UB
1356 *total = (rtx_cost (XEXP (XEXP (x, 0), 0),
1357 (enum rtx_code) outer_code, speed)
1358 + rtx_cost (XEXP (x, 1),
1359 (enum rtx_code) outer_code, speed)
1360 + COSTS_N_INSNS (1));
3c50106f
RH
1361 return true;
1362 }
1363 return false;
1364
1365 case MULT:
1366 if (float_mode_p)
8260c194 1367 *total = cost_data->fp_mult;
3c50106f 1368 else if (mode == DImode)
8260c194 1369 *total = cost_data->int_mult_di;
3c50106f 1370 else
8260c194 1371 *total = cost_data->int_mult_si;
3c50106f
RH
1372 return false;
1373
1374 case ASHIFT:
7d83f4f5 1375 if (CONST_INT_P (XEXP (x, 1))
3c50106f
RH
1376 && INTVAL (XEXP (x, 1)) <= 3)
1377 {
1378 *total = COSTS_N_INSNS (1);
1379 return false;
1380 }
5efb1046 1381 /* FALLTHRU */
3c50106f
RH
1382
1383 case ASHIFTRT:
1384 case LSHIFTRT:
8260c194 1385 *total = cost_data->int_shift;
3c50106f
RH
1386 return false;
1387
1388 case IF_THEN_ELSE:
1389 if (float_mode_p)
8260c194 1390 *total = cost_data->fp_add;
3c50106f 1391 else
8260c194 1392 *total = cost_data->int_cmov;
3c50106f
RH
1393 return false;
1394
1395 case DIV:
1396 case UDIV:
1397 case MOD:
1398 case UMOD:
1399 if (!float_mode_p)
8260c194 1400 *total = cost_data->int_div;
3c50106f 1401 else if (mode == SFmode)
8260c194 1402 *total = cost_data->fp_div_sf;
3c50106f 1403 else
8260c194 1404 *total = cost_data->fp_div_df;
3c50106f
RH
1405 return false;
1406
1407 case MEM:
f40751dd 1408 *total = COSTS_N_INSNS (!speed ? 1 : alpha_memory_latency);
3c50106f
RH
1409 return true;
1410
1411 case NEG:
1412 if (! float_mode_p)
1413 {
1414 *total = COSTS_N_INSNS (1);
1415 return false;
1416 }
5efb1046 1417 /* FALLTHRU */
3c50106f
RH
1418
1419 case ABS:
1420 if (! float_mode_p)
1421 {
8260c194 1422 *total = COSTS_N_INSNS (1) + cost_data->int_cmov;
3c50106f
RH
1423 return false;
1424 }
5efb1046 1425 /* FALLTHRU */
3c50106f
RH
1426
1427 case FLOAT:
1428 case UNSIGNED_FLOAT:
1429 case FIX:
1430 case UNSIGNED_FIX:
3c50106f 1431 case FLOAT_TRUNCATE:
8260c194 1432 *total = cost_data->fp_add;
3c50106f
RH
1433 return false;
1434
a220ee34 1435 case FLOAT_EXTEND:
7d83f4f5 1436 if (MEM_P (XEXP (x, 0)))
a220ee34
RH
1437 *total = 0;
1438 else
1439 *total = cost_data->fp_add;
1440 return false;
1441
3c50106f
RH
1442 default:
1443 return false;
1444 }
1445}
1446\f
a6f12d7c
RK
1447/* REF is an alignable memory location. Place an aligned SImode
1448 reference into *PALIGNED_MEM and the number of bits to shift into
96043e7e
RH
1449 *PBITNUM. SCRATCH is a free register for use in reloading out
1450 of range stack slots. */
a6f12d7c
RK
1451
1452void
a5c24926 1453get_aligned_mem (rtx ref, rtx *paligned_mem, rtx *pbitnum)
a6f12d7c
RK
1454{
1455 rtx base;
525e67c1 1456 HOST_WIDE_INT disp, offset;
a6f12d7c 1457
7d83f4f5 1458 gcc_assert (MEM_P (ref));
a6f12d7c 1459
4e46365b
RH
1460 if (reload_in_progress
1461 && ! memory_address_p (GET_MODE (ref), XEXP (ref, 0)))
96043e7e 1462 {
4e46365b 1463 base = find_replacement (&XEXP (ref, 0));
56daab84 1464 gcc_assert (memory_address_p (GET_MODE (ref), base));
96043e7e 1465 }
a6f12d7c 1466 else
56daab84 1467 base = XEXP (ref, 0);
a6f12d7c
RK
1468
1469 if (GET_CODE (base) == PLUS)
525e67c1
RH
1470 disp = INTVAL (XEXP (base, 1)), base = XEXP (base, 0);
1471 else
1472 disp = 0;
1473
1474 /* Find the byte offset within an aligned word. If the memory itself is
1475 claimed to be aligned, believe it. Otherwise, aligned_memory_operand
1476 will have examined the base register and determined it is aligned, and
1477 thus displacements from it are naturally alignable. */
1478 if (MEM_ALIGN (ref) >= 32)
1479 offset = 0;
1480 else
1481 offset = disp & 3;
a6f12d7c 1482
02143d0b
UB
1483 /* The location should not cross aligned word boundary. */
1484 gcc_assert (offset + GET_MODE_SIZE (GET_MODE (ref))
1485 <= GET_MODE_SIZE (SImode));
1486
525e67c1
RH
1487 /* Access the entire aligned word. */
1488 *paligned_mem = widen_memory_access (ref, SImode, -offset);
a6f12d7c 1489
525e67c1 1490 /* Convert the byte offset within the word to a bit offset. */
30102605 1491 if (WORDS_BIG_ENDIAN)
525e67c1 1492 offset = 32 - (GET_MODE_BITSIZE (GET_MODE (ref)) + offset * 8);
30102605 1493 else
525e67c1
RH
1494 offset *= 8;
1495 *pbitnum = GEN_INT (offset);
a6f12d7c
RK
1496}
1497
f676971a 1498/* Similar, but just get the address. Handle the two reload cases.
adb18b68 1499 Add EXTRA_OFFSET to the address we return. */
a6f12d7c
RK
1500
1501rtx
60e93525 1502get_unaligned_address (rtx ref)
a6f12d7c
RK
1503{
1504 rtx base;
1505 HOST_WIDE_INT offset = 0;
1506
7d83f4f5 1507 gcc_assert (MEM_P (ref));
a6f12d7c 1508
4e46365b
RH
1509 if (reload_in_progress
1510 && ! memory_address_p (GET_MODE (ref), XEXP (ref, 0)))
96043e7e 1511 {
96043e7e 1512 base = find_replacement (&XEXP (ref, 0));
4e46365b 1513
56daab84 1514 gcc_assert (memory_address_p (GET_MODE (ref), base));
96043e7e 1515 }
a6f12d7c 1516 else
56daab84 1517 base = XEXP (ref, 0);
a6f12d7c
RK
1518
1519 if (GET_CODE (base) == PLUS)
1520 offset += INTVAL (XEXP (base, 1)), base = XEXP (base, 0);
1521
60e93525
RH
1522 return plus_constant (base, offset);
1523}
1524
1525/* Compute a value X, such that X & 7 == (ADDR + OFS) & 7.
1526 X is always returned in a register. */
1527
1528rtx
1529get_unaligned_offset (rtx addr, HOST_WIDE_INT ofs)
1530{
1531 if (GET_CODE (addr) == PLUS)
1532 {
1533 ofs += INTVAL (XEXP (addr, 1));
1534 addr = XEXP (addr, 0);
1535 }
1536
1537 return expand_simple_binop (Pmode, PLUS, addr, GEN_INT (ofs & 7),
1538 NULL_RTX, 1, OPTAB_LIB_WIDEN);
a6f12d7c 1539}
3611aef0 1540
551cc6fd 1541/* On the Alpha, all (non-symbolic) constants except zero go into
f676971a 1542 a floating-point register via memory. Note that we cannot
0a2aaacc 1543 return anything that is not a subset of RCLASS, and that some
551cc6fd
RH
1544 symbolic constants cannot be dropped to memory. */
1545
1546enum reg_class
0a2aaacc 1547alpha_preferred_reload_class(rtx x, enum reg_class rclass)
551cc6fd
RH
1548{
1549 /* Zero is present in any register class. */
1550 if (x == CONST0_RTX (GET_MODE (x)))
0a2aaacc 1551 return rclass;
551cc6fd
RH
1552
1553 /* These sorts of constants we can easily drop to memory. */
7d83f4f5 1554 if (CONST_INT_P (x)
72910a0b
RH
1555 || GET_CODE (x) == CONST_DOUBLE
1556 || GET_CODE (x) == CONST_VECTOR)
551cc6fd 1557 {
0a2aaacc 1558 if (rclass == FLOAT_REGS)
551cc6fd 1559 return NO_REGS;
0a2aaacc 1560 if (rclass == ALL_REGS)
551cc6fd 1561 return GENERAL_REGS;
0a2aaacc 1562 return rclass;
551cc6fd
RH
1563 }
1564
1565 /* All other kinds of constants should not (and in the case of HIGH
1566 cannot) be dropped to memory -- instead we use a GENERAL_REGS
1567 secondary reload. */
1568 if (CONSTANT_P (x))
0a2aaacc 1569 return (rclass == ALL_REGS ? GENERAL_REGS : rclass);
551cc6fd 1570
0a2aaacc 1571 return rclass;
551cc6fd
RH
1572}
1573
48f46219 1574/* Inform reload about cases where moving X with a mode MODE to a register in
0a2aaacc 1575 RCLASS requires an extra scratch or immediate register. Return the class
48f46219 1576 needed for the immediate register. */
3611aef0 1577
a87cf97e
JR
1578static reg_class_t
1579alpha_secondary_reload (bool in_p, rtx x, reg_class_t rclass_i,
48f46219 1580 enum machine_mode mode, secondary_reload_info *sri)
3611aef0 1581{
a87cf97e
JR
1582 enum reg_class rclass = (enum reg_class) rclass_i;
1583
48f46219
RH
1584 /* Loading and storing HImode or QImode values to and from memory
1585 usually requires a scratch register. */
1586 if (!TARGET_BWX && (mode == QImode || mode == HImode || mode == CQImode))
35a414df 1587 {
48f46219 1588 if (any_memory_operand (x, mode))
35a414df 1589 {
48f46219
RH
1590 if (in_p)
1591 {
1592 if (!aligned_memory_operand (x, mode))
f9621cc4 1593 sri->icode = direct_optab_handler (reload_in_optab, mode);
48f46219
RH
1594 }
1595 else
f9621cc4 1596 sri->icode = direct_optab_handler (reload_out_optab, mode);
48f46219 1597 return NO_REGS;
35a414df
RH
1598 }
1599 }
3611aef0 1600
48f46219
RH
1601 /* We also cannot do integral arithmetic into FP regs, as might result
1602 from register elimination into a DImode fp register. */
0a2aaacc 1603 if (rclass == FLOAT_REGS)
3611aef0 1604 {
48f46219 1605 if (MEM_P (x) && GET_CODE (XEXP (x, 0)) == AND)
3611aef0 1606 return GENERAL_REGS;
48f46219
RH
1607 if (in_p && INTEGRAL_MODE_P (mode)
1608 && !MEM_P (x) && !REG_P (x) && !CONST_INT_P (x))
3611aef0
RH
1609 return GENERAL_REGS;
1610 }
1611
1612 return NO_REGS;
1613}
a6f12d7c
RK
1614\f
1615/* Subfunction of the following function. Update the flags of any MEM
1616 found in part of X. */
1617
389fdba0
RH
1618static int
1619alpha_set_memflags_1 (rtx *xp, void *data)
a6f12d7c 1620{
389fdba0 1621 rtx x = *xp, orig = (rtx) data;
a6f12d7c 1622
7d83f4f5 1623 if (!MEM_P (x))
389fdba0 1624 return 0;
a6f12d7c 1625
389fdba0
RH
1626 MEM_VOLATILE_P (x) = MEM_VOLATILE_P (orig);
1627 MEM_IN_STRUCT_P (x) = MEM_IN_STRUCT_P (orig);
1628 MEM_SCALAR_P (x) = MEM_SCALAR_P (orig);
1629 MEM_NOTRAP_P (x) = MEM_NOTRAP_P (orig);
1630 MEM_READONLY_P (x) = MEM_READONLY_P (orig);
a6f12d7c 1631
389fdba0
RH
1632 /* Sadly, we cannot use alias sets because the extra aliasing
1633 produced by the AND interferes. Given that two-byte quantities
1634 are the only thing we would be able to differentiate anyway,
1635 there does not seem to be any point in convoluting the early
1636 out of the alias check. */
1d300e19 1637
389fdba0 1638 return -1;
a6f12d7c
RK
1639}
1640
13a4e577 1641/* Given SEQ, which is an INSN list, look for any MEMs in either
2f937369
DM
1642 a SET_DEST or a SET_SRC and copy the in-struct, unchanging, and
1643 volatile flags from REF into each of the MEMs found. If REF is not
1644 a MEM, don't do anything. */
a6f12d7c
RK
1645
1646void
13a4e577 1647alpha_set_memflags (rtx seq, rtx ref)
a6f12d7c 1648{
13a4e577 1649 rtx insn;
3873d24b 1650
13a4e577 1651 if (!MEM_P (ref))
a6f12d7c
RK
1652 return;
1653
f676971a 1654 /* This is only called from alpha.md, after having had something
3873d24b
RH
1655 generated from one of the insn patterns. So if everything is
1656 zero, the pattern is already up-to-date. */
389fdba0
RH
1657 if (!MEM_VOLATILE_P (ref)
1658 && !MEM_IN_STRUCT_P (ref)
1659 && !MEM_SCALAR_P (ref)
1660 && !MEM_NOTRAP_P (ref)
1661 && !MEM_READONLY_P (ref))
3873d24b
RH
1662 return;
1663
13a4e577
UB
1664 for (insn = seq; insn; insn = NEXT_INSN (insn))
1665 if (INSN_P (insn))
1666 for_each_rtx (&PATTERN (insn), alpha_set_memflags_1, (void *) ref);
1667 else
1668 gcc_unreachable ();
a6f12d7c
RK
1669}
1670\f
72910a0b
RH
1671static rtx alpha_emit_set_const (rtx, enum machine_mode, HOST_WIDE_INT,
1672 int, bool);
1673
1674/* Internal routine for alpha_emit_set_const to check for N or below insns.
1675 If NO_OUTPUT is true, then we only check to see if N insns are possible,
1676 and return pc_rtx if successful. */
9102cd1f
RK
1677
1678static rtx
a5c24926 1679alpha_emit_set_const_1 (rtx target, enum machine_mode mode,
72910a0b 1680 HOST_WIDE_INT c, int n, bool no_output)
a6f12d7c 1681{
0a2aaacc 1682 HOST_WIDE_INT new_const;
a6f12d7c 1683 int i, bits;
fd94addf
RK
1684 /* Use a pseudo if highly optimizing and still generating RTL. */
1685 rtx subtarget
b3a13419 1686 = (flag_expensive_optimizations && can_create_pseudo_p () ? 0 : target);
b83b7fa3 1687 rtx temp, insn;
a6f12d7c 1688
a6f12d7c
RK
1689 /* If this is a sign-extended 32-bit constant, we can do this in at most
1690 three insns, so do it if we have enough insns left. We always have
285a5742 1691 a sign-extended 32-bit constant when compiling on a narrow machine. */
a6f12d7c 1692
858e4e8c
RH
1693 if (HOST_BITS_PER_WIDE_INT != 64
1694 || c >> 31 == -1 || c >> 31 == 0)
a6f12d7c 1695 {
20a4db98 1696 HOST_WIDE_INT low = ((c & 0xffff) ^ 0x8000) - 0x8000;
a6f12d7c 1697 HOST_WIDE_INT tmp1 = c - low;
20a4db98 1698 HOST_WIDE_INT high = (((tmp1 >> 16) & 0xffff) ^ 0x8000) - 0x8000;
a6f12d7c
RK
1699 HOST_WIDE_INT extra = 0;
1700
ab034cfc
RK
1701 /* If HIGH will be interpreted as negative but the constant is
1702 positive, we must adjust it to do two ldha insns. */
1703
1704 if ((high & 0x8000) != 0 && c >= 0)
a6f12d7c
RK
1705 {
1706 extra = 0x4000;
1707 tmp1 -= 0x40000000;
1708 high = ((tmp1 >> 16) & 0xffff) - 2 * ((tmp1 >> 16) & 0x8000);
1709 }
1710
1711 if (c == low || (low == 0 && extra == 0))
858e4e8c
RH
1712 {
1713 /* We used to use copy_to_suggested_reg (GEN_INT (c), target, mode)
1714 but that meant that we can't handle INT_MIN on 32-bit machines
f676971a 1715 (like NT/Alpha), because we recurse indefinitely through
858e4e8c
RH
1716 emit_move_insn to gen_movdi. So instead, since we know exactly
1717 what we want, create it explicitly. */
1718
72910a0b
RH
1719 if (no_output)
1720 return pc_rtx;
858e4e8c
RH
1721 if (target == NULL)
1722 target = gen_reg_rtx (mode);
38a448ca 1723 emit_insn (gen_rtx_SET (VOIDmode, target, GEN_INT (c)));
858e4e8c
RH
1724 return target;
1725 }
9102cd1f 1726 else if (n >= 2 + (extra != 0))
a6f12d7c 1727 {
72910a0b
RH
1728 if (no_output)
1729 return pc_rtx;
b3a13419 1730 if (!can_create_pseudo_p ())
c3cda381
FH
1731 {
1732 emit_insn (gen_rtx_SET (VOIDmode, target, GEN_INT (high << 16)));
1733 temp = target;
1734 }
1735 else
1736 temp = copy_to_suggested_reg (GEN_INT (high << 16),
1737 subtarget, mode);
fd94addf 1738
b83b7fa3
RH
1739 /* As of 2002-02-23, addsi3 is only available when not optimizing.
1740 This means that if we go through expand_binop, we'll try to
1741 generate extensions, etc, which will require new pseudos, which
1742 will fail during some split phases. The SImode add patterns
1743 still exist, but are not named. So build the insns by hand. */
1744
a6f12d7c 1745 if (extra != 0)
b83b7fa3
RH
1746 {
1747 if (! subtarget)
1748 subtarget = gen_reg_rtx (mode);
1749 insn = gen_rtx_PLUS (mode, temp, GEN_INT (extra << 16));
1750 insn = gen_rtx_SET (VOIDmode, subtarget, insn);
1751 emit_insn (insn);
1ef9531b 1752 temp = subtarget;
b83b7fa3 1753 }
a6f12d7c 1754
b83b7fa3
RH
1755 if (target == NULL)
1756 target = gen_reg_rtx (mode);
1757 insn = gen_rtx_PLUS (mode, temp, GEN_INT (low));
1758 insn = gen_rtx_SET (VOIDmode, target, insn);
1759 emit_insn (insn);
1760 return target;
a6f12d7c
RK
1761 }
1762 }
1763
0af3ee30 1764 /* If we couldn't do it that way, try some other methods. But if we have
f444f304
RK
1765 no instructions left, don't bother. Likewise, if this is SImode and
1766 we can't make pseudos, we can't do anything since the expand_binop
1767 and expand_unop calls will widen and try to make pseudos. */
a6f12d7c 1768
b3a13419 1769 if (n == 1 || (mode == SImode && !can_create_pseudo_p ()))
a6f12d7c
RK
1770 return 0;
1771
0af3ee30 1772 /* Next, see if we can load a related constant and then shift and possibly
a6f12d7c
RK
1773 negate it to get the constant we want. Try this once each increasing
1774 numbers of insns. */
1775
1776 for (i = 1; i < n; i++)
1777 {
20a4db98
RH
1778 /* First, see if minus some low bits, we've an easy load of
1779 high bits. */
1780
0a2aaacc
KG
1781 new_const = ((c & 0xffff) ^ 0x8000) - 0x8000;
1782 if (new_const != 0)
72910a0b 1783 {
0a2aaacc 1784 temp = alpha_emit_set_const (subtarget, mode, c - new_const, i, no_output);
72910a0b
RH
1785 if (temp)
1786 {
1787 if (no_output)
1788 return temp;
0a2aaacc 1789 return expand_binop (mode, add_optab, temp, GEN_INT (new_const),
72910a0b
RH
1790 target, 0, OPTAB_WIDEN);
1791 }
1792 }
20a4db98
RH
1793
1794 /* Next try complementing. */
72910a0b
RH
1795 temp = alpha_emit_set_const (subtarget, mode, ~c, i, no_output);
1796 if (temp)
1797 {
1798 if (no_output)
1799 return temp;
1800 return expand_unop (mode, one_cmpl_optab, temp, target, 0);
1801 }
a6f12d7c 1802
fd94addf 1803 /* Next try to form a constant and do a left shift. We can do this
a6f12d7c
RK
1804 if some low-order bits are zero; the exact_log2 call below tells
1805 us that information. The bits we are shifting out could be any
1806 value, but here we'll just try the 0- and sign-extended forms of
1807 the constant. To try to increase the chance of having the same
1808 constant in more than one insn, start at the highest number of
1809 bits to shift, but try all possibilities in case a ZAPNOT will
1810 be useful. */
1811
72910a0b
RH
1812 bits = exact_log2 (c & -c);
1813 if (bits > 0)
a6f12d7c 1814 for (; bits > 0; bits--)
72910a0b 1815 {
0a2aaacc
KG
1816 new_const = c >> bits;
1817 temp = alpha_emit_set_const (subtarget, mode, new_const, i, no_output);
72910a0b
RH
1818 if (!temp && c < 0)
1819 {
0a2aaacc
KG
1820 new_const = (unsigned HOST_WIDE_INT)c >> bits;
1821 temp = alpha_emit_set_const (subtarget, mode, new_const,
72910a0b
RH
1822 i, no_output);
1823 }
1824 if (temp)
1825 {
1826 if (no_output)
1827 return temp;
1828 return expand_binop (mode, ashl_optab, temp, GEN_INT (bits),
1829 target, 0, OPTAB_WIDEN);
1830 }
1831 }
a6f12d7c
RK
1832
1833 /* Now try high-order zero bits. Here we try the shifted-in bits as
57cfde96
RK
1834 all zero and all ones. Be careful to avoid shifting outside the
1835 mode and to avoid shifting outside the host wide int size. */
858e4e8c
RH
1836 /* On narrow hosts, don't shift a 1 into the high bit, since we'll
1837 confuse the recursive call and set all of the high 32 bits. */
a6f12d7c 1838
72910a0b
RH
1839 bits = (MIN (HOST_BITS_PER_WIDE_INT, GET_MODE_SIZE (mode) * 8)
1840 - floor_log2 (c) - 1 - (HOST_BITS_PER_WIDE_INT < 64));
1841 if (bits > 0)
a6f12d7c 1842 for (; bits > 0; bits--)
72910a0b 1843 {
0a2aaacc
KG
1844 new_const = c << bits;
1845 temp = alpha_emit_set_const (subtarget, mode, new_const, i, no_output);
72910a0b
RH
1846 if (!temp)
1847 {
0a2aaacc
KG
1848 new_const = (c << bits) | (((HOST_WIDE_INT) 1 << bits) - 1);
1849 temp = alpha_emit_set_const (subtarget, mode, new_const,
72910a0b
RH
1850 i, no_output);
1851 }
1852 if (temp)
1853 {
1854 if (no_output)
1855 return temp;
1856 return expand_binop (mode, lshr_optab, temp, GEN_INT (bits),
1857 target, 1, OPTAB_WIDEN);
1858 }
1859 }
a6f12d7c
RK
1860
1861 /* Now try high-order 1 bits. We get that with a sign-extension.
57cfde96 1862 But one bit isn't enough here. Be careful to avoid shifting outside
285a5742 1863 the mode and to avoid shifting outside the host wide int size. */
30102605 1864
72910a0b
RH
1865 bits = (MIN (HOST_BITS_PER_WIDE_INT, GET_MODE_SIZE (mode) * 8)
1866 - floor_log2 (~ c) - 2);
1867 if (bits > 0)
a6f12d7c 1868 for (; bits > 0; bits--)
72910a0b 1869 {
0a2aaacc
KG
1870 new_const = c << bits;
1871 temp = alpha_emit_set_const (subtarget, mode, new_const, i, no_output);
72910a0b
RH
1872 if (!temp)
1873 {
0a2aaacc
KG
1874 new_const = (c << bits) | (((HOST_WIDE_INT) 1 << bits) - 1);
1875 temp = alpha_emit_set_const (subtarget, mode, new_const,
72910a0b
RH
1876 i, no_output);
1877 }
1878 if (temp)
1879 {
1880 if (no_output)
1881 return temp;
1882 return expand_binop (mode, ashr_optab, temp, GEN_INT (bits),
1883 target, 0, OPTAB_WIDEN);
1884 }
1885 }
a6f12d7c
RK
1886 }
1887
20a4db98
RH
1888#if HOST_BITS_PER_WIDE_INT == 64
1889 /* Finally, see if can load a value into the target that is the same as the
1890 constant except that all bytes that are 0 are changed to be 0xff. If we
1891 can, then we can do a ZAPNOT to obtain the desired constant. */
1892
0a2aaacc 1893 new_const = c;
20a4db98 1894 for (i = 0; i < 64; i += 8)
0a2aaacc
KG
1895 if ((new_const & ((HOST_WIDE_INT) 0xff << i)) == 0)
1896 new_const |= (HOST_WIDE_INT) 0xff << i;
e68c380c 1897
20a4db98
RH
1898 /* We are only called for SImode and DImode. If this is SImode, ensure that
1899 we are sign extended to a full word. */
1900
1901 if (mode == SImode)
0a2aaacc 1902 new_const = ((new_const & 0xffffffff) ^ 0x80000000) - 0x80000000;
20a4db98 1903
0a2aaacc 1904 if (new_const != c)
72910a0b 1905 {
0a2aaacc 1906 temp = alpha_emit_set_const (subtarget, mode, new_const, n - 1, no_output);
72910a0b
RH
1907 if (temp)
1908 {
1909 if (no_output)
1910 return temp;
0a2aaacc 1911 return expand_binop (mode, and_optab, temp, GEN_INT (c | ~ new_const),
72910a0b
RH
1912 target, 0, OPTAB_WIDEN);
1913 }
1914 }
20a4db98 1915#endif
e68c380c 1916
a6f12d7c
RK
1917 return 0;
1918}
758d2c0c 1919
a5c24926
RH
1920/* Try to output insns to set TARGET equal to the constant C if it can be
1921 done in less than N insns. Do all computations in MODE. Returns the place
1922 where the output has been placed if it can be done and the insns have been
1923 emitted. If it would take more than N insns, zero is returned and no
1924 insns and emitted. */
1925
72910a0b 1926static rtx
a5c24926 1927alpha_emit_set_const (rtx target, enum machine_mode mode,
72910a0b 1928 HOST_WIDE_INT c, int n, bool no_output)
a5c24926 1929{
72910a0b 1930 enum machine_mode orig_mode = mode;
a5c24926 1931 rtx orig_target = target;
72910a0b 1932 rtx result = 0;
a5c24926
RH
1933 int i;
1934
1935 /* If we can't make any pseudos, TARGET is an SImode hard register, we
1936 can't load this constant in one insn, do this in DImode. */
b3a13419 1937 if (!can_create_pseudo_p () && mode == SImode
7d83f4f5 1938 && REG_P (target) && REGNO (target) < FIRST_PSEUDO_REGISTER)
a5c24926 1939 {
72910a0b
RH
1940 result = alpha_emit_set_const_1 (target, mode, c, 1, no_output);
1941 if (result)
1942 return result;
1943
1944 target = no_output ? NULL : gen_lowpart (DImode, target);
1945 mode = DImode;
1946 }
1947 else if (mode == V8QImode || mode == V4HImode || mode == V2SImode)
1948 {
1949 target = no_output ? NULL : gen_lowpart (DImode, target);
a5c24926
RH
1950 mode = DImode;
1951 }
1952
1953 /* Try 1 insn, then 2, then up to N. */
1954 for (i = 1; i <= n; i++)
1955 {
72910a0b 1956 result = alpha_emit_set_const_1 (target, mode, c, i, no_output);
a5c24926
RH
1957 if (result)
1958 {
72910a0b
RH
1959 rtx insn, set;
1960
1961 if (no_output)
1962 return result;
1963
1964 insn = get_last_insn ();
1965 set = single_set (insn);
a5c24926
RH
1966 if (! CONSTANT_P (SET_SRC (set)))
1967 set_unique_reg_note (get_last_insn (), REG_EQUAL, GEN_INT (c));
1968 break;
1969 }
1970 }
1971
1972 /* Allow for the case where we changed the mode of TARGET. */
72910a0b
RH
1973 if (result)
1974 {
1975 if (result == target)
1976 result = orig_target;
1977 else if (mode != orig_mode)
1978 result = gen_lowpart (orig_mode, result);
1979 }
a5c24926
RH
1980
1981 return result;
1982}
1983
97aea203
RK
1984/* Having failed to find a 3 insn sequence in alpha_emit_set_const,
1985 fall back to a straight forward decomposition. We do this to avoid
1986 exponential run times encountered when looking for longer sequences
1987 with alpha_emit_set_const. */
1988
72910a0b 1989static rtx
a5c24926 1990alpha_emit_set_long_const (rtx target, HOST_WIDE_INT c1, HOST_WIDE_INT c2)
97aea203 1991{
97aea203 1992 HOST_WIDE_INT d1, d2, d3, d4;
97aea203
RK
1993
1994 /* Decompose the entire word */
3fe5612d 1995#if HOST_BITS_PER_WIDE_INT >= 64
56daab84 1996 gcc_assert (c2 == -(c1 < 0));
3fe5612d
RH
1997 d1 = ((c1 & 0xffff) ^ 0x8000) - 0x8000;
1998 c1 -= d1;
1999 d2 = ((c1 & 0xffffffff) ^ 0x80000000) - 0x80000000;
2000 c1 = (c1 - d2) >> 32;
2001 d3 = ((c1 & 0xffff) ^ 0x8000) - 0x8000;
2002 c1 -= d3;
2003 d4 = ((c1 & 0xffffffff) ^ 0x80000000) - 0x80000000;
56daab84 2004 gcc_assert (c1 == d4);
3fe5612d
RH
2005#else
2006 d1 = ((c1 & 0xffff) ^ 0x8000) - 0x8000;
2007 c1 -= d1;
2008 d2 = ((c1 & 0xffffffff) ^ 0x80000000) - 0x80000000;
56daab84 2009 gcc_assert (c1 == d2);
3fe5612d
RH
2010 c2 += (d2 < 0);
2011 d3 = ((c2 & 0xffff) ^ 0x8000) - 0x8000;
2012 c2 -= d3;
2013 d4 = ((c2 & 0xffffffff) ^ 0x80000000) - 0x80000000;
56daab84 2014 gcc_assert (c2 == d4);
3fe5612d 2015#endif
97aea203
RK
2016
2017 /* Construct the high word */
3fe5612d
RH
2018 if (d4)
2019 {
2020 emit_move_insn (target, GEN_INT (d4));
2021 if (d3)
2022 emit_move_insn (target, gen_rtx_PLUS (DImode, target, GEN_INT (d3)));
2023 }
97aea203 2024 else
3fe5612d 2025 emit_move_insn (target, GEN_INT (d3));
97aea203
RK
2026
2027 /* Shift it into place */
3fe5612d 2028 emit_move_insn (target, gen_rtx_ASHIFT (DImode, target, GEN_INT (32)));
97aea203 2029
3fe5612d
RH
2030 /* Add in the low bits. */
2031 if (d2)
2032 emit_move_insn (target, gen_rtx_PLUS (DImode, target, GEN_INT (d2)));
2033 if (d1)
2034 emit_move_insn (target, gen_rtx_PLUS (DImode, target, GEN_INT (d1)));
97aea203 2035
3fe5612d 2036 return target;
97aea203 2037}
97aea203 2038
72910a0b
RH
2039/* Given an integral CONST_INT, CONST_DOUBLE, or CONST_VECTOR, return
2040 the low 64 bits. */
2041
2042static void
2043alpha_extract_integer (rtx x, HOST_WIDE_INT *p0, HOST_WIDE_INT *p1)
2044{
2045 HOST_WIDE_INT i0, i1;
2046
2047 if (GET_CODE (x) == CONST_VECTOR)
2048 x = simplify_subreg (DImode, x, GET_MODE (x), 0);
2049
2050
7d83f4f5 2051 if (CONST_INT_P (x))
72910a0b
RH
2052 {
2053 i0 = INTVAL (x);
2054 i1 = -(i0 < 0);
2055 }
2056 else if (HOST_BITS_PER_WIDE_INT >= 64)
2057 {
2058 i0 = CONST_DOUBLE_LOW (x);
2059 i1 = -(i0 < 0);
2060 }
2061 else
2062 {
2063 i0 = CONST_DOUBLE_LOW (x);
2064 i1 = CONST_DOUBLE_HIGH (x);
2065 }
2066
2067 *p0 = i0;
2068 *p1 = i1;
2069}
2070
2071/* Implement LEGITIMATE_CONSTANT_P. This is all constants for which we
2072 are willing to load the value into a register via a move pattern.
2073 Normally this is all symbolic constants, integral constants that
2074 take three or fewer instructions, and floating-point zero. */
2075
2076bool
2077alpha_legitimate_constant_p (rtx x)
2078{
2079 enum machine_mode mode = GET_MODE (x);
2080 HOST_WIDE_INT i0, i1;
2081
2082 switch (GET_CODE (x))
2083 {
72910a0b 2084 case LABEL_REF:
72910a0b
RH
2085 case HIGH:
2086 return true;
2087
42a9ba1d
UB
2088 case CONST:
2089 if (GET_CODE (XEXP (x, 0)) == PLUS
2090 && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT)
2091 x = XEXP (XEXP (x, 0), 0);
2092 else
2093 return true;
2094
2095 if (GET_CODE (x) != SYMBOL_REF)
2096 return true;
2097
2098 /* FALLTHRU */
2099
e584065d
RH
2100 case SYMBOL_REF:
2101 /* TLS symbols are never valid. */
2102 return SYMBOL_REF_TLS_MODEL (x) == 0;
2103
72910a0b
RH
2104 case CONST_DOUBLE:
2105 if (x == CONST0_RTX (mode))
2106 return true;
2107 if (FLOAT_MODE_P (mode))
2108 return false;
2109 goto do_integer;
2110
2111 case CONST_VECTOR:
2112 if (x == CONST0_RTX (mode))
2113 return true;
2114 if (GET_MODE_CLASS (mode) != MODE_VECTOR_INT)
2115 return false;
2116 if (GET_MODE_SIZE (mode) != 8)
2117 return false;
2118 goto do_integer;
2119
2120 case CONST_INT:
2121 do_integer:
2122 if (TARGET_BUILD_CONSTANTS)
2123 return true;
2124 alpha_extract_integer (x, &i0, &i1);
2125 if (HOST_BITS_PER_WIDE_INT >= 64 || i1 == (-i0 < 0))
2126 return alpha_emit_set_const_1 (x, mode, i0, 3, true) != NULL;
2127 return false;
2128
2129 default:
2130 return false;
2131 }
2132}
2133
2134/* Operand 1 is known to be a constant, and should require more than one
2135 instruction to load. Emit that multi-part load. */
2136
2137bool
2138alpha_split_const_mov (enum machine_mode mode, rtx *operands)
2139{
2140 HOST_WIDE_INT i0, i1;
2141 rtx temp = NULL_RTX;
2142
2143 alpha_extract_integer (operands[1], &i0, &i1);
2144
2145 if (HOST_BITS_PER_WIDE_INT >= 64 || i1 == -(i0 < 0))
2146 temp = alpha_emit_set_const (operands[0], mode, i0, 3, false);
2147
2148 if (!temp && TARGET_BUILD_CONSTANTS)
2149 temp = alpha_emit_set_long_const (operands[0], i0, i1);
2150
2151 if (temp)
2152 {
2153 if (!rtx_equal_p (operands[0], temp))
2154 emit_move_insn (operands[0], temp);
2155 return true;
2156 }
2157
2158 return false;
2159}
2160
23296a36
RH
2161/* Expand a move instruction; return true if all work is done.
2162 We don't handle non-bwx subword loads here. */
2163
2164bool
a5c24926 2165alpha_expand_mov (enum machine_mode mode, rtx *operands)
23296a36 2166{
9dadeeb8
UB
2167 rtx tmp;
2168
23296a36 2169 /* If the output is not a register, the input must be. */
7d83f4f5 2170 if (MEM_P (operands[0])
23296a36
RH
2171 && ! reg_or_0_operand (operands[1], mode))
2172 operands[1] = force_reg (mode, operands[1]);
2173
551cc6fd 2174 /* Allow legitimize_address to perform some simplifications. */
d3e98208 2175 if (mode == Pmode && symbolic_operand (operands[1], mode))
1eb356b9 2176 {
506d7b68 2177 tmp = alpha_legitimize_address_1 (operands[1], operands[0], mode);
551cc6fd 2178 if (tmp)
133d3133 2179 {
6f9b006d
RH
2180 if (tmp == operands[0])
2181 return true;
551cc6fd 2182 operands[1] = tmp;
e2c9fb9b
RH
2183 return false;
2184 }
1eb356b9
RH
2185 }
2186
23296a36
RH
2187 /* Early out for non-constants and valid constants. */
2188 if (! CONSTANT_P (operands[1]) || input_operand (operands[1], mode))
2189 return false;
2190
2191 /* Split large integers. */
7d83f4f5 2192 if (CONST_INT_P (operands[1])
72910a0b
RH
2193 || GET_CODE (operands[1]) == CONST_DOUBLE
2194 || GET_CODE (operands[1]) == CONST_VECTOR)
23296a36 2195 {
72910a0b
RH
2196 if (alpha_split_const_mov (mode, operands))
2197 return true;
23296a36
RH
2198 }
2199
2200 /* Otherwise we've nothing left but to drop the thing to memory. */
9dadeeb8
UB
2201 tmp = force_const_mem (mode, operands[1]);
2202
2203 if (tmp == NULL_RTX)
2204 return false;
2205
23296a36
RH
2206 if (reload_in_progress)
2207 {
9dadeeb8
UB
2208 emit_move_insn (operands[0], XEXP (tmp, 0));
2209 operands[1] = replace_equiv_address (tmp, operands[0]);
23296a36
RH
2210 }
2211 else
9dadeeb8 2212 operands[1] = validize_mem (tmp);
23296a36
RH
2213 return false;
2214}
2215
2216/* Expand a non-bwx QImode or HImode move instruction;
2217 return true if all work is done. */
2218
2219bool
a5c24926 2220alpha_expand_mov_nobwx (enum machine_mode mode, rtx *operands)
23296a36 2221{
48f46219
RH
2222 rtx seq;
2223
23296a36 2224 /* If the output is not a register, the input must be. */
48f46219 2225 if (MEM_P (operands[0]))
23296a36
RH
2226 operands[1] = force_reg (mode, operands[1]);
2227
2228 /* Handle four memory cases, unaligned and aligned for either the input
2229 or the output. The only case where we can be called during reload is
2230 for aligned loads; all other cases require temporaries. */
2231
48f46219 2232 if (any_memory_operand (operands[1], mode))
23296a36
RH
2233 {
2234 if (aligned_memory_operand (operands[1], mode))
2235 {
2236 if (reload_in_progress)
2237 {
48f46219
RH
2238 if (mode == QImode)
2239 seq = gen_reload_inqi_aligned (operands[0], operands[1]);
2240 else
2241 seq = gen_reload_inhi_aligned (operands[0], operands[1]);
2242 emit_insn (seq);
23296a36
RH
2243 }
2244 else
2245 {
2246 rtx aligned_mem, bitnum;
2247 rtx scratch = gen_reg_rtx (SImode);
62e88293
RH
2248 rtx subtarget;
2249 bool copyout;
23296a36
RH
2250
2251 get_aligned_mem (operands[1], &aligned_mem, &bitnum);
2252
62e88293 2253 subtarget = operands[0];
7d83f4f5 2254 if (REG_P (subtarget))
62e88293
RH
2255 subtarget = gen_lowpart (DImode, subtarget), copyout = false;
2256 else
2257 subtarget = gen_reg_rtx (DImode), copyout = true;
2258
48f46219
RH
2259 if (mode == QImode)
2260 seq = gen_aligned_loadqi (subtarget, aligned_mem,
2261 bitnum, scratch);
2262 else
2263 seq = gen_aligned_loadhi (subtarget, aligned_mem,
2264 bitnum, scratch);
2265 emit_insn (seq);
62e88293
RH
2266
2267 if (copyout)
2268 emit_move_insn (operands[0], gen_lowpart (mode, subtarget));
23296a36
RH
2269 }
2270 }
2271 else
2272 {
2273 /* Don't pass these as parameters since that makes the generated
2274 code depend on parameter evaluation order which will cause
2275 bootstrap failures. */
2276
48f46219 2277 rtx temp1, temp2, subtarget, ua;
62e88293
RH
2278 bool copyout;
2279
2280 temp1 = gen_reg_rtx (DImode);
2281 temp2 = gen_reg_rtx (DImode);
23296a36 2282
62e88293 2283 subtarget = operands[0];
7d83f4f5 2284 if (REG_P (subtarget))
62e88293
RH
2285 subtarget = gen_lowpart (DImode, subtarget), copyout = false;
2286 else
2287 subtarget = gen_reg_rtx (DImode), copyout = true;
2288
48f46219
RH
2289 ua = get_unaligned_address (operands[1]);
2290 if (mode == QImode)
2291 seq = gen_unaligned_loadqi (subtarget, ua, temp1, temp2);
2292 else
2293 seq = gen_unaligned_loadhi (subtarget, ua, temp1, temp2);
2294
23296a36
RH
2295 alpha_set_memflags (seq, operands[1]);
2296 emit_insn (seq);
62e88293
RH
2297
2298 if (copyout)
2299 emit_move_insn (operands[0], gen_lowpart (mode, subtarget));
23296a36
RH
2300 }
2301 return true;
2302 }
2303
48f46219 2304 if (any_memory_operand (operands[0], mode))
23296a36
RH
2305 {
2306 if (aligned_memory_operand (operands[0], mode))
2307 {
2308 rtx aligned_mem, bitnum;
2309 rtx temp1 = gen_reg_rtx (SImode);
2310 rtx temp2 = gen_reg_rtx (SImode);
2311
2312 get_aligned_mem (operands[0], &aligned_mem, &bitnum);
2313
2314 emit_insn (gen_aligned_store (aligned_mem, operands[1], bitnum,
2315 temp1, temp2));
2316 }
2317 else
2318 {
2319 rtx temp1 = gen_reg_rtx (DImode);
2320 rtx temp2 = gen_reg_rtx (DImode);
2321 rtx temp3 = gen_reg_rtx (DImode);
48f46219
RH
2322 rtx ua = get_unaligned_address (operands[0]);
2323
2324 if (mode == QImode)
2325 seq = gen_unaligned_storeqi (ua, operands[1], temp1, temp2, temp3);
2326 else
2327 seq = gen_unaligned_storehi (ua, operands[1], temp1, temp2, temp3);
23296a36
RH
2328
2329 alpha_set_memflags (seq, operands[0]);
2330 emit_insn (seq);
2331 }
2332 return true;
2333 }
2334
2335 return false;
2336}
2337
ad78a663 2338/* Implement the movmisalign patterns. One of the operands is a memory
35c0104b 2339 that is not naturally aligned. Emit instructions to load it. */
ad78a663
RH
2340
2341void
2342alpha_expand_movmisalign (enum machine_mode mode, rtx *operands)
2343{
2344 /* Honor misaligned loads, for those we promised to do so. */
2345 if (MEM_P (operands[1]))
2346 {
2347 rtx tmp;
2348
2349 if (register_operand (operands[0], mode))
2350 tmp = operands[0];
2351 else
2352 tmp = gen_reg_rtx (mode);
2353
2354 alpha_expand_unaligned_load (tmp, operands[1], 8, 0, 0);
2355 if (tmp != operands[0])
2356 emit_move_insn (operands[0], tmp);
2357 }
2358 else if (MEM_P (operands[0]))
2359 {
2360 if (!reg_or_0_operand (operands[1], mode))
2361 operands[1] = force_reg (mode, operands[1]);
2362 alpha_expand_unaligned_store (operands[0], operands[1], 8, 0);
2363 }
2364 else
2365 gcc_unreachable ();
2366}
2367
01b9e84e
RH
2368/* Generate an unsigned DImode to FP conversion. This is the same code
2369 optabs would emit if we didn't have TFmode patterns.
2370
2371 For SFmode, this is the only construction I've found that can pass
2372 gcc.c-torture/execute/ieee/rbug.c. No scenario that uses DFmode
2373 intermediates will work, because you'll get intermediate rounding
2374 that ruins the end result. Some of this could be fixed by turning
2375 on round-to-positive-infinity, but that requires diddling the fpsr,
2376 which kills performance. I tried turning this around and converting
2377 to a negative number, so that I could turn on /m, but either I did
2378 it wrong or there's something else cause I wound up with the exact
2379 same single-bit error. There is a branch-less form of this same code:
2380
2381 srl $16,1,$1
2382 and $16,1,$2
2383 cmplt $16,0,$3
2384 or $1,$2,$2
2385 cmovge $16,$16,$2
2386 itoft $3,$f10
2387 itoft $2,$f11
2388 cvtqs $f11,$f11
2389 adds $f11,$f11,$f0
2390 fcmoveq $f10,$f11,$f0
2391
2392 I'm not using it because it's the same number of instructions as
2393 this branch-full form, and it has more serialized long latency
2394 instructions on the critical path.
2395
2396 For DFmode, we can avoid rounding errors by breaking up the word
2397 into two pieces, converting them separately, and adding them back:
2398
2399 LC0: .long 0,0x5f800000
2400
2401 itoft $16,$f11
2402 lda $2,LC0
70994f30 2403 cmplt $16,0,$1
01b9e84e
RH
2404 cpyse $f11,$f31,$f10
2405 cpyse $f31,$f11,$f11
2406 s4addq $1,$2,$1
2407 lds $f12,0($1)
2408 cvtqt $f10,$f10
2409 cvtqt $f11,$f11
2410 addt $f12,$f10,$f0
2411 addt $f0,$f11,$f0
2412
2413 This doesn't seem to be a clear-cut win over the optabs form.
2414 It probably all depends on the distribution of numbers being
2415 converted -- in the optabs form, all but high-bit-set has a
2416 much lower minimum execution time. */
2417
2418void
a5c24926 2419alpha_emit_floatuns (rtx operands[2])
01b9e84e
RH
2420{
2421 rtx neglab, donelab, i0, i1, f0, in, out;
2422 enum machine_mode mode;
2423
2424 out = operands[0];
57014cb9 2425 in = force_reg (DImode, operands[1]);
01b9e84e
RH
2426 mode = GET_MODE (out);
2427 neglab = gen_label_rtx ();
2428 donelab = gen_label_rtx ();
2429 i0 = gen_reg_rtx (DImode);
2430 i1 = gen_reg_rtx (DImode);
2431 f0 = gen_reg_rtx (mode);
2432
d43e0b7d 2433 emit_cmp_and_jump_insns (in, const0_rtx, LT, const0_rtx, DImode, 0, neglab);
01b9e84e
RH
2434
2435 emit_insn (gen_rtx_SET (VOIDmode, out, gen_rtx_FLOAT (mode, in)));
2436 emit_jump_insn (gen_jump (donelab));
70994f30 2437 emit_barrier ();
01b9e84e
RH
2438
2439 emit_label (neglab);
2440
2441 emit_insn (gen_lshrdi3 (i0, in, const1_rtx));
2442 emit_insn (gen_anddi3 (i1, in, const1_rtx));
2443 emit_insn (gen_iordi3 (i0, i0, i1));
2444 emit_insn (gen_rtx_SET (VOIDmode, f0, gen_rtx_FLOAT (mode, i0)));
2445 emit_insn (gen_rtx_SET (VOIDmode, out, gen_rtx_PLUS (mode, f0, f0)));
2446
2447 emit_label (donelab);
2448}
2449
f283421d
RH
2450/* Generate the comparison for a conditional branch. */
2451
f90b7a5a
PB
2452void
2453alpha_emit_conditional_branch (rtx operands[], enum machine_mode cmp_mode)
f283421d
RH
2454{
2455 enum rtx_code cmp_code, branch_code;
f90b7a5a
PB
2456 enum machine_mode branch_mode = VOIDmode;
2457 enum rtx_code code = GET_CODE (operands[0]);
2458 rtx op0 = operands[1], op1 = operands[2];
f283421d
RH
2459 rtx tem;
2460
f90b7a5a 2461 if (cmp_mode == TFmode)
5495cc55 2462 {
0da4e73a 2463 op0 = alpha_emit_xfloating_compare (&code, op0, op1);
5495cc55 2464 op1 = const0_rtx;
f90b7a5a 2465 cmp_mode = DImode;
5495cc55
RH
2466 }
2467
f283421d
RH
2468 /* The general case: fold the comparison code to the types of compares
2469 that we have, choosing the branch as necessary. */
2470 switch (code)
2471 {
2472 case EQ: case LE: case LT: case LEU: case LTU:
1eb8759b 2473 case UNORDERED:
f283421d
RH
2474 /* We have these compares: */
2475 cmp_code = code, branch_code = NE;
2476 break;
2477
2478 case NE:
1eb8759b 2479 case ORDERED:
285a5742 2480 /* These must be reversed. */
1eb8759b 2481 cmp_code = reverse_condition (code), branch_code = EQ;
f283421d
RH
2482 break;
2483
2484 case GE: case GT: case GEU: case GTU:
2485 /* For FP, we swap them, for INT, we reverse them. */
f90b7a5a 2486 if (cmp_mode == DFmode)
f283421d
RH
2487 {
2488 cmp_code = swap_condition (code);
2489 branch_code = NE;
2490 tem = op0, op0 = op1, op1 = tem;
2491 }
2492 else
2493 {
2494 cmp_code = reverse_condition (code);
2495 branch_code = EQ;
2496 }
2497 break;
2498
2499 default:
56daab84 2500 gcc_unreachable ();
f283421d
RH
2501 }
2502
f90b7a5a 2503 if (cmp_mode == DFmode)
f283421d 2504 {
ec46190f 2505 if (flag_unsafe_math_optimizations && cmp_code != UNORDERED)
f283421d
RH
2506 {
2507 /* When we are not as concerned about non-finite values, and we
2508 are comparing against zero, we can branch directly. */
2509 if (op1 == CONST0_RTX (DFmode))
f822d252 2510 cmp_code = UNKNOWN, branch_code = code;
f283421d
RH
2511 else if (op0 == CONST0_RTX (DFmode))
2512 {
2513 /* Undo the swap we probably did just above. */
2514 tem = op0, op0 = op1, op1 = tem;
b771b6b4 2515 branch_code = swap_condition (cmp_code);
f822d252 2516 cmp_code = UNKNOWN;
f283421d
RH
2517 }
2518 }
2519 else
2520 {
27d30956 2521 /* ??? We mark the branch mode to be CCmode to prevent the
f676971a 2522 compare and branch from being combined, since the compare
f283421d
RH
2523 insn follows IEEE rules that the branch does not. */
2524 branch_mode = CCmode;
2525 }
2526 }
2527 else
2528 {
f283421d
RH
2529 /* The following optimizations are only for signed compares. */
2530 if (code != LEU && code != LTU && code != GEU && code != GTU)
2531 {
2532 /* Whee. Compare and branch against 0 directly. */
2533 if (op1 == const0_rtx)
f822d252 2534 cmp_code = UNKNOWN, branch_code = code;
f283421d 2535
e006ced2
FH
2536 /* If the constants doesn't fit into an immediate, but can
2537 be generated by lda/ldah, we adjust the argument and
2538 compare against zero, so we can use beq/bne directly. */
4a4f95d9
RH
2539 /* ??? Don't do this when comparing against symbols, otherwise
2540 we'll reduce (&x == 0x1234) to (&x-0x1234 == 0), which will
2541 be declared false out of hand (at least for non-weak). */
7d83f4f5 2542 else if (CONST_INT_P (op1)
4a4f95d9
RH
2543 && (code == EQ || code == NE)
2544 && !(symbolic_operand (op0, VOIDmode)
7d83f4f5 2545 || (REG_P (op0) && REG_POINTER (op0))))
f283421d 2546 {
dfcbeaa5
RH
2547 rtx n_op1 = GEN_INT (-INTVAL (op1));
2548
2549 if (! satisfies_constraint_I (op1)
2550 && (satisfies_constraint_K (n_op1)
2551 || satisfies_constraint_L (n_op1)))
2552 cmp_code = PLUS, branch_code = code, op1 = n_op1;
f283421d
RH
2553 }
2554 }
f283421d 2555
9e495700
RH
2556 if (!reg_or_0_operand (op0, DImode))
2557 op0 = force_reg (DImode, op0);
2558 if (cmp_code != PLUS && !reg_or_8bit_operand (op1, DImode))
2559 op1 = force_reg (DImode, op1);
2560 }
f283421d
RH
2561
2562 /* Emit an initial compare instruction, if necessary. */
2563 tem = op0;
f822d252 2564 if (cmp_code != UNKNOWN)
f283421d
RH
2565 {
2566 tem = gen_reg_rtx (cmp_mode);
2567 emit_move_insn (tem, gen_rtx_fmt_ee (cmp_code, cmp_mode, op0, op1));
2568 }
2569
f90b7a5a
PB
2570 /* Emit the branch instruction. */
2571 tem = gen_rtx_SET (VOIDmode, pc_rtx,
2572 gen_rtx_IF_THEN_ELSE (VOIDmode,
2573 gen_rtx_fmt_ee (branch_code,
2574 branch_mode, tem,
2575 CONST0_RTX (cmp_mode)),
2576 gen_rtx_LABEL_REF (VOIDmode,
2577 operands[3]),
2578 pc_rtx));
2579 emit_jump_insn (tem);
f283421d
RH
2580}
2581
9e495700
RH
2582/* Certain simplifications can be done to make invalid setcc operations
2583 valid. Return the final comparison, or NULL if we can't work. */
2584
f90b7a5a
PB
2585bool
2586alpha_emit_setcc (rtx operands[], enum machine_mode cmp_mode)
9e495700
RH
2587{
2588 enum rtx_code cmp_code;
f90b7a5a
PB
2589 enum rtx_code code = GET_CODE (operands[1]);
2590 rtx op0 = operands[2], op1 = operands[3];
9e495700
RH
2591 rtx tmp;
2592
f90b7a5a 2593 if (cmp_mode == TFmode)
9e495700 2594 {
0da4e73a 2595 op0 = alpha_emit_xfloating_compare (&code, op0, op1);
9e495700 2596 op1 = const0_rtx;
f90b7a5a 2597 cmp_mode = DImode;
9e495700
RH
2598 }
2599
f90b7a5a
PB
2600 if (cmp_mode == DFmode && !TARGET_FIX)
2601 return 0;
9e495700
RH
2602
2603 /* The general case: fold the comparison code to the types of compares
2604 that we have, choosing the branch as necessary. */
2605
f822d252 2606 cmp_code = UNKNOWN;
9e495700
RH
2607 switch (code)
2608 {
2609 case EQ: case LE: case LT: case LEU: case LTU:
2610 case UNORDERED:
2611 /* We have these compares. */
f90b7a5a 2612 if (cmp_mode == DFmode)
9e495700
RH
2613 cmp_code = code, code = NE;
2614 break;
2615
2616 case NE:
f90b7a5a 2617 if (cmp_mode == DImode && op1 == const0_rtx)
9e495700 2618 break;
5efb1046 2619 /* FALLTHRU */
9e495700
RH
2620
2621 case ORDERED:
2622 cmp_code = reverse_condition (code);
2623 code = EQ;
2624 break;
2625
2626 case GE: case GT: case GEU: case GTU:
56f19d92 2627 /* These normally need swapping, but for integer zero we have
c74fa144 2628 special patterns that recognize swapped operands. */
f90b7a5a 2629 if (cmp_mode == DImode && op1 == const0_rtx)
c74fa144 2630 break;
9e495700 2631 code = swap_condition (code);
f90b7a5a 2632 if (cmp_mode == DFmode)
9e495700
RH
2633 cmp_code = code, code = NE;
2634 tmp = op0, op0 = op1, op1 = tmp;
2635 break;
2636
2637 default:
56daab84 2638 gcc_unreachable ();
9e495700
RH
2639 }
2640
f90b7a5a 2641 if (cmp_mode == DImode)
9e495700 2642 {
c74fa144 2643 if (!register_operand (op0, DImode))
9e495700
RH
2644 op0 = force_reg (DImode, op0);
2645 if (!reg_or_8bit_operand (op1, DImode))
2646 op1 = force_reg (DImode, op1);
2647 }
2648
2649 /* Emit an initial compare instruction, if necessary. */
f822d252 2650 if (cmp_code != UNKNOWN)
9e495700 2651 {
f90b7a5a 2652 tmp = gen_reg_rtx (cmp_mode);
9e495700 2653 emit_insn (gen_rtx_SET (VOIDmode, tmp,
f90b7a5a 2654 gen_rtx_fmt_ee (cmp_code, cmp_mode, op0, op1)));
9e495700 2655
7c1db202 2656 op0 = cmp_mode != DImode ? gen_lowpart (DImode, tmp) : tmp;
9e495700
RH
2657 op1 = const0_rtx;
2658 }
2659
f90b7a5a
PB
2660 /* Emit the setcc instruction. */
2661 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
2662 gen_rtx_fmt_ee (code, DImode, op0, op1)));
2663 return true;
9e495700
RH
2664}
2665
f283421d 2666
758d2c0c
RK
2667/* Rewrite a comparison against zero CMP of the form
2668 (CODE (cc0) (const_int 0)) so it can be written validly in
2669 a conditional move (if_then_else CMP ...).
825dda42 2670 If both of the operands that set cc0 are nonzero we must emit
758d2c0c 2671 an insn to perform the compare (it can't be done within
285a5742 2672 the conditional move). */
a5c24926 2673
758d2c0c 2674rtx
a5c24926 2675alpha_emit_conditional_move (rtx cmp, enum machine_mode mode)
758d2c0c 2676{
1ad2a62d 2677 enum rtx_code code = GET_CODE (cmp);
89b7c471 2678 enum rtx_code cmov_code = NE;
f90b7a5a
PB
2679 rtx op0 = XEXP (cmp, 0);
2680 rtx op1 = XEXP (cmp, 1);
1ad2a62d
RK
2681 enum machine_mode cmp_mode
2682 = (GET_MODE (op0) == VOIDmode ? DImode : GET_MODE (op0));
f283421d 2683 enum machine_mode cmov_mode = VOIDmode;
de6c5979 2684 int local_fast_math = flag_unsafe_math_optimizations;
1ad2a62d 2685 rtx tem;
758d2c0c 2686
387c39e1
UB
2687 if (cmp_mode == TFmode)
2688 {
2689 op0 = alpha_emit_xfloating_compare (&code, op0, op1);
2690 op1 = const0_rtx;
2691 cmp_mode = DImode;
2692 }
2693
f90b7a5a 2694 gcc_assert (cmp_mode == DFmode || cmp_mode == DImode);
6db21c7f 2695
f90b7a5a 2696 if (FLOAT_MODE_P (cmp_mode) != FLOAT_MODE_P (mode))
09fe1c49
RH
2697 {
2698 enum rtx_code cmp_code;
2699
2700 if (! TARGET_FIX)
2701 return 0;
2702
2703 /* If we have fp<->int register move instructions, do a cmov by
2704 performing the comparison in fp registers, and move the
825dda42 2705 zero/nonzero value to integer registers, where we can then
09fe1c49
RH
2706 use a normal cmov, or vice-versa. */
2707
2708 switch (code)
2709 {
2710 case EQ: case LE: case LT: case LEU: case LTU:
2711 /* We have these compares. */
2712 cmp_code = code, code = NE;
2713 break;
2714
2715 case NE:
2716 /* This must be reversed. */
2717 cmp_code = EQ, code = EQ;
2718 break;
2719
2720 case GE: case GT: case GEU: case GTU:
56f19d92
RH
2721 /* These normally need swapping, but for integer zero we have
2722 special patterns that recognize swapped operands. */
f90b7a5a 2723 if (cmp_mode == DImode && op1 == const0_rtx)
c53f9f5b
RH
2724 cmp_code = code, code = NE;
2725 else
2726 {
2727 cmp_code = swap_condition (code);
2728 code = NE;
2729 tem = op0, op0 = op1, op1 = tem;
2730 }
09fe1c49
RH
2731 break;
2732
2733 default:
56daab84 2734 gcc_unreachable ();
09fe1c49
RH
2735 }
2736
f90b7a5a 2737 tem = gen_reg_rtx (cmp_mode);
09fe1c49 2738 emit_insn (gen_rtx_SET (VOIDmode, tem,
f90b7a5a 2739 gen_rtx_fmt_ee (cmp_code, cmp_mode,
09fe1c49
RH
2740 op0, op1)));
2741
f90b7a5a
PB
2742 cmp_mode = cmp_mode == DImode ? DFmode : DImode;
2743 op0 = gen_lowpart (cmp_mode, tem);
2744 op1 = CONST0_RTX (cmp_mode);
09fe1c49
RH
2745 local_fast_math = 1;
2746 }
758d2c0c
RK
2747
2748 /* We may be able to use a conditional move directly.
285a5742 2749 This avoids emitting spurious compares. */
01b9e84e 2750 if (signed_comparison_operator (cmp, VOIDmode)
f90b7a5a 2751 && (cmp_mode == DImode || local_fast_math)
1ad2a62d 2752 && (op0 == CONST0_RTX (cmp_mode) || op1 == CONST0_RTX (cmp_mode)))
38a448ca 2753 return gen_rtx_fmt_ee (code, VOIDmode, op0, op1);
758d2c0c 2754
000ca373 2755 /* We can't put the comparison inside the conditional move;
758d2c0c 2756 emit a compare instruction and put that inside the
1ad2a62d
RK
2757 conditional move. Make sure we emit only comparisons we have;
2758 swap or reverse as necessary. */
758d2c0c 2759
b3a13419 2760 if (!can_create_pseudo_p ())
000ca373
RH
2761 return NULL_RTX;
2762
758d2c0c
RK
2763 switch (code)
2764 {
1ad2a62d
RK
2765 case EQ: case LE: case LT: case LEU: case LTU:
2766 /* We have these compares: */
758d2c0c 2767 break;
1ad2a62d 2768
758d2c0c 2769 case NE:
285a5742 2770 /* This must be reversed. */
1ad2a62d 2771 code = reverse_condition (code);
89b7c471 2772 cmov_code = EQ;
758d2c0c 2773 break;
1ad2a62d
RK
2774
2775 case GE: case GT: case GEU: case GTU:
9e495700 2776 /* These must be swapped. */
c53f9f5b
RH
2777 if (op1 != CONST0_RTX (cmp_mode))
2778 {
2779 code = swap_condition (code);
2780 tem = op0, op0 = op1, op1 = tem;
2781 }
758d2c0c 2782 break;
1ad2a62d 2783
758d2c0c 2784 default:
56daab84 2785 gcc_unreachable ();
758d2c0c
RK
2786 }
2787
f90b7a5a 2788 if (cmp_mode == DImode)
9e495700
RH
2789 {
2790 if (!reg_or_0_operand (op0, DImode))
2791 op0 = force_reg (DImode, op0);
2792 if (!reg_or_8bit_operand (op1, DImode))
2793 op1 = force_reg (DImode, op1);
2794 }
2795
68aed21b 2796 /* ??? We mark the branch mode to be CCmode to prevent the compare
f283421d
RH
2797 and cmov from being combined, since the compare insn follows IEEE
2798 rules that the cmov does not. */
f90b7a5a 2799 if (cmp_mode == DFmode && !local_fast_math)
f283421d
RH
2800 cmov_mode = CCmode;
2801
f90b7a5a
PB
2802 tem = gen_reg_rtx (cmp_mode);
2803 emit_move_insn (tem, gen_rtx_fmt_ee (code, cmp_mode, op0, op1));
2804 return gen_rtx_fmt_ee (cmov_code, cmov_mode, tem, CONST0_RTX (cmp_mode));
758d2c0c 2805}
8f4773ea
RH
2806
2807/* Simplify a conditional move of two constants into a setcc with
2808 arithmetic. This is done with a splitter since combine would
2809 just undo the work if done during code generation. It also catches
2810 cases we wouldn't have before cse. */
2811
2812int
a5c24926
RH
2813alpha_split_conditional_move (enum rtx_code code, rtx dest, rtx cond,
2814 rtx t_rtx, rtx f_rtx)
8f4773ea
RH
2815{
2816 HOST_WIDE_INT t, f, diff;
2817 enum machine_mode mode;
2818 rtx target, subtarget, tmp;
2819
2820 mode = GET_MODE (dest);
2821 t = INTVAL (t_rtx);
2822 f = INTVAL (f_rtx);
2823 diff = t - f;
2824
2825 if (((code == NE || code == EQ) && diff < 0)
2826 || (code == GE || code == GT))
2827 {
2828 code = reverse_condition (code);
2829 diff = t, t = f, f = diff;
2830 diff = t - f;
2831 }
2832
2833 subtarget = target = dest;
2834 if (mode != DImode)
2835 {
2836 target = gen_lowpart (DImode, dest);
b3a13419 2837 if (can_create_pseudo_p ())
8f4773ea
RH
2838 subtarget = gen_reg_rtx (DImode);
2839 else
2840 subtarget = target;
2841 }
a5376276
RH
2842 /* Below, we must be careful to use copy_rtx on target and subtarget
2843 in intermediate insns, as they may be a subreg rtx, which may not
2844 be shared. */
8f4773ea
RH
2845
2846 if (f == 0 && exact_log2 (diff) > 0
9a9f7594 2847 /* On EV6, we've got enough shifters to make non-arithmetic shifts
8f4773ea 2848 viable over a longer latency cmove. On EV5, the E0 slot is a
285a5742 2849 scarce resource, and on EV4 shift has the same latency as a cmove. */
8bea7f7c 2850 && (diff <= 8 || alpha_tune == PROCESSOR_EV6))
8f4773ea
RH
2851 {
2852 tmp = gen_rtx_fmt_ee (code, DImode, cond, const0_rtx);
a5376276 2853 emit_insn (gen_rtx_SET (VOIDmode, copy_rtx (subtarget), tmp));
8f4773ea 2854
a5376276
RH
2855 tmp = gen_rtx_ASHIFT (DImode, copy_rtx (subtarget),
2856 GEN_INT (exact_log2 (t)));
8f4773ea
RH
2857 emit_insn (gen_rtx_SET (VOIDmode, target, tmp));
2858 }
2859 else if (f == 0 && t == -1)
2860 {
2861 tmp = gen_rtx_fmt_ee (code, DImode, cond, const0_rtx);
a5376276 2862 emit_insn (gen_rtx_SET (VOIDmode, copy_rtx (subtarget), tmp));
8f4773ea 2863
a5376276 2864 emit_insn (gen_negdi2 (target, copy_rtx (subtarget)));
8f4773ea
RH
2865 }
2866 else if (diff == 1 || diff == 4 || diff == 8)
2867 {
2868 rtx add_op;
2869
2870 tmp = gen_rtx_fmt_ee (code, DImode, cond, const0_rtx);
a5376276 2871 emit_insn (gen_rtx_SET (VOIDmode, copy_rtx (subtarget), tmp));
8f4773ea
RH
2872
2873 if (diff == 1)
a5376276 2874 emit_insn (gen_adddi3 (target, copy_rtx (subtarget), GEN_INT (f)));
8f4773ea
RH
2875 else
2876 {
2877 add_op = GEN_INT (f);
2878 if (sext_add_operand (add_op, mode))
2879 {
a5376276
RH
2880 tmp = gen_rtx_MULT (DImode, copy_rtx (subtarget),
2881 GEN_INT (diff));
8f4773ea
RH
2882 tmp = gen_rtx_PLUS (DImode, tmp, add_op);
2883 emit_insn (gen_rtx_SET (VOIDmode, target, tmp));
2884 }
2885 else
2886 return 0;
2887 }
2888 }
2889 else
2890 return 0;
2891
2892 return 1;
2893}
6c174fc0 2894\f
5495cc55
RH
2895/* Look up the function X_floating library function name for the
2896 given operation. */
2897
d1b38208 2898struct GTY(()) xfloating_op
75959f0a
RH
2899{
2900 const enum rtx_code code;
1431042e
ZW
2901 const char *const GTY((skip)) osf_func;
2902 const char *const GTY((skip)) vms_func;
75959f0a
RH
2903 rtx libcall;
2904};
2905
f676971a 2906static GTY(()) struct xfloating_op xfloating_ops[] =
75959f0a
RH
2907{
2908 { PLUS, "_OtsAddX", "OTS$ADD_X", 0 },
2909 { MINUS, "_OtsSubX", "OTS$SUB_X", 0 },
2910 { MULT, "_OtsMulX", "OTS$MUL_X", 0 },
2911 { DIV, "_OtsDivX", "OTS$DIV_X", 0 },
2912 { EQ, "_OtsEqlX", "OTS$EQL_X", 0 },
2913 { NE, "_OtsNeqX", "OTS$NEQ_X", 0 },
2914 { LT, "_OtsLssX", "OTS$LSS_X", 0 },
2915 { LE, "_OtsLeqX", "OTS$LEQ_X", 0 },
2916 { GT, "_OtsGtrX", "OTS$GTR_X", 0 },
2917 { GE, "_OtsGeqX", "OTS$GEQ_X", 0 },
2918 { FIX, "_OtsCvtXQ", "OTS$CVTXQ", 0 },
2919 { FLOAT, "_OtsCvtQX", "OTS$CVTQX", 0 },
2920 { UNSIGNED_FLOAT, "_OtsCvtQUX", "OTS$CVTQUX", 0 },
2921 { FLOAT_EXTEND, "_OtsConvertFloatTX", "OTS$CVT_FLOAT_T_X", 0 },
2922 { FLOAT_TRUNCATE, "_OtsConvertFloatXT", "OTS$CVT_FLOAT_X_T", 0 }
2923};
2924
2925static GTY(()) struct xfloating_op vax_cvt_ops[] =
2926{
2927 { FLOAT_EXTEND, "_OtsConvertFloatGX", "OTS$CVT_FLOAT_G_X", 0 },
2928 { FLOAT_TRUNCATE, "_OtsConvertFloatXG", "OTS$CVT_FLOAT_X_G", 0 }
2929};
2930
2931static rtx
a5c24926 2932alpha_lookup_xfloating_lib_func (enum rtx_code code)
5495cc55 2933{
75959f0a
RH
2934 struct xfloating_op *ops = xfloating_ops;
2935 long n = ARRAY_SIZE (xfloating_ops);
5495cc55
RH
2936 long i;
2937
0da4e73a
RH
2938 gcc_assert (TARGET_HAS_XFLOATING_LIBS);
2939
75959f0a
RH
2940 /* How irritating. Nothing to key off for the main table. */
2941 if (TARGET_FLOAT_VAX && (code == FLOAT_EXTEND || code == FLOAT_TRUNCATE))
5495cc55 2942 {
75959f0a
RH
2943 ops = vax_cvt_ops;
2944 n = ARRAY_SIZE (vax_cvt_ops);
5495cc55
RH
2945 }
2946
75959f0a
RH
2947 for (i = 0; i < n; ++i, ++ops)
2948 if (ops->code == code)
2949 {
2950 rtx func = ops->libcall;
2951 if (!func)
2952 {
2953 func = init_one_libfunc (TARGET_ABI_OPEN_VMS
2954 ? ops->vms_func : ops->osf_func);
2955 ops->libcall = func;
2956 }
2957 return func;
2958 }
5495cc55 2959
56daab84 2960 gcc_unreachable ();
5495cc55
RH
2961}
2962
2963/* Most X_floating operations take the rounding mode as an argument.
2964 Compute that here. */
2965
2966static int
a5c24926
RH
2967alpha_compute_xfloating_mode_arg (enum rtx_code code,
2968 enum alpha_fp_rounding_mode round)
5495cc55
RH
2969{
2970 int mode;
2971
2972 switch (round)
2973 {
2974 case ALPHA_FPRM_NORM:
2975 mode = 2;
2976 break;
2977 case ALPHA_FPRM_MINF:
2978 mode = 1;
2979 break;
2980 case ALPHA_FPRM_CHOP:
2981 mode = 0;
2982 break;
2983 case ALPHA_FPRM_DYN:
2984 mode = 4;
2985 break;
2986 default:
56daab84 2987 gcc_unreachable ();
5495cc55
RH
2988
2989 /* XXX For reference, round to +inf is mode = 3. */
2990 }
2991
2992 if (code == FLOAT_TRUNCATE && alpha_fptm == ALPHA_FPTM_N)
2993 mode |= 0x10000;
2994
2995 return mode;
2996}
2997
2998/* Emit an X_floating library function call.
2999
3000 Note that these functions do not follow normal calling conventions:
3001 TFmode arguments are passed in two integer registers (as opposed to
f676971a 3002 indirect); TFmode return values appear in R16+R17.
5495cc55 3003
75959f0a 3004 FUNC is the function to call.
5495cc55
RH
3005 TARGET is where the output belongs.
3006 OPERANDS are the inputs.
3007 NOPERANDS is the count of inputs.
3008 EQUIV is the expression equivalent for the function.
3009*/
3010
3011static void
75959f0a 3012alpha_emit_xfloating_libcall (rtx func, rtx target, rtx operands[],
a5c24926 3013 int noperands, rtx equiv)
5495cc55
RH
3014{
3015 rtx usage = NULL_RTX, tmp, reg;
3016 int regno = 16, i;
3017
3018 start_sequence ();
3019
3020 for (i = 0; i < noperands; ++i)
3021 {
3022 switch (GET_MODE (operands[i]))
3023 {
3024 case TFmode:
3025 reg = gen_rtx_REG (TFmode, regno);
3026 regno += 2;
3027 break;
3028
3029 case DFmode:
3030 reg = gen_rtx_REG (DFmode, regno + 32);
3031 regno += 1;
3032 break;
3033
3034 case VOIDmode:
7d83f4f5 3035 gcc_assert (CONST_INT_P (operands[i]));
5efb1046 3036 /* FALLTHRU */
5495cc55
RH
3037 case DImode:
3038 reg = gen_rtx_REG (DImode, regno);
3039 regno += 1;
3040 break;
3041
3042 default:
56daab84 3043 gcc_unreachable ();
5495cc55
RH
3044 }
3045
3046 emit_move_insn (reg, operands[i]);
3047 usage = alloc_EXPR_LIST (0, gen_rtx_USE (VOIDmode, reg), usage);
3048 }
3049
3050 switch (GET_MODE (target))
3051 {
3052 case TFmode:
3053 reg = gen_rtx_REG (TFmode, 16);
3054 break;
3055 case DFmode:
3056 reg = gen_rtx_REG (DFmode, 32);
3057 break;
3058 case DImode:
3059 reg = gen_rtx_REG (DImode, 0);
3060 break;
3061 default:
56daab84 3062 gcc_unreachable ();
5495cc55
RH
3063 }
3064
75959f0a 3065 tmp = gen_rtx_MEM (QImode, func);
0499c2e4 3066 tmp = emit_call_insn (GEN_CALL_VALUE (reg, tmp, const0_rtx,
5495cc55
RH
3067 const0_rtx, const0_rtx));
3068 CALL_INSN_FUNCTION_USAGE (tmp) = usage;
becfd6e5 3069 RTL_CONST_CALL_P (tmp) = 1;
5495cc55
RH
3070
3071 tmp = get_insns ();
3072 end_sequence ();
3073
3074 emit_libcall_block (tmp, target, reg, equiv);
3075}
3076
3077/* Emit an X_floating library function call for arithmetic (+,-,*,/). */
3078
3079void
a5c24926 3080alpha_emit_xfloating_arith (enum rtx_code code, rtx operands[])
5495cc55 3081{
75959f0a 3082 rtx func;
5495cc55 3083 int mode;
c77f46c6 3084 rtx out_operands[3];
5495cc55
RH
3085
3086 func = alpha_lookup_xfloating_lib_func (code);
3087 mode = alpha_compute_xfloating_mode_arg (code, alpha_fprm);
3088
c77f46c6
AO
3089 out_operands[0] = operands[1];
3090 out_operands[1] = operands[2];
3091 out_operands[2] = GEN_INT (mode);
f676971a 3092 alpha_emit_xfloating_libcall (func, operands[0], out_operands, 3,
5495cc55
RH
3093 gen_rtx_fmt_ee (code, TFmode, operands[1],
3094 operands[2]));
3095}
3096
3097/* Emit an X_floating library function call for a comparison. */
3098
3099static rtx
0da4e73a 3100alpha_emit_xfloating_compare (enum rtx_code *pcode, rtx op0, rtx op1)
5495cc55 3101{
0da4e73a 3102 enum rtx_code cmp_code, res_code;
32891ff6 3103 rtx func, out, operands[2], note;
5495cc55 3104
0da4e73a
RH
3105 /* X_floating library comparison functions return
3106 -1 unordered
3107 0 false
3108 1 true
3109 Convert the compare against the raw return value. */
3110
3111 cmp_code = *pcode;
3112 switch (cmp_code)
3113 {
3114 case UNORDERED:
3115 cmp_code = EQ;
3116 res_code = LT;
3117 break;
3118 case ORDERED:
3119 cmp_code = EQ;
3120 res_code = GE;
3121 break;
3122 case NE:
3123 res_code = NE;
3124 break;
3125 case EQ:
3126 case LT:
3127 case GT:
3128 case LE:
3129 case GE:
3130 res_code = GT;
3131 break;
3132 default:
3133 gcc_unreachable ();
3134 }
3135 *pcode = res_code;
3136
3137 func = alpha_lookup_xfloating_lib_func (cmp_code);
5495cc55
RH
3138
3139 operands[0] = op0;
3140 operands[1] = op1;
3141 out = gen_reg_rtx (DImode);
3142
32891ff6
RH
3143 /* What's actually returned is -1,0,1, not a proper boolean value,
3144 so use an EXPR_LIST as with a generic libcall instead of a
3145 comparison type expression. */
3146 note = gen_rtx_EXPR_LIST (VOIDmode, op1, NULL_RTX);
3147 note = gen_rtx_EXPR_LIST (VOIDmode, op0, note);
3148 note = gen_rtx_EXPR_LIST (VOIDmode, func, note);
3149 alpha_emit_xfloating_libcall (func, out, operands, 2, note);
5495cc55
RH
3150
3151 return out;
3152}
3153
3154/* Emit an X_floating library function call for a conversion. */
3155
3156void
64bb2e1d 3157alpha_emit_xfloating_cvt (enum rtx_code orig_code, rtx operands[])
5495cc55
RH
3158{
3159 int noperands = 1, mode;
c77f46c6 3160 rtx out_operands[2];
75959f0a 3161 rtx func;
64bb2e1d
RH
3162 enum rtx_code code = orig_code;
3163
3164 if (code == UNSIGNED_FIX)
3165 code = FIX;
5495cc55
RH
3166
3167 func = alpha_lookup_xfloating_lib_func (code);
3168
c77f46c6
AO
3169 out_operands[0] = operands[1];
3170
5495cc55
RH
3171 switch (code)
3172 {
3173 case FIX:
3174 mode = alpha_compute_xfloating_mode_arg (code, ALPHA_FPRM_CHOP);
c77f46c6 3175 out_operands[1] = GEN_INT (mode);
d6cde845 3176 noperands = 2;
5495cc55
RH
3177 break;
3178 case FLOAT_TRUNCATE:
3179 mode = alpha_compute_xfloating_mode_arg (code, alpha_fprm);
c77f46c6 3180 out_operands[1] = GEN_INT (mode);
d6cde845 3181 noperands = 2;
5495cc55
RH
3182 break;
3183 default:
3184 break;
3185 }
3186
c77f46c6 3187 alpha_emit_xfloating_libcall (func, operands[0], out_operands, noperands,
64bb2e1d
RH
3188 gen_rtx_fmt_e (orig_code,
3189 GET_MODE (operands[0]),
5495cc55
RH
3190 operands[1]));
3191}
628d74de 3192
b2f39494
EB
3193/* Split a TImode or TFmode move from OP[1] to OP[0] into a pair of
3194 DImode moves from OP[2,3] to OP[0,1]. If FIXUP_OVERLAP is true,
3195 guarantee that the sequence
3196 set (OP[0] OP[2])
3197 set (OP[1] OP[3])
3198 is valid. Naturally, output operand ordering is little-endian.
3199 This is used by *movtf_internal and *movti_internal. */
3200
628d74de 3201void
b2f39494
EB
3202alpha_split_tmode_pair (rtx operands[4], enum machine_mode mode,
3203 bool fixup_overlap)
628d74de 3204{
56daab84 3205 switch (GET_CODE (operands[1]))
628d74de 3206 {
56daab84 3207 case REG:
628d74de
RH
3208 operands[3] = gen_rtx_REG (DImode, REGNO (operands[1]) + 1);
3209 operands[2] = gen_rtx_REG (DImode, REGNO (operands[1]));
56daab84
NS
3210 break;
3211
3212 case MEM:
f4ef873c
RK
3213 operands[3] = adjust_address (operands[1], DImode, 8);
3214 operands[2] = adjust_address (operands[1], DImode, 0);
56daab84
NS
3215 break;
3216
b2f39494 3217 case CONST_INT:
65ab381c 3218 case CONST_DOUBLE:
b2f39494 3219 gcc_assert (operands[1] == CONST0_RTX (mode));
56daab84
NS
3220 operands[2] = operands[3] = const0_rtx;
3221 break;
3222
3223 default:
3224 gcc_unreachable ();
628d74de 3225 }
628d74de 3226
56daab84 3227 switch (GET_CODE (operands[0]))
628d74de 3228 {
56daab84 3229 case REG:
628d74de
RH
3230 operands[1] = gen_rtx_REG (DImode, REGNO (operands[0]) + 1);
3231 operands[0] = gen_rtx_REG (DImode, REGNO (operands[0]));
56daab84
NS
3232 break;
3233
3234 case MEM:
f4ef873c
RK
3235 operands[1] = adjust_address (operands[0], DImode, 8);
3236 operands[0] = adjust_address (operands[0], DImode, 0);
56daab84
NS
3237 break;
3238
3239 default:
3240 gcc_unreachable ();
628d74de 3241 }
b2f39494
EB
3242
3243 if (fixup_overlap && reg_overlap_mentioned_p (operands[0], operands[3]))
3244 {
3245 rtx tmp;
3246 tmp = operands[0], operands[0] = operands[1], operands[1] = tmp;
3247 tmp = operands[2], operands[2] = operands[3], operands[3] = tmp;
3248 }
628d74de 3249}
f940c352 3250
f676971a
EC
3251/* Implement negtf2 or abstf2. Op0 is destination, op1 is source,
3252 op2 is a register containing the sign bit, operation is the
f940c352
RH
3253 logical operation to be performed. */
3254
3255void
a5c24926 3256alpha_split_tfmode_frobsign (rtx operands[3], rtx (*operation) (rtx, rtx, rtx))
f940c352
RH
3257{
3258 rtx high_bit = operands[2];
3259 rtx scratch;
3260 int move;
3261
b2f39494 3262 alpha_split_tmode_pair (operands, TFmode, false);
f940c352 3263
825dda42 3264 /* Detect three flavors of operand overlap. */
f940c352
RH
3265 move = 1;
3266 if (rtx_equal_p (operands[0], operands[2]))
3267 move = 0;
3268 else if (rtx_equal_p (operands[1], operands[2]))
3269 {
3270 if (rtx_equal_p (operands[0], high_bit))
3271 move = 2;
3272 else
3273 move = -1;
3274 }
3275
3276 if (move < 0)
3277 emit_move_insn (operands[0], operands[2]);
3278
3279 /* ??? If the destination overlaps both source tf and high_bit, then
3280 assume source tf is dead in its entirety and use the other half
3281 for a scratch register. Otherwise "scratch" is just the proper
3282 destination register. */
3283 scratch = operands[move < 2 ? 1 : 3];
3284
3285 emit_insn ((*operation) (scratch, high_bit, operands[3]));
3286
3287 if (move > 0)
3288 {
3289 emit_move_insn (operands[0], operands[2]);
3290 if (move > 1)
3291 emit_move_insn (operands[1], scratch);
3292 }
3293}
5495cc55 3294\f
6c174fc0
RH
3295/* Use ext[wlq][lh] as the Architecture Handbook describes for extracting
3296 unaligned data:
3297
3298 unsigned: signed:
3299 word: ldq_u r1,X(r11) ldq_u r1,X(r11)
3300 ldq_u r2,X+1(r11) ldq_u r2,X+1(r11)
3301 lda r3,X(r11) lda r3,X+2(r11)
3302 extwl r1,r3,r1 extql r1,r3,r1
3303 extwh r2,r3,r2 extqh r2,r3,r2
3304 or r1.r2.r1 or r1,r2,r1
3305 sra r1,48,r1
3306
3307 long: ldq_u r1,X(r11) ldq_u r1,X(r11)
3308 ldq_u r2,X+3(r11) ldq_u r2,X+3(r11)
3309 lda r3,X(r11) lda r3,X(r11)
3310 extll r1,r3,r1 extll r1,r3,r1
3311 extlh r2,r3,r2 extlh r2,r3,r2
3312 or r1.r2.r1 addl r1,r2,r1
3313
3314 quad: ldq_u r1,X(r11)
3315 ldq_u r2,X+7(r11)
3316 lda r3,X(r11)
3317 extql r1,r3,r1
3318 extqh r2,r3,r2
3319 or r1.r2.r1
3320*/
3321
3322void
a5c24926
RH
3323alpha_expand_unaligned_load (rtx tgt, rtx mem, HOST_WIDE_INT size,
3324 HOST_WIDE_INT ofs, int sign)
6c174fc0 3325{
1eb356b9 3326 rtx meml, memh, addr, extl, exth, tmp, mema;
4208b40f 3327 enum machine_mode mode;
6c174fc0 3328
9f7d06d6
RH
3329 if (TARGET_BWX && size == 2)
3330 {
34642493
RH
3331 meml = adjust_address (mem, QImode, ofs);
3332 memh = adjust_address (mem, QImode, ofs+1);
9f7d06d6
RH
3333 if (BYTES_BIG_ENDIAN)
3334 tmp = meml, meml = memh, memh = tmp;
3335 extl = gen_reg_rtx (DImode);
3336 exth = gen_reg_rtx (DImode);
3337 emit_insn (gen_zero_extendqidi2 (extl, meml));
3338 emit_insn (gen_zero_extendqidi2 (exth, memh));
3339 exth = expand_simple_binop (DImode, ASHIFT, exth, GEN_INT (8),
3340 NULL, 1, OPTAB_LIB_WIDEN);
3341 addr = expand_simple_binop (DImode, IOR, extl, exth,
3342 NULL, 1, OPTAB_LIB_WIDEN);
3343
3344 if (sign && GET_MODE (tgt) != HImode)
3345 {
3346 addr = gen_lowpart (HImode, addr);
3347 emit_insn (gen_extend_insn (tgt, addr, GET_MODE (tgt), HImode, 0));
3348 }
3349 else
3350 {
3351 if (GET_MODE (tgt) != DImode)
3352 addr = gen_lowpart (GET_MODE (tgt), addr);
3353 emit_move_insn (tgt, addr);
3354 }
3355 return;
3356 }
3357
6c174fc0
RH
3358 meml = gen_reg_rtx (DImode);
3359 memh = gen_reg_rtx (DImode);
3360 addr = gen_reg_rtx (DImode);
3361 extl = gen_reg_rtx (DImode);
3362 exth = gen_reg_rtx (DImode);
3363
1eb356b9
RH
3364 mema = XEXP (mem, 0);
3365 if (GET_CODE (mema) == LO_SUM)
3366 mema = force_reg (Pmode, mema);
3367
e01acbb1 3368 /* AND addresses cannot be in any alias set, since they may implicitly
f676971a 3369 alias surrounding code. Ideally we'd have some alias set that
e01acbb1
RH
3370 covered all types except those with alignment 8 or higher. */
3371
3372 tmp = change_address (mem, DImode,
f676971a 3373 gen_rtx_AND (DImode,
1eb356b9 3374 plus_constant (mema, ofs),
e01acbb1 3375 GEN_INT (-8)));
ba4828e0 3376 set_mem_alias_set (tmp, 0);
e01acbb1
RH
3377 emit_move_insn (meml, tmp);
3378
3379 tmp = change_address (mem, DImode,
f676971a 3380 gen_rtx_AND (DImode,
1eb356b9 3381 plus_constant (mema, ofs + size - 1),
e01acbb1 3382 GEN_INT (-8)));
ba4828e0 3383 set_mem_alias_set (tmp, 0);
e01acbb1 3384 emit_move_insn (memh, tmp);
6c174fc0 3385
30102605
RH
3386 if (WORDS_BIG_ENDIAN && sign && (size == 2 || size == 4))
3387 {
3388 emit_move_insn (addr, plus_constant (mema, -1));
3389
3390 emit_insn (gen_extqh_be (extl, meml, addr));
3391 emit_insn (gen_extxl_be (exth, memh, GEN_INT (64), addr));
3392
3393 addr = expand_binop (DImode, ior_optab, extl, exth, tgt, 1, OPTAB_WIDEN);
3394 addr = expand_binop (DImode, ashr_optab, addr, GEN_INT (64 - size*8),
3395 addr, 1, OPTAB_WIDEN);
3396 }
3397 else if (sign && size == 2)
6c174fc0 3398 {
1eb356b9 3399 emit_move_insn (addr, plus_constant (mema, ofs+2));
6c174fc0 3400
30102605
RH
3401 emit_insn (gen_extxl_le (extl, meml, GEN_INT (64), addr));
3402 emit_insn (gen_extqh_le (exth, memh, addr));
6c174fc0 3403
1a7cb241
JW
3404 /* We must use tgt here for the target. Alpha-vms port fails if we use
3405 addr for the target, because addr is marked as a pointer and combine
a50aa827 3406 knows that pointers are always sign-extended 32-bit values. */
1a7cb241 3407 addr = expand_binop (DImode, ior_optab, extl, exth, tgt, 1, OPTAB_WIDEN);
f676971a 3408 addr = expand_binop (DImode, ashr_optab, addr, GEN_INT (48),
4208b40f 3409 addr, 1, OPTAB_WIDEN);
6c174fc0 3410 }
4208b40f 3411 else
6c174fc0 3412 {
30102605 3413 if (WORDS_BIG_ENDIAN)
4208b40f 3414 {
30102605
RH
3415 emit_move_insn (addr, plus_constant (mema, ofs+size-1));
3416 switch ((int) size)
3417 {
3418 case 2:
3419 emit_insn (gen_extwh_be (extl, meml, addr));
3420 mode = HImode;
3421 break;
6c174fc0 3422
30102605
RH
3423 case 4:
3424 emit_insn (gen_extlh_be (extl, meml, addr));
3425 mode = SImode;
3426 break;
6c174fc0 3427
30102605
RH
3428 case 8:
3429 emit_insn (gen_extqh_be (extl, meml, addr));
3430 mode = DImode;
3431 break;
5495cc55 3432
30102605 3433 default:
56daab84 3434 gcc_unreachable ();
30102605
RH
3435 }
3436 emit_insn (gen_extxl_be (exth, memh, GEN_INT (size*8), addr));
3437 }
3438 else
3439 {
3440 emit_move_insn (addr, plus_constant (mema, ofs));
3441 emit_insn (gen_extxl_le (extl, meml, GEN_INT (size*8), addr));
3442 switch ((int) size)
3443 {
3444 case 2:
3445 emit_insn (gen_extwh_le (exth, memh, addr));
3446 mode = HImode;
3447 break;
3448
3449 case 4:
3450 emit_insn (gen_extlh_le (exth, memh, addr));
3451 mode = SImode;
3452 break;
3453
3454 case 8:
3455 emit_insn (gen_extqh_le (exth, memh, addr));
3456 mode = DImode;
3457 break;
3458
3459 default:
56daab84 3460 gcc_unreachable ();
30102605 3461 }
4208b40f
RH
3462 }
3463
3464 addr = expand_binop (mode, ior_optab, gen_lowpart (mode, extl),
3465 gen_lowpart (mode, exth), gen_lowpart (mode, tgt),
3466 sign, OPTAB_WIDEN);
6c174fc0
RH
3467 }
3468
4208b40f 3469 if (addr != tgt)
9f7d06d6 3470 emit_move_insn (tgt, gen_lowpart (GET_MODE (tgt), addr));
6c174fc0
RH
3471}
3472
3473/* Similarly, use ins and msk instructions to perform unaligned stores. */
3474
3475void
a5c24926
RH
3476alpha_expand_unaligned_store (rtx dst, rtx src,
3477 HOST_WIDE_INT size, HOST_WIDE_INT ofs)
6c174fc0 3478{
1eb356b9 3479 rtx dstl, dsth, addr, insl, insh, meml, memh, dsta;
f676971a 3480
9f7d06d6
RH
3481 if (TARGET_BWX && size == 2)
3482 {
3483 if (src != const0_rtx)
3484 {
3485 dstl = gen_lowpart (QImode, src);
3486 dsth = expand_simple_binop (DImode, LSHIFTRT, src, GEN_INT (8),
3487 NULL, 1, OPTAB_LIB_WIDEN);
3488 dsth = gen_lowpart (QImode, dsth);
3489 }
3490 else
3491 dstl = dsth = const0_rtx;
3492
34642493
RH
3493 meml = adjust_address (dst, QImode, ofs);
3494 memh = adjust_address (dst, QImode, ofs+1);
9f7d06d6
RH
3495 if (BYTES_BIG_ENDIAN)
3496 addr = meml, meml = memh, memh = addr;
3497
3498 emit_move_insn (meml, dstl);
3499 emit_move_insn (memh, dsth);
3500 return;
3501 }
3502
6c174fc0
RH
3503 dstl = gen_reg_rtx (DImode);
3504 dsth = gen_reg_rtx (DImode);
3505 insl = gen_reg_rtx (DImode);
3506 insh = gen_reg_rtx (DImode);
3507
1eb356b9
RH
3508 dsta = XEXP (dst, 0);
3509 if (GET_CODE (dsta) == LO_SUM)
3510 dsta = force_reg (Pmode, dsta);
3511
e01acbb1 3512 /* AND addresses cannot be in any alias set, since they may implicitly
f676971a 3513 alias surrounding code. Ideally we'd have some alias set that
e01acbb1
RH
3514 covered all types except those with alignment 8 or higher. */
3515
6c174fc0 3516 meml = change_address (dst, DImode,
f676971a 3517 gen_rtx_AND (DImode,
1eb356b9 3518 plus_constant (dsta, ofs),
38a448ca 3519 GEN_INT (-8)));
ba4828e0 3520 set_mem_alias_set (meml, 0);
e01acbb1 3521
6c174fc0 3522 memh = change_address (dst, DImode,
f676971a 3523 gen_rtx_AND (DImode,
1eb356b9 3524 plus_constant (dsta, ofs + size - 1),
38a448ca 3525 GEN_INT (-8)));
ba4828e0 3526 set_mem_alias_set (memh, 0);
6c174fc0
RH
3527
3528 emit_move_insn (dsth, memh);
3529 emit_move_insn (dstl, meml);
30102605 3530 if (WORDS_BIG_ENDIAN)
6c174fc0 3531 {
30102605
RH
3532 addr = copy_addr_to_reg (plus_constant (dsta, ofs+size-1));
3533
3534 if (src != const0_rtx)
3535 {
3536 switch ((int) size)
3537 {
3538 case 2:
3539 emit_insn (gen_inswl_be (insh, gen_lowpart (HImode,src), addr));
3540 break;
3541 case 4:
3542 emit_insn (gen_insll_be (insh, gen_lowpart (SImode,src), addr));
3543 break;
3544 case 8:
3545 emit_insn (gen_insql_be (insh, gen_lowpart (DImode,src), addr));
3546 break;
3547 }
3548 emit_insn (gen_insxh (insl, gen_lowpart (DImode, src),
3549 GEN_INT (size*8), addr));
3550 }
6c174fc0 3551
c8d8ed65 3552 switch ((int) size)
6c174fc0
RH
3553 {
3554 case 2:
30102605 3555 emit_insn (gen_mskxl_be (dsth, dsth, GEN_INT (0xffff), addr));
6c174fc0
RH
3556 break;
3557 case 4:
30102605 3558 {
c4b50f1a 3559 rtx msk = immed_double_const (0xffffffff, 0, DImode);
30102605 3560 emit_insn (gen_mskxl_be (dsth, dsth, msk, addr));
c4b50f1a 3561 break;
30102605 3562 }
c4b50f1a
RH
3563 case 8:
3564 emit_insn (gen_mskxl_be (dsth, dsth, constm1_rtx, addr));
6c174fc0
RH
3565 break;
3566 }
30102605
RH
3567
3568 emit_insn (gen_mskxh (dstl, dstl, GEN_INT (size*8), addr));
6c174fc0 3569 }
30102605
RH
3570 else
3571 {
3572 addr = copy_addr_to_reg (plus_constant (dsta, ofs));
6c174fc0 3573
e2ea71ea 3574 if (src != CONST0_RTX (GET_MODE (src)))
30102605
RH
3575 {
3576 emit_insn (gen_insxh (insh, gen_lowpart (DImode, src),
3577 GEN_INT (size*8), addr));
6c174fc0 3578
30102605
RH
3579 switch ((int) size)
3580 {
3581 case 2:
3582 emit_insn (gen_inswl_le (insl, gen_lowpart (HImode, src), addr));
3583 break;
3584 case 4:
3585 emit_insn (gen_insll_le (insl, gen_lowpart (SImode, src), addr));
3586 break;
3587 case 8:
bc4eac6d 3588 emit_insn (gen_insql_le (insl, gen_lowpart (DImode, src), addr));
30102605
RH
3589 break;
3590 }
3591 }
3592
3593 emit_insn (gen_mskxh (dsth, dsth, GEN_INT (size*8), addr));
3594
3595 switch ((int) size)
3596 {
3597 case 2:
3598 emit_insn (gen_mskxl_le (dstl, dstl, GEN_INT (0xffff), addr));
3599 break;
3600 case 4:
30102605 3601 {
c4b50f1a 3602 rtx msk = immed_double_const (0xffffffff, 0, DImode);
30102605 3603 emit_insn (gen_mskxl_le (dstl, dstl, msk, addr));
c4b50f1a 3604 break;
30102605 3605 }
c4b50f1a
RH
3606 case 8:
3607 emit_insn (gen_mskxl_le (dstl, dstl, constm1_rtx, addr));
30102605
RH
3608 break;
3609 }
6c174fc0
RH
3610 }
3611
e2ea71ea 3612 if (src != CONST0_RTX (GET_MODE (src)))
6c174fc0 3613 {
4208b40f
RH
3614 dsth = expand_binop (DImode, ior_optab, insh, dsth, dsth, 0, OPTAB_WIDEN);
3615 dstl = expand_binop (DImode, ior_optab, insl, dstl, dstl, 0, OPTAB_WIDEN);
6c174fc0 3616 }
f676971a 3617
30102605
RH
3618 if (WORDS_BIG_ENDIAN)
3619 {
3620 emit_move_insn (meml, dstl);
3621 emit_move_insn (memh, dsth);
3622 }
3623 else
3624 {
3625 /* Must store high before low for degenerate case of aligned. */
3626 emit_move_insn (memh, dsth);
3627 emit_move_insn (meml, dstl);
3628 }
6c174fc0
RH
3629}
3630
4208b40f
RH
3631/* The block move code tries to maximize speed by separating loads and
3632 stores at the expense of register pressure: we load all of the data
3633 before we store it back out. There are two secondary effects worth
3634 mentioning, that this speeds copying to/from aligned and unaligned
3635 buffers, and that it makes the code significantly easier to write. */
6c174fc0 3636
4208b40f
RH
3637#define MAX_MOVE_WORDS 8
3638
3639/* Load an integral number of consecutive unaligned quadwords. */
6c174fc0
RH
3640
3641static void
a5c24926
RH
3642alpha_expand_unaligned_load_words (rtx *out_regs, rtx smem,
3643 HOST_WIDE_INT words, HOST_WIDE_INT ofs)
6c174fc0
RH
3644{
3645 rtx const im8 = GEN_INT (-8);
3646 rtx const i64 = GEN_INT (64);
4208b40f 3647 rtx ext_tmps[MAX_MOVE_WORDS], data_regs[MAX_MOVE_WORDS+1];
1eb356b9 3648 rtx sreg, areg, tmp, smema;
6c174fc0
RH
3649 HOST_WIDE_INT i;
3650
1eb356b9
RH
3651 smema = XEXP (smem, 0);
3652 if (GET_CODE (smema) == LO_SUM)
3653 smema = force_reg (Pmode, smema);
3654
6c174fc0
RH
3655 /* Generate all the tmp registers we need. */
3656 for (i = 0; i < words; ++i)
4208b40f
RH
3657 {
3658 data_regs[i] = out_regs[i];
3659 ext_tmps[i] = gen_reg_rtx (DImode);
3660 }
3661 data_regs[words] = gen_reg_rtx (DImode);
3662
3663 if (ofs != 0)
f4ef873c 3664 smem = adjust_address (smem, GET_MODE (smem), ofs);
f676971a 3665
6c174fc0
RH
3666 /* Load up all of the source data. */
3667 for (i = 0; i < words; ++i)
3668 {
e01acbb1
RH
3669 tmp = change_address (smem, DImode,
3670 gen_rtx_AND (DImode,
1eb356b9 3671 plus_constant (smema, 8*i),
e01acbb1 3672 im8));
ba4828e0 3673 set_mem_alias_set (tmp, 0);
e01acbb1 3674 emit_move_insn (data_regs[i], tmp);
6c174fc0 3675 }
e01acbb1
RH
3676
3677 tmp = change_address (smem, DImode,
3678 gen_rtx_AND (DImode,
1eb356b9 3679 plus_constant (smema, 8*words - 1),
e01acbb1 3680 im8));
ba4828e0 3681 set_mem_alias_set (tmp, 0);
e01acbb1 3682 emit_move_insn (data_regs[words], tmp);
6c174fc0
RH
3683
3684 /* Extract the half-word fragments. Unfortunately DEC decided to make
f676971a 3685 extxh with offset zero a noop instead of zeroing the register, so
6c174fc0
RH
3686 we must take care of that edge condition ourselves with cmov. */
3687
1eb356b9 3688 sreg = copy_addr_to_reg (smema);
f676971a 3689 areg = expand_binop (DImode, and_optab, sreg, GEN_INT (7), NULL,
4208b40f 3690 1, OPTAB_WIDEN);
30102605
RH
3691 if (WORDS_BIG_ENDIAN)
3692 emit_move_insn (sreg, plus_constant (sreg, 7));
6c174fc0
RH
3693 for (i = 0; i < words; ++i)
3694 {
30102605
RH
3695 if (WORDS_BIG_ENDIAN)
3696 {
3697 emit_insn (gen_extqh_be (data_regs[i], data_regs[i], sreg));
3698 emit_insn (gen_extxl_be (ext_tmps[i], data_regs[i+1], i64, sreg));
3699 }
3700 else
3701 {
3702 emit_insn (gen_extxl_le (data_regs[i], data_regs[i], i64, sreg));
3703 emit_insn (gen_extqh_le (ext_tmps[i], data_regs[i+1], sreg));
3704 }
38a448ca
RH
3705 emit_insn (gen_rtx_SET (VOIDmode, ext_tmps[i],
3706 gen_rtx_IF_THEN_ELSE (DImode,
4208b40f
RH
3707 gen_rtx_EQ (DImode, areg,
3708 const0_rtx),
38a448ca 3709 const0_rtx, ext_tmps[i])));
6c174fc0
RH
3710 }
3711
3712 /* Merge the half-words into whole words. */
3713 for (i = 0; i < words; ++i)
3714 {
4208b40f
RH
3715 out_regs[i] = expand_binop (DImode, ior_optab, data_regs[i],
3716 ext_tmps[i], data_regs[i], 1, OPTAB_WIDEN);
6c174fc0
RH
3717 }
3718}
3719
3720/* Store an integral number of consecutive unaligned quadwords. DATA_REGS
3721 may be NULL to store zeros. */
3722
3723static void
a5c24926
RH
3724alpha_expand_unaligned_store_words (rtx *data_regs, rtx dmem,
3725 HOST_WIDE_INT words, HOST_WIDE_INT ofs)
6c174fc0
RH
3726{
3727 rtx const im8 = GEN_INT (-8);
3728 rtx const i64 = GEN_INT (64);
6c174fc0 3729 rtx ins_tmps[MAX_MOVE_WORDS];
4208b40f 3730 rtx st_tmp_1, st_tmp_2, dreg;
1eb356b9 3731 rtx st_addr_1, st_addr_2, dmema;
6c174fc0
RH
3732 HOST_WIDE_INT i;
3733
1eb356b9
RH
3734 dmema = XEXP (dmem, 0);
3735 if (GET_CODE (dmema) == LO_SUM)
3736 dmema = force_reg (Pmode, dmema);
3737
6c174fc0
RH
3738 /* Generate all the tmp registers we need. */
3739 if (data_regs != NULL)
3740 for (i = 0; i < words; ++i)
3741 ins_tmps[i] = gen_reg_rtx(DImode);
3742 st_tmp_1 = gen_reg_rtx(DImode);
3743 st_tmp_2 = gen_reg_rtx(DImode);
f676971a 3744
4208b40f 3745 if (ofs != 0)
f4ef873c 3746 dmem = adjust_address (dmem, GET_MODE (dmem), ofs);
4208b40f
RH
3747
3748 st_addr_2 = change_address (dmem, DImode,
38a448ca 3749 gen_rtx_AND (DImode,
1eb356b9 3750 plus_constant (dmema, words*8 - 1),
6c174fc0 3751 im8));
ba4828e0 3752 set_mem_alias_set (st_addr_2, 0);
e01acbb1 3753
4208b40f 3754 st_addr_1 = change_address (dmem, DImode,
1eb356b9 3755 gen_rtx_AND (DImode, dmema, im8));
ba4828e0 3756 set_mem_alias_set (st_addr_1, 0);
6c174fc0
RH
3757
3758 /* Load up the destination end bits. */
3759 emit_move_insn (st_tmp_2, st_addr_2);
3760 emit_move_insn (st_tmp_1, st_addr_1);
3761
3762 /* Shift the input data into place. */
1eb356b9 3763 dreg = copy_addr_to_reg (dmema);
30102605
RH
3764 if (WORDS_BIG_ENDIAN)
3765 emit_move_insn (dreg, plus_constant (dreg, 7));
6c174fc0
RH
3766 if (data_regs != NULL)
3767 {
3768 for (i = words-1; i >= 0; --i)
3769 {
30102605
RH
3770 if (WORDS_BIG_ENDIAN)
3771 {
3772 emit_insn (gen_insql_be (ins_tmps[i], data_regs[i], dreg));
3773 emit_insn (gen_insxh (data_regs[i], data_regs[i], i64, dreg));
3774 }
3775 else
3776 {
3777 emit_insn (gen_insxh (ins_tmps[i], data_regs[i], i64, dreg));
3778 emit_insn (gen_insql_le (data_regs[i], data_regs[i], dreg));
3779 }
6c174fc0 3780 }
6c174fc0
RH
3781 for (i = words-1; i > 0; --i)
3782 {
4208b40f
RH
3783 ins_tmps[i-1] = expand_binop (DImode, ior_optab, data_regs[i],
3784 ins_tmps[i-1], ins_tmps[i-1], 1,
3785 OPTAB_WIDEN);
6c174fc0
RH
3786 }
3787 }
3788
3789 /* Split and merge the ends with the destination data. */
30102605
RH
3790 if (WORDS_BIG_ENDIAN)
3791 {
c4b50f1a 3792 emit_insn (gen_mskxl_be (st_tmp_2, st_tmp_2, constm1_rtx, dreg));
30102605
RH
3793 emit_insn (gen_mskxh (st_tmp_1, st_tmp_1, i64, dreg));
3794 }
3795 else
3796 {
3797 emit_insn (gen_mskxh (st_tmp_2, st_tmp_2, i64, dreg));
c4b50f1a 3798 emit_insn (gen_mskxl_le (st_tmp_1, st_tmp_1, constm1_rtx, dreg));
30102605 3799 }
6c174fc0
RH
3800
3801 if (data_regs != NULL)
3802 {
4208b40f
RH
3803 st_tmp_2 = expand_binop (DImode, ior_optab, st_tmp_2, ins_tmps[words-1],
3804 st_tmp_2, 1, OPTAB_WIDEN);
3805 st_tmp_1 = expand_binop (DImode, ior_optab, st_tmp_1, data_regs[0],
3806 st_tmp_1, 1, OPTAB_WIDEN);
6c174fc0
RH
3807 }
3808
3809 /* Store it all. */
30102605
RH
3810 if (WORDS_BIG_ENDIAN)
3811 emit_move_insn (st_addr_1, st_tmp_1);
3812 else
3813 emit_move_insn (st_addr_2, st_tmp_2);
6c174fc0
RH
3814 for (i = words-1; i > 0; --i)
3815 {
e01acbb1
RH
3816 rtx tmp = change_address (dmem, DImode,
3817 gen_rtx_AND (DImode,
30102605
RH
3818 plus_constant(dmema,
3819 WORDS_BIG_ENDIAN ? i*8-1 : i*8),
e01acbb1 3820 im8));
ba4828e0 3821 set_mem_alias_set (tmp, 0);
e01acbb1 3822 emit_move_insn (tmp, data_regs ? ins_tmps[i-1] : const0_rtx);
6c174fc0 3823 }
30102605
RH
3824 if (WORDS_BIG_ENDIAN)
3825 emit_move_insn (st_addr_2, st_tmp_2);
3826 else
3827 emit_move_insn (st_addr_1, st_tmp_1);
6c174fc0
RH
3828}
3829
3830
3831/* Expand string/block move operations.
3832
3833 operands[0] is the pointer to the destination.
3834 operands[1] is the pointer to the source.
3835 operands[2] is the number of bytes to move.
3836 operands[3] is the alignment. */
3837
3838int
a5c24926 3839alpha_expand_block_move (rtx operands[])
6c174fc0
RH
3840{
3841 rtx bytes_rtx = operands[2];
3842 rtx align_rtx = operands[3];
f35cba21 3843 HOST_WIDE_INT orig_bytes = INTVAL (bytes_rtx);
c17f08e1
RH
3844 HOST_WIDE_INT bytes = orig_bytes;
3845 HOST_WIDE_INT src_align = INTVAL (align_rtx) * BITS_PER_UNIT;
3846 HOST_WIDE_INT dst_align = src_align;
bdb429a5
RK
3847 rtx orig_src = operands[1];
3848 rtx orig_dst = operands[0];
3849 rtx data_regs[2 * MAX_MOVE_WORDS + 16];
4208b40f 3850 rtx tmp;
1eb356b9 3851 unsigned int i, words, ofs, nregs = 0;
f676971a 3852
bdb429a5 3853 if (orig_bytes <= 0)
6c174fc0 3854 return 1;
c17f08e1 3855 else if (orig_bytes > MAX_MOVE_WORDS * UNITS_PER_WORD)
6c174fc0
RH
3856 return 0;
3857
4208b40f
RH
3858 /* Look for additional alignment information from recorded register info. */
3859
3860 tmp = XEXP (orig_src, 0);
7d83f4f5 3861 if (REG_P (tmp))
bdb429a5 3862 src_align = MAX (src_align, REGNO_POINTER_ALIGN (REGNO (tmp)));
4208b40f 3863 else if (GET_CODE (tmp) == PLUS
7d83f4f5
UB
3864 && REG_P (XEXP (tmp, 0))
3865 && CONST_INT_P (XEXP (tmp, 1)))
4208b40f 3866 {
bdb429a5
RK
3867 unsigned HOST_WIDE_INT c = INTVAL (XEXP (tmp, 1));
3868 unsigned int a = REGNO_POINTER_ALIGN (REGNO (XEXP (tmp, 0)));
4208b40f
RH
3869
3870 if (a > src_align)
3871 {
bdb429a5
RK
3872 if (a >= 64 && c % 8 == 0)
3873 src_align = 64;
3874 else if (a >= 32 && c % 4 == 0)
3875 src_align = 32;
3876 else if (a >= 16 && c % 2 == 0)
3877 src_align = 16;
4208b40f
RH
3878 }
3879 }
f676971a 3880
4208b40f 3881 tmp = XEXP (orig_dst, 0);
7d83f4f5 3882 if (REG_P (tmp))
bdb429a5 3883 dst_align = MAX (dst_align, REGNO_POINTER_ALIGN (REGNO (tmp)));
4208b40f 3884 else if (GET_CODE (tmp) == PLUS
7d83f4f5
UB
3885 && REG_P (XEXP (tmp, 0))
3886 && CONST_INT_P (XEXP (tmp, 1)))
4208b40f 3887 {
bdb429a5
RK
3888 unsigned HOST_WIDE_INT c = INTVAL (XEXP (tmp, 1));
3889 unsigned int a = REGNO_POINTER_ALIGN (REGNO (XEXP (tmp, 0)));
4208b40f
RH
3890
3891 if (a > dst_align)
3892 {
bdb429a5
RK
3893 if (a >= 64 && c % 8 == 0)
3894 dst_align = 64;
3895 else if (a >= 32 && c % 4 == 0)
3896 dst_align = 32;
3897 else if (a >= 16 && c % 2 == 0)
3898 dst_align = 16;
4208b40f
RH
3899 }
3900 }
3901
4208b40f 3902 ofs = 0;
bdb429a5 3903 if (src_align >= 64 && bytes >= 8)
6c174fc0
RH
3904 {
3905 words = bytes / 8;
3906
6c174fc0 3907 for (i = 0; i < words; ++i)
5197bd50 3908 data_regs[nregs + i] = gen_reg_rtx (DImode);
6c174fc0 3909
6c174fc0 3910 for (i = 0; i < words; ++i)
bdb429a5 3911 emit_move_insn (data_regs[nregs + i],
f4ef873c 3912 adjust_address (orig_src, DImode, ofs + i * 8));
6c174fc0 3913
4208b40f 3914 nregs += words;
6c174fc0 3915 bytes -= words * 8;
cd36edbd 3916 ofs += words * 8;
6c174fc0 3917 }
bdb429a5
RK
3918
3919 if (src_align >= 32 && bytes >= 4)
6c174fc0
RH
3920 {
3921 words = bytes / 4;
3922
6c174fc0 3923 for (i = 0; i < words; ++i)
5197bd50 3924 data_regs[nregs + i] = gen_reg_rtx (SImode);
6c174fc0 3925
6c174fc0 3926 for (i = 0; i < words; ++i)
bdb429a5 3927 emit_move_insn (data_regs[nregs + i],
792760b9 3928 adjust_address (orig_src, SImode, ofs + i * 4));
6c174fc0 3929
4208b40f 3930 nregs += words;
6c174fc0 3931 bytes -= words * 4;
cd36edbd 3932 ofs += words * 4;
6c174fc0 3933 }
bdb429a5 3934
c17f08e1 3935 if (bytes >= 8)
6c174fc0
RH
3936 {
3937 words = bytes / 8;
3938
6c174fc0 3939 for (i = 0; i < words+1; ++i)
5197bd50 3940 data_regs[nregs + i] = gen_reg_rtx (DImode);
6c174fc0 3941
c576fce7
RH
3942 alpha_expand_unaligned_load_words (data_regs + nregs, orig_src,
3943 words, ofs);
6c174fc0 3944
4208b40f 3945 nregs += words;
6c174fc0 3946 bytes -= words * 8;
cd36edbd 3947 ofs += words * 8;
6c174fc0 3948 }
bdb429a5 3949
bdb429a5 3950 if (! TARGET_BWX && bytes >= 4)
6c174fc0 3951 {
4208b40f 3952 data_regs[nregs++] = tmp = gen_reg_rtx (SImode);
6c174fc0 3953 alpha_expand_unaligned_load (tmp, orig_src, 4, ofs, 0);
6c174fc0
RH
3954 bytes -= 4;
3955 ofs += 4;
3956 }
bdb429a5 3957
6c174fc0
RH
3958 if (bytes >= 2)
3959 {
bdb429a5 3960 if (src_align >= 16)
6c174fc0
RH
3961 {
3962 do {
4208b40f 3963 data_regs[nregs++] = tmp = gen_reg_rtx (HImode);
f4ef873c 3964 emit_move_insn (tmp, adjust_address (orig_src, HImode, ofs));
6c174fc0
RH
3965 bytes -= 2;
3966 ofs += 2;
3967 } while (bytes >= 2);
3968 }
bdb429a5 3969 else if (! TARGET_BWX)
6c174fc0 3970 {
4208b40f 3971 data_regs[nregs++] = tmp = gen_reg_rtx (HImode);
6c174fc0 3972 alpha_expand_unaligned_load (tmp, orig_src, 2, ofs, 0);
6c174fc0
RH
3973 bytes -= 2;
3974 ofs += 2;
3975 }
3976 }
bdb429a5 3977
6c174fc0
RH
3978 while (bytes > 0)
3979 {
4208b40f 3980 data_regs[nregs++] = tmp = gen_reg_rtx (QImode);
f4ef873c 3981 emit_move_insn (tmp, adjust_address (orig_src, QImode, ofs));
6c174fc0
RH
3982 bytes -= 1;
3983 ofs += 1;
3984 }
bdb429a5 3985
56daab84 3986 gcc_assert (nregs <= ARRAY_SIZE (data_regs));
4208b40f 3987
bdb429a5 3988 /* Now save it back out again. */
4208b40f
RH
3989
3990 i = 0, ofs = 0;
3991
4208b40f 3992 /* Write out the data in whatever chunks reading the source allowed. */
bdb429a5 3993 if (dst_align >= 64)
4208b40f
RH
3994 {
3995 while (i < nregs && GET_MODE (data_regs[i]) == DImode)
3996 {
f4ef873c 3997 emit_move_insn (adjust_address (orig_dst, DImode, ofs),
4208b40f
RH
3998 data_regs[i]);
3999 ofs += 8;
4000 i++;
4001 }
4002 }
bdb429a5
RK
4003
4004 if (dst_align >= 32)
4208b40f
RH
4005 {
4006 /* If the source has remaining DImode regs, write them out in
4007 two pieces. */
4008 while (i < nregs && GET_MODE (data_regs[i]) == DImode)
4009 {
4010 tmp = expand_binop (DImode, lshr_optab, data_regs[i], GEN_INT (32),
4011 NULL_RTX, 1, OPTAB_WIDEN);
4012
f4ef873c 4013 emit_move_insn (adjust_address (orig_dst, SImode, ofs),
4208b40f 4014 gen_lowpart (SImode, data_regs[i]));
f4ef873c 4015 emit_move_insn (adjust_address (orig_dst, SImode, ofs + 4),
4208b40f
RH
4016 gen_lowpart (SImode, tmp));
4017 ofs += 8;
4018 i++;
4019 }
4020
4021 while (i < nregs && GET_MODE (data_regs[i]) == SImode)
4022 {
f4ef873c 4023 emit_move_insn (adjust_address (orig_dst, SImode, ofs),
4208b40f
RH
4024 data_regs[i]);
4025 ofs += 4;
4026 i++;
4027 }
4028 }
bdb429a5 4029
4208b40f
RH
4030 if (i < nregs && GET_MODE (data_regs[i]) == DImode)
4031 {
4032 /* Write out a remaining block of words using unaligned methods. */
4033
bdb429a5
RK
4034 for (words = 1; i + words < nregs; words++)
4035 if (GET_MODE (data_regs[i + words]) != DImode)
4208b40f
RH
4036 break;
4037
4038 if (words == 1)
4039 alpha_expand_unaligned_store (orig_dst, data_regs[i], 8, ofs);
4040 else
bdb429a5
RK
4041 alpha_expand_unaligned_store_words (data_regs + i, orig_dst,
4042 words, ofs);
f676971a 4043
4208b40f
RH
4044 i += words;
4045 ofs += words * 8;
4046 }
4047
4048 /* Due to the above, this won't be aligned. */
4049 /* ??? If we have more than one of these, consider constructing full
4050 words in registers and using alpha_expand_unaligned_store_words. */
4051 while (i < nregs && GET_MODE (data_regs[i]) == SImode)
4052 {
4053 alpha_expand_unaligned_store (orig_dst, data_regs[i], 4, ofs);
4054 ofs += 4;
4055 i++;
4056 }
4057
bdb429a5 4058 if (dst_align >= 16)
4208b40f
RH
4059 while (i < nregs && GET_MODE (data_regs[i]) == HImode)
4060 {
f4ef873c 4061 emit_move_insn (adjust_address (orig_dst, HImode, ofs), data_regs[i]);
4208b40f
RH
4062 i++;
4063 ofs += 2;
4064 }
4065 else
4066 while (i < nregs && GET_MODE (data_regs[i]) == HImode)
4067 {
4068 alpha_expand_unaligned_store (orig_dst, data_regs[i], 2, ofs);
4069 i++;
4070 ofs += 2;
4071 }
bdb429a5 4072
56daab84
NS
4073 /* The remainder must be byte copies. */
4074 while (i < nregs)
4208b40f 4075 {
56daab84 4076 gcc_assert (GET_MODE (data_regs[i]) == QImode);
f4ef873c 4077 emit_move_insn (adjust_address (orig_dst, QImode, ofs), data_regs[i]);
4208b40f
RH
4078 i++;
4079 ofs += 1;
4080 }
bdb429a5 4081
6c174fc0
RH
4082 return 1;
4083}
4084
4085int
a5c24926 4086alpha_expand_block_clear (rtx operands[])
6c174fc0
RH
4087{
4088 rtx bytes_rtx = operands[1];
57e84f18 4089 rtx align_rtx = operands[3];
bdb429a5 4090 HOST_WIDE_INT orig_bytes = INTVAL (bytes_rtx);
c17f08e1
RH
4091 HOST_WIDE_INT bytes = orig_bytes;
4092 HOST_WIDE_INT align = INTVAL (align_rtx) * BITS_PER_UNIT;
4093 HOST_WIDE_INT alignofs = 0;
bdb429a5 4094 rtx orig_dst = operands[0];
4208b40f 4095 rtx tmp;
c17f08e1 4096 int i, words, ofs = 0;
f676971a 4097
bdb429a5 4098 if (orig_bytes <= 0)
6c174fc0 4099 return 1;
c17f08e1 4100 if (orig_bytes > MAX_MOVE_WORDS * UNITS_PER_WORD)
6c174fc0
RH
4101 return 0;
4102
4208b40f 4103 /* Look for stricter alignment. */
4208b40f 4104 tmp = XEXP (orig_dst, 0);
7d83f4f5 4105 if (REG_P (tmp))
bdb429a5 4106 align = MAX (align, REGNO_POINTER_ALIGN (REGNO (tmp)));
4208b40f 4107 else if (GET_CODE (tmp) == PLUS
7d83f4f5
UB
4108 && REG_P (XEXP (tmp, 0))
4109 && CONST_INT_P (XEXP (tmp, 1)))
4208b40f 4110 {
c17f08e1
RH
4111 HOST_WIDE_INT c = INTVAL (XEXP (tmp, 1));
4112 int a = REGNO_POINTER_ALIGN (REGNO (XEXP (tmp, 0)));
4208b40f
RH
4113
4114 if (a > align)
4115 {
c17f08e1
RH
4116 if (a >= 64)
4117 align = a, alignofs = 8 - c % 8;
4118 else if (a >= 32)
4119 align = a, alignofs = 4 - c % 4;
4120 else if (a >= 16)
4121 align = a, alignofs = 2 - c % 2;
4208b40f
RH
4122 }
4123 }
4124
c17f08e1
RH
4125 /* Handle an unaligned prefix first. */
4126
4127 if (alignofs > 0)
4128 {
4129#if HOST_BITS_PER_WIDE_INT >= 64
4130 /* Given that alignofs is bounded by align, the only time BWX could
4131 generate three stores is for a 7 byte fill. Prefer two individual
4132 stores over a load/mask/store sequence. */
4133 if ((!TARGET_BWX || alignofs == 7)
4134 && align >= 32
4135 && !(alignofs == 4 && bytes >= 4))
4136 {
4137 enum machine_mode mode = (align >= 64 ? DImode : SImode);
4138 int inv_alignofs = (align >= 64 ? 8 : 4) - alignofs;
4139 rtx mem, tmp;
4140 HOST_WIDE_INT mask;
4141
f4ef873c 4142 mem = adjust_address (orig_dst, mode, ofs - inv_alignofs);
ba4828e0 4143 set_mem_alias_set (mem, 0);
c17f08e1
RH
4144
4145 mask = ~(~(HOST_WIDE_INT)0 << (inv_alignofs * 8));
4146 if (bytes < alignofs)
4147 {
4148 mask |= ~(HOST_WIDE_INT)0 << ((inv_alignofs + bytes) * 8);
4149 ofs += bytes;
4150 bytes = 0;
4151 }
4152 else
4153 {
4154 bytes -= alignofs;
4155 ofs += alignofs;
4156 }
4157 alignofs = 0;
4158
4159 tmp = expand_binop (mode, and_optab, mem, GEN_INT (mask),
4160 NULL_RTX, 1, OPTAB_WIDEN);
4161
4162 emit_move_insn (mem, tmp);
4163 }
4164#endif
4165
4166 if (TARGET_BWX && (alignofs & 1) && bytes >= 1)
4167 {
f4ef873c 4168 emit_move_insn (adjust_address (orig_dst, QImode, ofs), const0_rtx);
c17f08e1
RH
4169 bytes -= 1;
4170 ofs += 1;
4171 alignofs -= 1;
4172 }
4173 if (TARGET_BWX && align >= 16 && (alignofs & 3) == 2 && bytes >= 2)
4174 {
f4ef873c 4175 emit_move_insn (adjust_address (orig_dst, HImode, ofs), const0_rtx);
c17f08e1
RH
4176 bytes -= 2;
4177 ofs += 2;
4178 alignofs -= 2;
4179 }
4180 if (alignofs == 4 && bytes >= 4)
4181 {
f4ef873c 4182 emit_move_insn (adjust_address (orig_dst, SImode, ofs), const0_rtx);
c17f08e1
RH
4183 bytes -= 4;
4184 ofs += 4;
4185 alignofs = 0;
4186 }
4187
4188 /* If we've not used the extra lead alignment information by now,
4189 we won't be able to. Downgrade align to match what's left over. */
4190 if (alignofs > 0)
4191 {
4192 alignofs = alignofs & -alignofs;
4193 align = MIN (align, alignofs * BITS_PER_UNIT);
4194 }
4195 }
4196
4197 /* Handle a block of contiguous long-words. */
6c174fc0 4198
bdb429a5 4199 if (align >= 64 && bytes >= 8)
6c174fc0
RH
4200 {
4201 words = bytes / 8;
4202
4203 for (i = 0; i < words; ++i)
1eb356b9 4204 emit_move_insn (adjust_address (orig_dst, DImode, ofs + i * 8),
f4ef873c 4205 const0_rtx);
6c174fc0
RH
4206
4207 bytes -= words * 8;
cd36edbd 4208 ofs += words * 8;
6c174fc0 4209 }
bdb429a5 4210
c17f08e1
RH
4211 /* If the block is large and appropriately aligned, emit a single
4212 store followed by a sequence of stq_u insns. */
4213
4214 if (align >= 32 && bytes > 16)
4215 {
1eb356b9
RH
4216 rtx orig_dsta;
4217
f4ef873c 4218 emit_move_insn (adjust_address (orig_dst, SImode, ofs), const0_rtx);
c17f08e1
RH
4219 bytes -= 4;
4220 ofs += 4;
4221
1eb356b9
RH
4222 orig_dsta = XEXP (orig_dst, 0);
4223 if (GET_CODE (orig_dsta) == LO_SUM)
4224 orig_dsta = force_reg (Pmode, orig_dsta);
4225
c17f08e1
RH
4226 words = bytes / 8;
4227 for (i = 0; i < words; ++i)
4228 {
ba4828e0
RK
4229 rtx mem
4230 = change_address (orig_dst, DImode,
4231 gen_rtx_AND (DImode,
1eb356b9 4232 plus_constant (orig_dsta, ofs + i*8),
ba4828e0
RK
4233 GEN_INT (-8)));
4234 set_mem_alias_set (mem, 0);
c17f08e1
RH
4235 emit_move_insn (mem, const0_rtx);
4236 }
4237
4238 /* Depending on the alignment, the first stq_u may have overlapped
4239 with the initial stl, which means that the last stq_u didn't
4240 write as much as it would appear. Leave those questionable bytes
4241 unaccounted for. */
4242 bytes -= words * 8 - 4;
4243 ofs += words * 8 - 4;
4244 }
4245
4246 /* Handle a smaller block of aligned words. */
4247
4248 if ((align >= 64 && bytes == 4)
4249 || (align == 32 && bytes >= 4))
6c174fc0
RH
4250 {
4251 words = bytes / 4;
4252
4253 for (i = 0; i < words; ++i)
f4ef873c 4254 emit_move_insn (adjust_address (orig_dst, SImode, ofs + i * 4),
bdb429a5 4255 const0_rtx);
6c174fc0
RH
4256
4257 bytes -= words * 4;
cd36edbd 4258 ofs += words * 4;
6c174fc0 4259 }
bdb429a5 4260
c17f08e1
RH
4261 /* An unaligned block uses stq_u stores for as many as possible. */
4262
4263 if (bytes >= 8)
6c174fc0
RH
4264 {
4265 words = bytes / 8;
4266
cd36edbd 4267 alpha_expand_unaligned_store_words (NULL, orig_dst, words, ofs);
6c174fc0
RH
4268
4269 bytes -= words * 8;
cd36edbd 4270 ofs += words * 8;
6c174fc0
RH
4271 }
4272
c17f08e1 4273 /* Next clean up any trailing pieces. */
6c174fc0 4274
c17f08e1
RH
4275#if HOST_BITS_PER_WIDE_INT >= 64
4276 /* Count the number of bits in BYTES for which aligned stores could
4277 be emitted. */
4278 words = 0;
4279 for (i = (TARGET_BWX ? 1 : 4); i * BITS_PER_UNIT <= align ; i <<= 1)
4280 if (bytes & i)
4281 words += 1;
4282
4283 /* If we have appropriate alignment (and it wouldn't take too many
4284 instructions otherwise), mask out the bytes we need. */
4285 if (TARGET_BWX ? words > 2 : bytes > 0)
4286 {
4287 if (align >= 64)
4288 {
4289 rtx mem, tmp;
4290 HOST_WIDE_INT mask;
4291
f4ef873c 4292 mem = adjust_address (orig_dst, DImode, ofs);
ba4828e0 4293 set_mem_alias_set (mem, 0);
c17f08e1
RH
4294
4295 mask = ~(HOST_WIDE_INT)0 << (bytes * 8);
4296
4297 tmp = expand_binop (DImode, and_optab, mem, GEN_INT (mask),
4298 NULL_RTX, 1, OPTAB_WIDEN);
4299
4300 emit_move_insn (mem, tmp);
4301 return 1;
4302 }
4303 else if (align >= 32 && bytes < 4)
4304 {
4305 rtx mem, tmp;
4306 HOST_WIDE_INT mask;
4307
f4ef873c 4308 mem = adjust_address (orig_dst, SImode, ofs);
ba4828e0 4309 set_mem_alias_set (mem, 0);
c17f08e1
RH
4310
4311 mask = ~(HOST_WIDE_INT)0 << (bytes * 8);
4312
4313 tmp = expand_binop (SImode, and_optab, mem, GEN_INT (mask),
4314 NULL_RTX, 1, OPTAB_WIDEN);
4315
4316 emit_move_insn (mem, tmp);
4317 return 1;
4318 }
6c174fc0 4319 }
c17f08e1 4320#endif
bdb429a5 4321
6c174fc0
RH
4322 if (!TARGET_BWX && bytes >= 4)
4323 {
4324 alpha_expand_unaligned_store (orig_dst, const0_rtx, 4, ofs);
4325 bytes -= 4;
4326 ofs += 4;
4327 }
bdb429a5 4328
6c174fc0
RH
4329 if (bytes >= 2)
4330 {
bdb429a5 4331 if (align >= 16)
6c174fc0
RH
4332 {
4333 do {
f4ef873c 4334 emit_move_insn (adjust_address (orig_dst, HImode, ofs),
6c174fc0
RH
4335 const0_rtx);
4336 bytes -= 2;
4337 ofs += 2;
4338 } while (bytes >= 2);
4339 }
bdb429a5 4340 else if (! TARGET_BWX)
6c174fc0
RH
4341 {
4342 alpha_expand_unaligned_store (orig_dst, const0_rtx, 2, ofs);
4343 bytes -= 2;
4344 ofs += 2;
4345 }
4346 }
bdb429a5 4347
6c174fc0
RH
4348 while (bytes > 0)
4349 {
f4ef873c 4350 emit_move_insn (adjust_address (orig_dst, QImode, ofs), const0_rtx);
6c174fc0
RH
4351 bytes -= 1;
4352 ofs += 1;
4353 }
4354
4355 return 1;
4356}
6d8fd7bb
RH
4357
4358/* Returns a mask so that zap(x, value) == x & mask. */
4359
4360rtx
a5c24926 4361alpha_expand_zap_mask (HOST_WIDE_INT value)
6d8fd7bb
RH
4362{
4363 rtx result;
4364 int i;
4365
4366 if (HOST_BITS_PER_WIDE_INT >= 64)
4367 {
4368 HOST_WIDE_INT mask = 0;
4369
4370 for (i = 7; i >= 0; --i)
4371 {
4372 mask <<= 8;
4373 if (!((value >> i) & 1))
4374 mask |= 0xff;
4375 }
4376
4377 result = gen_int_mode (mask, DImode);
4378 }
56daab84 4379 else
6d8fd7bb
RH
4380 {
4381 HOST_WIDE_INT mask_lo = 0, mask_hi = 0;
4382
56daab84
NS
4383 gcc_assert (HOST_BITS_PER_WIDE_INT == 32);
4384
6d8fd7bb
RH
4385 for (i = 7; i >= 4; --i)
4386 {
4387 mask_hi <<= 8;
4388 if (!((value >> i) & 1))
4389 mask_hi |= 0xff;
4390 }
4391
4392 for (i = 3; i >= 0; --i)
4393 {
4394 mask_lo <<= 8;
4395 if (!((value >> i) & 1))
4396 mask_lo |= 0xff;
4397 }
4398
4399 result = immed_double_const (mask_lo, mask_hi, DImode);
4400 }
6d8fd7bb
RH
4401
4402 return result;
4403}
4404
4405void
a5c24926
RH
4406alpha_expand_builtin_vector_binop (rtx (*gen) (rtx, rtx, rtx),
4407 enum machine_mode mode,
4408 rtx op0, rtx op1, rtx op2)
6d8fd7bb
RH
4409{
4410 op0 = gen_lowpart (mode, op0);
4411
4412 if (op1 == const0_rtx)
4413 op1 = CONST0_RTX (mode);
4414 else
4415 op1 = gen_lowpart (mode, op1);
c4b50f1a
RH
4416
4417 if (op2 == const0_rtx)
6d8fd7bb
RH
4418 op2 = CONST0_RTX (mode);
4419 else
4420 op2 = gen_lowpart (mode, op2);
4421
4422 emit_insn ((*gen) (op0, op1, op2));
4423}
0b196b18 4424
b686c48c
RH
4425/* A subroutine of the atomic operation splitters. Jump to LABEL if
4426 COND is true. Mark the jump as unlikely to be taken. */
4427
4428static void
4429emit_unlikely_jump (rtx cond, rtx label)
4430{
4431 rtx very_unlikely = GEN_INT (REG_BR_PROB_BASE / 100 - 1);
4432 rtx x;
4433
4434 x = gen_rtx_IF_THEN_ELSE (VOIDmode, cond, label, pc_rtx);
4435 x = emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, x));
bf758008 4436 add_reg_note (x, REG_BR_PROB, very_unlikely);
b686c48c
RH
4437}
4438
4439/* A subroutine of the atomic operation splitters. Emit a load-locked
4440 instruction in MODE. */
4441
4442static void
4443emit_load_locked (enum machine_mode mode, rtx reg, rtx mem)
4444{
4445 rtx (*fn) (rtx, rtx) = NULL;
4446 if (mode == SImode)
4447 fn = gen_load_locked_si;
4448 else if (mode == DImode)
4449 fn = gen_load_locked_di;
4450 emit_insn (fn (reg, mem));
4451}
4452
4453/* A subroutine of the atomic operation splitters. Emit a store-conditional
4454 instruction in MODE. */
4455
4456static void
4457emit_store_conditional (enum machine_mode mode, rtx res, rtx mem, rtx val)
4458{
4459 rtx (*fn) (rtx, rtx, rtx) = NULL;
4460 if (mode == SImode)
4461 fn = gen_store_conditional_si;
4462 else if (mode == DImode)
4463 fn = gen_store_conditional_di;
4464 emit_insn (fn (res, mem, val));
4465}
4466
38f31687
RH
4467/* A subroutine of the atomic operation splitters. Emit an insxl
4468 instruction in MODE. */
4469
4470static rtx
4471emit_insxl (enum machine_mode mode, rtx op1, rtx op2)
4472{
4473 rtx ret = gen_reg_rtx (DImode);
4474 rtx (*fn) (rtx, rtx, rtx);
4475
4476 if (WORDS_BIG_ENDIAN)
4477 {
4478 if (mode == QImode)
4479 fn = gen_insbl_be;
4480 else
4481 fn = gen_inswl_be;
4482 }
4483 else
4484 {
4485 if (mode == QImode)
4486 fn = gen_insbl_le;
4487 else
4488 fn = gen_inswl_le;
4489 }
f2477b06
RS
4490 /* The insbl and inswl patterns require a register operand. */
4491 op1 = force_reg (mode, op1);
38f31687
RH
4492 emit_insn (fn (ret, op1, op2));
4493
4494 return ret;
4495}
4496
ea2c620c 4497/* Expand an atomic fetch-and-operate pattern. CODE is the binary operation
0b196b18
RH
4498 to perform. MEM is the memory on which to operate. VAL is the second
4499 operand of the binary operator. BEFORE and AFTER are optional locations to
4500 return the value of MEM either before of after the operation. SCRATCH is
4501 a scratch register. */
4502
4503void
4504alpha_split_atomic_op (enum rtx_code code, rtx mem, rtx val,
4505 rtx before, rtx after, rtx scratch)
4506{
4507 enum machine_mode mode = GET_MODE (mem);
b686c48c 4508 rtx label, x, cond = gen_rtx_REG (DImode, REGNO (scratch));
0b196b18
RH
4509
4510 emit_insn (gen_memory_barrier ());
4511
4512 label = gen_label_rtx ();
4513 emit_label (label);
4514 label = gen_rtx_LABEL_REF (DImode, label);
4515
4516 if (before == NULL)
4517 before = scratch;
b686c48c 4518 emit_load_locked (mode, before, mem);
0b196b18
RH
4519
4520 if (code == NOT)
d04dceb5
UB
4521 {
4522 x = gen_rtx_AND (mode, before, val);
4523 emit_insn (gen_rtx_SET (VOIDmode, val, x));
4524
4525 x = gen_rtx_NOT (mode, val);
4526 }
0b196b18
RH
4527 else
4528 x = gen_rtx_fmt_ee (code, mode, before, val);
0b196b18
RH
4529 if (after)
4530 emit_insn (gen_rtx_SET (VOIDmode, after, copy_rtx (x)));
f12b785d 4531 emit_insn (gen_rtx_SET (VOIDmode, scratch, x));
0b196b18 4532
b686c48c
RH
4533 emit_store_conditional (mode, cond, mem, scratch);
4534
4535 x = gen_rtx_EQ (DImode, cond, const0_rtx);
4536 emit_unlikely_jump (x, label);
4537
4538 emit_insn (gen_memory_barrier ());
4539}
4540
4541/* Expand a compare and swap operation. */
4542
4543void
4544alpha_split_compare_and_swap (rtx retval, rtx mem, rtx oldval, rtx newval,
4545 rtx scratch)
4546{
4547 enum machine_mode mode = GET_MODE (mem);
4548 rtx label1, label2, x, cond = gen_lowpart (DImode, scratch);
4549
4550 emit_insn (gen_memory_barrier ());
4551
4552 label1 = gen_rtx_LABEL_REF (DImode, gen_label_rtx ());
4553 label2 = gen_rtx_LABEL_REF (DImode, gen_label_rtx ());
4554 emit_label (XEXP (label1, 0));
4555
4556 emit_load_locked (mode, retval, mem);
4557
4558 x = gen_lowpart (DImode, retval);
4559 if (oldval == const0_rtx)
4560 x = gen_rtx_NE (DImode, x, const0_rtx);
0b196b18 4561 else
b686c48c
RH
4562 {
4563 x = gen_rtx_EQ (DImode, x, oldval);
4564 emit_insn (gen_rtx_SET (VOIDmode, cond, x));
4565 x = gen_rtx_EQ (DImode, cond, const0_rtx);
4566 }
4567 emit_unlikely_jump (x, label2);
4568
4569 emit_move_insn (scratch, newval);
4570 emit_store_conditional (mode, cond, mem, scratch);
0b196b18
RH
4571
4572 x = gen_rtx_EQ (DImode, cond, const0_rtx);
b686c48c
RH
4573 emit_unlikely_jump (x, label1);
4574
4575 emit_insn (gen_memory_barrier ());
4576 emit_label (XEXP (label2, 0));
4577}
4578
38f31687
RH
4579void
4580alpha_expand_compare_and_swap_12 (rtx dst, rtx mem, rtx oldval, rtx newval)
4581{
4582 enum machine_mode mode = GET_MODE (mem);
4583 rtx addr, align, wdst;
4584 rtx (*fn5) (rtx, rtx, rtx, rtx, rtx);
4585
4586 addr = force_reg (DImode, XEXP (mem, 0));
4587 align = expand_simple_binop (Pmode, AND, addr, GEN_INT (-8),
4588 NULL_RTX, 1, OPTAB_DIRECT);
4589
4590 oldval = convert_modes (DImode, mode, oldval, 1);
4591 newval = emit_insxl (mode, newval, addr);
4592
4593 wdst = gen_reg_rtx (DImode);
4594 if (mode == QImode)
4595 fn5 = gen_sync_compare_and_swapqi_1;
4596 else
4597 fn5 = gen_sync_compare_and_swaphi_1;
4598 emit_insn (fn5 (wdst, addr, oldval, newval, align));
4599
4600 emit_move_insn (dst, gen_lowpart (mode, wdst));
4601}
4602
4603void
4604alpha_split_compare_and_swap_12 (enum machine_mode mode, rtx dest, rtx addr,
4605 rtx oldval, rtx newval, rtx align,
4606 rtx scratch, rtx cond)
4607{
4608 rtx label1, label2, mem, width, mask, x;
4609
4610 mem = gen_rtx_MEM (DImode, align);
4611 MEM_VOLATILE_P (mem) = 1;
4612
4613 emit_insn (gen_memory_barrier ());
4614 label1 = gen_rtx_LABEL_REF (DImode, gen_label_rtx ());
4615 label2 = gen_rtx_LABEL_REF (DImode, gen_label_rtx ());
4616 emit_label (XEXP (label1, 0));
4617
4618 emit_load_locked (DImode, scratch, mem);
4619
4620 width = GEN_INT (GET_MODE_BITSIZE (mode));
4621 mask = GEN_INT (mode == QImode ? 0xff : 0xffff);
4622 if (WORDS_BIG_ENDIAN)
4623 emit_insn (gen_extxl_be (dest, scratch, width, addr));
4624 else
4625 emit_insn (gen_extxl_le (dest, scratch, width, addr));
4626
4627 if (oldval == const0_rtx)
4628 x = gen_rtx_NE (DImode, dest, const0_rtx);
4629 else
4630 {
4631 x = gen_rtx_EQ (DImode, dest, oldval);
4632 emit_insn (gen_rtx_SET (VOIDmode, cond, x));
4633 x = gen_rtx_EQ (DImode, cond, const0_rtx);
4634 }
4635 emit_unlikely_jump (x, label2);
4636
4637 if (WORDS_BIG_ENDIAN)
4638 emit_insn (gen_mskxl_be (scratch, scratch, mask, addr));
4639 else
4640 emit_insn (gen_mskxl_le (scratch, scratch, mask, addr));
4641 emit_insn (gen_iordi3 (scratch, scratch, newval));
4642
4643 emit_store_conditional (DImode, scratch, mem, scratch);
4644
4645 x = gen_rtx_EQ (DImode, scratch, const0_rtx);
4646 emit_unlikely_jump (x, label1);
4647
4648 emit_insn (gen_memory_barrier ());
4649 emit_label (XEXP (label2, 0));
4650}
4651
b686c48c
RH
4652/* Expand an atomic exchange operation. */
4653
4654void
4655alpha_split_lock_test_and_set (rtx retval, rtx mem, rtx val, rtx scratch)
4656{
4657 enum machine_mode mode = GET_MODE (mem);
4658 rtx label, x, cond = gen_lowpart (DImode, scratch);
0b196b18 4659
b686c48c
RH
4660 label = gen_rtx_LABEL_REF (DImode, gen_label_rtx ());
4661 emit_label (XEXP (label, 0));
4662
4663 emit_load_locked (mode, retval, mem);
4664 emit_move_insn (scratch, val);
4665 emit_store_conditional (mode, cond, mem, scratch);
4666
4667 x = gen_rtx_EQ (DImode, cond, const0_rtx);
4668 emit_unlikely_jump (x, label);
27738602
RH
4669
4670 emit_insn (gen_memory_barrier ());
0b196b18 4671}
38f31687
RH
4672
4673void
4674alpha_expand_lock_test_and_set_12 (rtx dst, rtx mem, rtx val)
4675{
4676 enum machine_mode mode = GET_MODE (mem);
4677 rtx addr, align, wdst;
4678 rtx (*fn4) (rtx, rtx, rtx, rtx);
4679
4680 /* Force the address into a register. */
4681 addr = force_reg (DImode, XEXP (mem, 0));
4682
4683 /* Align it to a multiple of 8. */
4684 align = expand_simple_binop (Pmode, AND, addr, GEN_INT (-8),
4685 NULL_RTX, 1, OPTAB_DIRECT);
4686
4687 /* Insert val into the correct byte location within the word. */
4688 val = emit_insxl (mode, val, addr);
4689
4690 wdst = gen_reg_rtx (DImode);
4691 if (mode == QImode)
4692 fn4 = gen_sync_lock_test_and_setqi_1;
4693 else
4694 fn4 = gen_sync_lock_test_and_sethi_1;
4695 emit_insn (fn4 (wdst, addr, val, align));
4696
4697 emit_move_insn (dst, gen_lowpart (mode, wdst));
4698}
4699
4700void
4701alpha_split_lock_test_and_set_12 (enum machine_mode mode, rtx dest, rtx addr,
4702 rtx val, rtx align, rtx scratch)
4703{
4704 rtx label, mem, width, mask, x;
4705
4706 mem = gen_rtx_MEM (DImode, align);
4707 MEM_VOLATILE_P (mem) = 1;
4708
38f31687
RH
4709 label = gen_rtx_LABEL_REF (DImode, gen_label_rtx ());
4710 emit_label (XEXP (label, 0));
4711
4712 emit_load_locked (DImode, scratch, mem);
4713
4714 width = GEN_INT (GET_MODE_BITSIZE (mode));
4715 mask = GEN_INT (mode == QImode ? 0xff : 0xffff);
4716 if (WORDS_BIG_ENDIAN)
4717 {
4718 emit_insn (gen_extxl_be (dest, scratch, width, addr));
4719 emit_insn (gen_mskxl_be (scratch, scratch, mask, addr));
4720 }
4721 else
4722 {
4723 emit_insn (gen_extxl_le (dest, scratch, width, addr));
4724 emit_insn (gen_mskxl_le (scratch, scratch, mask, addr));
4725 }
4726 emit_insn (gen_iordi3 (scratch, scratch, val));
4727
4728 emit_store_conditional (DImode, scratch, mem, scratch);
4729
4730 x = gen_rtx_EQ (DImode, scratch, const0_rtx);
4731 emit_unlikely_jump (x, label);
27738602
RH
4732
4733 emit_insn (gen_memory_barrier ());
38f31687 4734}
a6f12d7c
RK
4735\f
4736/* Adjust the cost of a scheduling dependency. Return the new cost of
4737 a dependency LINK or INSN on DEP_INSN. COST is the current cost. */
4738
c237e94a 4739static int
a5c24926 4740alpha_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost)
a6f12d7c 4741{
d58770e7 4742 enum attr_type dep_insn_type;
a6f12d7c
RK
4743
4744 /* If the dependence is an anti-dependence, there is no cost. For an
4745 output dependence, there is sometimes a cost, but it doesn't seem
4746 worth handling those few cases. */
a6f12d7c 4747 if (REG_NOTE_KIND (link) != 0)
98791e3a 4748 return cost;
a6f12d7c 4749
26250081
RH
4750 /* If we can't recognize the insns, we can't really do anything. */
4751 if (recog_memoized (insn) < 0 || recog_memoized (dep_insn) < 0)
4752 return cost;
4753
26250081
RH
4754 dep_insn_type = get_attr_type (dep_insn);
4755
bcbbac26 4756 /* Bring in the user-defined memory latency. */
71d9b493
RH
4757 if (dep_insn_type == TYPE_ILD
4758 || dep_insn_type == TYPE_FLD
4759 || dep_insn_type == TYPE_LDSYM)
bcbbac26
RH
4760 cost += alpha_memory_latency-1;
4761
98791e3a 4762 /* Everything else handled in DFA bypasses now. */
74835ed8 4763
a6f12d7c
RK
4764 return cost;
4765}
c237e94a 4766
98791e3a
RH
4767/* The number of instructions that can be issued per cycle. */
4768
c237e94a 4769static int
a5c24926 4770alpha_issue_rate (void)
c237e94a 4771{
8bea7f7c 4772 return (alpha_tune == PROCESSOR_EV4 ? 2 : 4);
c237e94a
ZW
4773}
4774
98791e3a
RH
4775/* How many alternative schedules to try. This should be as wide as the
4776 scheduling freedom in the DFA, but no wider. Making this value too
4777 large results extra work for the scheduler.
4778
4779 For EV4, loads can be issued to either IB0 or IB1, thus we have 2
4780 alternative schedules. For EV5, we can choose between E0/E1 and
9a9f7594 4781 FA/FM. For EV6, an arithmetic insn can be issued to U0/U1/L0/L1. */
98791e3a
RH
4782
4783static int
a5c24926 4784alpha_multipass_dfa_lookahead (void)
98791e3a 4785{
8bea7f7c 4786 return (alpha_tune == PROCESSOR_EV6 ? 4 : 2);
98791e3a 4787}
9ecc37f0 4788\f
6f9b006d
RH
4789/* Machine-specific function data. */
4790
d1b38208 4791struct GTY(()) machine_function
6f9b006d 4792{
d6b4baa4 4793 /* For unicosmk. */
6f9b006d
RH
4794 /* List of call information words for calls from this function. */
4795 struct rtx_def *first_ciw;
4796 struct rtx_def *last_ciw;
4797 int ciw_count;
4798
4799 /* List of deferred case vectors. */
4800 struct rtx_def *addr_list;
e2500fed 4801
d6b4baa4 4802 /* For OSF. */
6f9b006d 4803 const char *some_ld_name;
229aa352
RH
4804
4805 /* For TARGET_LD_BUGGY_LDGP. */
4806 struct rtx_def *gp_save_rtx;
221cf9ab
OH
4807
4808 /* For VMS condition handlers. */
4809 bool uses_condition_handler;
6f9b006d
RH
4810};
4811
e2500fed 4812/* How to allocate a 'struct machine_function'. */
30102605 4813
e2500fed 4814static struct machine_function *
a5c24926 4815alpha_init_machine_status (void)
30102605 4816{
a9429e29 4817 return ggc_alloc_cleared_machine_function ();
30102605 4818}
30102605 4819
221cf9ab
OH
4820/* Support for frame based VMS condition handlers. */
4821
4822/* A VMS condition handler may be established for a function with a call to
4823 __builtin_establish_vms_condition_handler, and cancelled with a call to
4824 __builtin_revert_vms_condition_handler.
4825
4826 The VMS Condition Handling Facility knows about the existence of a handler
4827 from the procedure descriptor .handler field. As the VMS native compilers,
4828 we store the user specified handler's address at a fixed location in the
4829 stack frame and point the procedure descriptor at a common wrapper which
4830 fetches the real handler's address and issues an indirect call.
4831
4832 The indirection wrapper is "__gcc_shell_handler", provided by libgcc.
4833
4834 We force the procedure kind to PT_STACK, and the fixed frame location is
4835 fp+8, just before the register save area. We use the handler_data field in
4836 the procedure descriptor to state the fp offset at which the installed
4837 handler address can be found. */
4838
4839#define VMS_COND_HANDLER_FP_OFFSET 8
4840
4841/* Expand code to store the currently installed user VMS condition handler
4842 into TARGET and install HANDLER as the new condition handler. */
4843
4844void
4845alpha_expand_builtin_establish_vms_condition_handler (rtx target, rtx handler)
4846{
4847 rtx handler_slot_address
4848 = plus_constant (hard_frame_pointer_rtx, VMS_COND_HANDLER_FP_OFFSET);
4849
4850 rtx handler_slot
4851 = gen_rtx_MEM (DImode, handler_slot_address);
4852
4853 emit_move_insn (target, handler_slot);
4854 emit_move_insn (handler_slot, handler);
4855
4856 /* Notify the start/prologue/epilogue emitters that the condition handler
4857 slot is needed. In addition to reserving the slot space, this will force
4858 the procedure kind to PT_STACK so ensure that the hard_frame_pointer_rtx
4859 use above is correct. */
4860 cfun->machine->uses_condition_handler = true;
4861}
4862
4863/* Expand code to store the current VMS condition handler into TARGET and
4864 nullify it. */
4865
4866void
4867alpha_expand_builtin_revert_vms_condition_handler (rtx target)
4868{
4869 /* We implement this by establishing a null condition handler, with the tiny
4870 side effect of setting uses_condition_handler. This is a little bit
4871 pessimistic if no actual builtin_establish call is ever issued, which is
4872 not a real problem and expected never to happen anyway. */
4873
4874 alpha_expand_builtin_establish_vms_condition_handler (target, const0_rtx);
4875}
4876
9ecc37f0
RH
4877/* Functions to save and restore alpha_return_addr_rtx. */
4878
9ecc37f0
RH
4879/* Start the ball rolling with RETURN_ADDR_RTX. */
4880
4881rtx
a5c24926 4882alpha_return_addr (int count, rtx frame ATTRIBUTE_UNUSED)
9ecc37f0 4883{
9ecc37f0
RH
4884 if (count != 0)
4885 return const0_rtx;
4886
b91055dd 4887 return get_hard_reg_initial_val (Pmode, REG_RA);
9ecc37f0
RH
4888}
4889
229aa352 4890/* Return or create a memory slot containing the gp value for the current
ccb83cbc
RH
4891 function. Needed only if TARGET_LD_BUGGY_LDGP. */
4892
4893rtx
a5c24926 4894alpha_gp_save_rtx (void)
ccb83cbc 4895{
229aa352
RH
4896 rtx seq, m = cfun->machine->gp_save_rtx;
4897
4898 if (m == NULL)
4899 {
4900 start_sequence ();
4901
4902 m = assign_stack_local (DImode, UNITS_PER_WORD, BITS_PER_WORD);
4903 m = validize_mem (m);
4904 emit_move_insn (m, pic_offset_table_rtx);
4905
4906 seq = get_insns ();
4907 end_sequence ();
8deb1d31
EB
4908
4909 /* We used to simply emit the sequence after entry_of_function.
4910 However this breaks the CFG if the first instruction in the
4911 first block is not the NOTE_INSN_BASIC_BLOCK, for example a
4912 label. Emit the sequence properly on the edge. We are only
4913 invoked from dw2_build_landing_pads and finish_eh_generation
4914 will call commit_edge_insertions thanks to a kludge. */
4915 insert_insn_on_edge (seq, single_succ_edge (ENTRY_BLOCK_PTR));
229aa352
RH
4916
4917 cfun->machine->gp_save_rtx = m;
4918 }
4919
4920 return m;
ccb83cbc
RH
4921}
4922
9ecc37f0 4923static int
a5c24926 4924alpha_ra_ever_killed (void)
9ecc37f0 4925{
6abc6f40
RH
4926 rtx top;
4927
b91055dd 4928 if (!has_hard_reg_initial_val (Pmode, REG_RA))
6fb5fa3c 4929 return (int)df_regs_ever_live_p (REG_RA);
9ecc37f0 4930
6abc6f40
RH
4931 push_topmost_sequence ();
4932 top = get_insns ();
4933 pop_topmost_sequence ();
4934
4935 return reg_set_between_p (gen_rtx_REG (Pmode, REG_RA), top, NULL_RTX);
9ecc37f0
RH
4936}
4937
a6f12d7c 4938\f
be7560ea 4939/* Return the trap mode suffix applicable to the current
285a5742 4940 instruction, or NULL. */
a6f12d7c 4941
be7560ea 4942static const char *
a5c24926 4943get_trap_mode_suffix (void)
a6f12d7c 4944{
be7560ea 4945 enum attr_trap_suffix s = get_attr_trap_suffix (current_output_insn);
a6f12d7c 4946
be7560ea 4947 switch (s)
a6f12d7c 4948 {
be7560ea
RH
4949 case TRAP_SUFFIX_NONE:
4950 return NULL;
6245e3df 4951
be7560ea 4952 case TRAP_SUFFIX_SU:
981a828e 4953 if (alpha_fptm >= ALPHA_FPTM_SU)
be7560ea
RH
4954 return "su";
4955 return NULL;
6245e3df 4956
be7560ea
RH
4957 case TRAP_SUFFIX_SUI:
4958 if (alpha_fptm >= ALPHA_FPTM_SUI)
4959 return "sui";
4960 return NULL;
4961
4962 case TRAP_SUFFIX_V_SV:
e83015a9
RH
4963 switch (alpha_fptm)
4964 {
4965 case ALPHA_FPTM_N:
be7560ea 4966 return NULL;
e83015a9 4967 case ALPHA_FPTM_U:
be7560ea 4968 return "v";
e83015a9
RH
4969 case ALPHA_FPTM_SU:
4970 case ALPHA_FPTM_SUI:
be7560ea 4971 return "sv";
56daab84
NS
4972 default:
4973 gcc_unreachable ();
e83015a9 4974 }
e83015a9 4975
be7560ea 4976 case TRAP_SUFFIX_V_SV_SVI:
0022a940
DMT
4977 switch (alpha_fptm)
4978 {
4979 case ALPHA_FPTM_N:
be7560ea 4980 return NULL;
0022a940 4981 case ALPHA_FPTM_U:
be7560ea 4982 return "v";
0022a940 4983 case ALPHA_FPTM_SU:
be7560ea 4984 return "sv";
0022a940 4985 case ALPHA_FPTM_SUI:
be7560ea 4986 return "svi";
56daab84
NS
4987 default:
4988 gcc_unreachable ();
0022a940
DMT
4989 }
4990 break;
4991
be7560ea 4992 case TRAP_SUFFIX_U_SU_SUI:
6245e3df
RK
4993 switch (alpha_fptm)
4994 {
4995 case ALPHA_FPTM_N:
be7560ea 4996 return NULL;
6245e3df 4997 case ALPHA_FPTM_U:
be7560ea 4998 return "u";
6245e3df 4999 case ALPHA_FPTM_SU:
be7560ea 5000 return "su";
6245e3df 5001 case ALPHA_FPTM_SUI:
be7560ea 5002 return "sui";
56daab84
NS
5003 default:
5004 gcc_unreachable ();
6245e3df
RK
5005 }
5006 break;
56daab84
NS
5007
5008 default:
5009 gcc_unreachable ();
be7560ea 5010 }
56daab84 5011 gcc_unreachable ();
be7560ea 5012}
6245e3df 5013
be7560ea 5014/* Return the rounding mode suffix applicable to the current
285a5742 5015 instruction, or NULL. */
be7560ea
RH
5016
5017static const char *
a5c24926 5018get_round_mode_suffix (void)
be7560ea
RH
5019{
5020 enum attr_round_suffix s = get_attr_round_suffix (current_output_insn);
5021
5022 switch (s)
5023 {
5024 case ROUND_SUFFIX_NONE:
5025 return NULL;
5026 case ROUND_SUFFIX_NORMAL:
5027 switch (alpha_fprm)
6245e3df 5028 {
be7560ea
RH
5029 case ALPHA_FPRM_NORM:
5030 return NULL;
f676971a 5031 case ALPHA_FPRM_MINF:
be7560ea
RH
5032 return "m";
5033 case ALPHA_FPRM_CHOP:
5034 return "c";
5035 case ALPHA_FPRM_DYN:
5036 return "d";
56daab84
NS
5037 default:
5038 gcc_unreachable ();
6245e3df
RK
5039 }
5040 break;
5041
be7560ea
RH
5042 case ROUND_SUFFIX_C:
5043 return "c";
56daab84
NS
5044
5045 default:
5046 gcc_unreachable ();
be7560ea 5047 }
56daab84 5048 gcc_unreachable ();
be7560ea
RH
5049}
5050
6f9b006d
RH
5051/* Locate some local-dynamic symbol still in use by this function
5052 so that we can print its name in some movdi_er_tlsldm pattern. */
5053
a5c24926
RH
5054static int
5055get_some_local_dynamic_name_1 (rtx *px, void *data ATTRIBUTE_UNUSED)
5056{
5057 rtx x = *px;
5058
5059 if (GET_CODE (x) == SYMBOL_REF
5060 && SYMBOL_REF_TLS_MODEL (x) == TLS_MODEL_LOCAL_DYNAMIC)
5061 {
5062 cfun->machine->some_ld_name = XSTR (x, 0);
5063 return 1;
5064 }
5065
5066 return 0;
5067}
5068
6f9b006d 5069static const char *
a5c24926 5070get_some_local_dynamic_name (void)
6f9b006d
RH
5071{
5072 rtx insn;
5073
5074 if (cfun->machine->some_ld_name)
5075 return cfun->machine->some_ld_name;
5076
5077 for (insn = get_insns (); insn ; insn = NEXT_INSN (insn))
5078 if (INSN_P (insn)
5079 && for_each_rtx (&PATTERN (insn), get_some_local_dynamic_name_1, 0))
5080 return cfun->machine->some_ld_name;
5081
56daab84 5082 gcc_unreachable ();
6f9b006d
RH
5083}
5084
be7560ea
RH
5085/* Print an operand. Recognize special options, documented below. */
5086
5087void
a5c24926 5088print_operand (FILE *file, rtx x, int code)
be7560ea
RH
5089{
5090 int i;
5091
5092 switch (code)
5093 {
5094 case '~':
5095 /* Print the assembler name of the current function. */
5096 assemble_name (file, alpha_fnname);
5097 break;
5098
6f9b006d
RH
5099 case '&':
5100 assemble_name (file, get_some_local_dynamic_name ());
5101 break;
5102
be7560ea
RH
5103 case '/':
5104 {
5105 const char *trap = get_trap_mode_suffix ();
5106 const char *round = get_round_mode_suffix ();
5107
5108 if (trap || round)
30102605
RH
5109 fprintf (file, (TARGET_AS_SLASH_BEFORE_SUFFIX ? "/%s%s" : "%s%s"),
5110 (trap ? trap : ""), (round ? round : ""));
be7560ea
RH
5111 break;
5112 }
5113
89cfc2c6
RK
5114 case ',':
5115 /* Generates single precision instruction suffix. */
be7560ea 5116 fputc ((TARGET_FLOAT_VAX ? 'f' : 's'), file);
89cfc2c6
RK
5117 break;
5118
5119 case '-':
5120 /* Generates double precision instruction suffix. */
be7560ea 5121 fputc ((TARGET_FLOAT_VAX ? 'g' : 't'), file);
89cfc2c6
RK
5122 break;
5123
1eb356b9
RH
5124 case '#':
5125 if (alpha_this_literal_sequence_number == 0)
5126 alpha_this_literal_sequence_number = alpha_next_sequence_number++;
5127 fprintf (file, "%d", alpha_this_literal_sequence_number);
5128 break;
5129
5130 case '*':
5131 if (alpha_this_gpdisp_sequence_number == 0)
5132 alpha_this_gpdisp_sequence_number = alpha_next_sequence_number++;
5133 fprintf (file, "%d", alpha_this_gpdisp_sequence_number);
5134 break;
5135
5136 case 'H':
5137 if (GET_CODE (x) == HIGH)
133d3133 5138 output_addr_const (file, XEXP (x, 0));
1eb356b9
RH
5139 else
5140 output_operand_lossage ("invalid %%H value");
5141 break;
5142
40571d67 5143 case 'J':
6f9b006d
RH
5144 {
5145 const char *lituse;
5146
5147 if (GET_CODE (x) == UNSPEC && XINT (x, 1) == UNSPEC_TLSGD_CALL)
5148 {
5149 x = XVECEXP (x, 0, 0);
5150 lituse = "lituse_tlsgd";
5151 }
5152 else if (GET_CODE (x) == UNSPEC && XINT (x, 1) == UNSPEC_TLSLDM_CALL)
5153 {
5154 x = XVECEXP (x, 0, 0);
5155 lituse = "lituse_tlsldm";
5156 }
7d83f4f5 5157 else if (CONST_INT_P (x))
6f9b006d
RH
5158 lituse = "lituse_jsr";
5159 else
5160 {
5161 output_operand_lossage ("invalid %%J value");
5162 break;
5163 }
5164
5165 if (x != const0_rtx)
5166 fprintf (file, "\t\t!%s!%d", lituse, (int) INTVAL (x));
5167 }
40571d67
RH
5168 break;
5169
d006f5eb
RH
5170 case 'j':
5171 {
5172 const char *lituse;
5173
5174#ifdef HAVE_AS_JSRDIRECT_RELOCS
5175 lituse = "lituse_jsrdirect";
5176#else
5177 lituse = "lituse_jsr";
5178#endif
5179
5180 gcc_assert (INTVAL (x) != 0);
5181 fprintf (file, "\t\t!%s!%d", lituse, (int) INTVAL (x));
5182 }
5183 break;
a6f12d7c
RK
5184 case 'r':
5185 /* If this operand is the constant zero, write it as "$31". */
7d83f4f5 5186 if (REG_P (x))
a6f12d7c
RK
5187 fprintf (file, "%s", reg_names[REGNO (x)]);
5188 else if (x == CONST0_RTX (GET_MODE (x)))
5189 fprintf (file, "$31");
5190 else
5191 output_operand_lossage ("invalid %%r value");
a6f12d7c
RK
5192 break;
5193
5194 case 'R':
5195 /* Similar, but for floating-point. */
7d83f4f5 5196 if (REG_P (x))
a6f12d7c
RK
5197 fprintf (file, "%s", reg_names[REGNO (x)]);
5198 else if (x == CONST0_RTX (GET_MODE (x)))
5199 fprintf (file, "$f31");
5200 else
5201 output_operand_lossage ("invalid %%R value");
a6f12d7c
RK
5202 break;
5203
5204 case 'N':
5205 /* Write the 1's complement of a constant. */
7d83f4f5 5206 if (!CONST_INT_P (x))
a6f12d7c
RK
5207 output_operand_lossage ("invalid %%N value");
5208
0bc8ae6e 5209 fprintf (file, HOST_WIDE_INT_PRINT_DEC, ~ INTVAL (x));
a6f12d7c
RK
5210 break;
5211
5212 case 'P':
5213 /* Write 1 << C, for a constant C. */
7d83f4f5 5214 if (!CONST_INT_P (x))
a6f12d7c
RK
5215 output_operand_lossage ("invalid %%P value");
5216
0bc8ae6e 5217 fprintf (file, HOST_WIDE_INT_PRINT_DEC, (HOST_WIDE_INT) 1 << INTVAL (x));
a6f12d7c
RK
5218 break;
5219
5220 case 'h':
5221 /* Write the high-order 16 bits of a constant, sign-extended. */
7d83f4f5 5222 if (!CONST_INT_P (x))
a6f12d7c
RK
5223 output_operand_lossage ("invalid %%h value");
5224
0bc8ae6e 5225 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x) >> 16);
a6f12d7c
RK
5226 break;
5227
5228 case 'L':
5229 /* Write the low-order 16 bits of a constant, sign-extended. */
7d83f4f5 5230 if (!CONST_INT_P (x))
a6f12d7c
RK
5231 output_operand_lossage ("invalid %%L value");
5232
0bc8ae6e
RK
5233 fprintf (file, HOST_WIDE_INT_PRINT_DEC,
5234 (INTVAL (x) & 0xffff) - 2 * (INTVAL (x) & 0x8000));
a6f12d7c
RK
5235 break;
5236
5237 case 'm':
5238 /* Write mask for ZAP insn. */
5239 if (GET_CODE (x) == CONST_DOUBLE)
5240 {
5241 HOST_WIDE_INT mask = 0;
5242 HOST_WIDE_INT value;
5243
5244 value = CONST_DOUBLE_LOW (x);
5245 for (i = 0; i < HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR;
5246 i++, value >>= 8)
5247 if (value & 0xff)
5248 mask |= (1 << i);
5249
5250 value = CONST_DOUBLE_HIGH (x);
5251 for (i = 0; i < HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR;
5252 i++, value >>= 8)
5253 if (value & 0xff)
5254 mask |= (1 << (i + sizeof (int)));
5255
0bc8ae6e 5256 fprintf (file, HOST_WIDE_INT_PRINT_DEC, mask & 0xff);
a6f12d7c
RK
5257 }
5258
7d83f4f5 5259 else if (CONST_INT_P (x))
a6f12d7c
RK
5260 {
5261 HOST_WIDE_INT mask = 0, value = INTVAL (x);
5262
5263 for (i = 0; i < 8; i++, value >>= 8)
5264 if (value & 0xff)
5265 mask |= (1 << i);
5266
0bc8ae6e 5267 fprintf (file, HOST_WIDE_INT_PRINT_DEC, mask);
a6f12d7c
RK
5268 }
5269 else
5270 output_operand_lossage ("invalid %%m value");
5271 break;
5272
5273 case 'M':
6c174fc0 5274 /* 'b', 'w', 'l', or 'q' as the value of the constant. */
7d83f4f5 5275 if (!CONST_INT_P (x)
6c174fc0
RH
5276 || (INTVAL (x) != 8 && INTVAL (x) != 16
5277 && INTVAL (x) != 32 && INTVAL (x) != 64))
a6f12d7c
RK
5278 output_operand_lossage ("invalid %%M value");
5279
5280 fprintf (file, "%s",
6c174fc0
RH
5281 (INTVAL (x) == 8 ? "b"
5282 : INTVAL (x) == 16 ? "w"
5283 : INTVAL (x) == 32 ? "l"
5284 : "q"));
a6f12d7c
RK
5285 break;
5286
5287 case 'U':
5288 /* Similar, except do it from the mask. */
7d83f4f5 5289 if (CONST_INT_P (x))
c4b50f1a
RH
5290 {
5291 HOST_WIDE_INT value = INTVAL (x);
5292
5293 if (value == 0xff)
5294 {
5295 fputc ('b', file);
5296 break;
5297 }
5298 if (value == 0xffff)
5299 {
5300 fputc ('w', file);
5301 break;
5302 }
5303 if (value == 0xffffffff)
5304 {
5305 fputc ('l', file);
5306 break;
5307 }
5308 if (value == -1)
5309 {
5310 fputc ('q', file);
5311 break;
5312 }
5313 }
5314 else if (HOST_BITS_PER_WIDE_INT == 32
5315 && GET_CODE (x) == CONST_DOUBLE
5316 && CONST_DOUBLE_LOW (x) == 0xffffffff
5317 && CONST_DOUBLE_HIGH (x) == 0)
5318 {
5319 fputc ('l', file);
5320 break;
5321 }
5322 output_operand_lossage ("invalid %%U value");
a6f12d7c
RK
5323 break;
5324
5325 case 's':
30102605
RH
5326 /* Write the constant value divided by 8 for little-endian mode or
5327 (56 - value) / 8 for big-endian mode. */
5328
7d83f4f5 5329 if (!CONST_INT_P (x)
30102605
RH
5330 || (unsigned HOST_WIDE_INT) INTVAL (x) >= (WORDS_BIG_ENDIAN
5331 ? 56
f676971a 5332 : 64)
30102605 5333 || (INTVAL (x) & 7) != 0)
a6f12d7c
RK
5334 output_operand_lossage ("invalid %%s value");
5335
30102605
RH
5336 fprintf (file, HOST_WIDE_INT_PRINT_DEC,
5337 WORDS_BIG_ENDIAN
5338 ? (56 - INTVAL (x)) / 8
5339 : INTVAL (x) / 8);
a6f12d7c
RK
5340 break;
5341
5342 case 'S':
5343 /* Same, except compute (64 - c) / 8 */
5344
7d83f4f5 5345 if (!CONST_INT_P (x)
a6f12d7c
RK
5346 && (unsigned HOST_WIDE_INT) INTVAL (x) >= 64
5347 && (INTVAL (x) & 7) != 8)
5348 output_operand_lossage ("invalid %%s value");
5349
0bc8ae6e 5350 fprintf (file, HOST_WIDE_INT_PRINT_DEC, (64 - INTVAL (x)) / 8);
a6f12d7c
RK
5351 break;
5352
30102605
RH
5353 case 't':
5354 {
5355 /* On Unicos/Mk systems: use a DEX expression if the symbol
5356 clashes with a register name. */
5357 int dex = unicosmk_need_dex (x);
5358 if (dex)
5359 fprintf (file, "DEX(%d)", dex);
5360 else
5361 output_addr_const (file, x);
5362 }
5363 break;
5364
bdd4c95a 5365 case 'C': case 'D': case 'c': case 'd':
a6f12d7c 5366 /* Write out comparison name. */
bdd4c95a
RK
5367 {
5368 enum rtx_code c = GET_CODE (x);
5369
ec8e098d 5370 if (!COMPARISON_P (x))
bdd4c95a
RK
5371 output_operand_lossage ("invalid %%C value");
5372
948068e2 5373 else if (code == 'D')
bdd4c95a
RK
5374 c = reverse_condition (c);
5375 else if (code == 'c')
5376 c = swap_condition (c);
5377 else if (code == 'd')
5378 c = swap_condition (reverse_condition (c));
5379
5380 if (c == LEU)
5381 fprintf (file, "ule");
5382 else if (c == LTU)
5383 fprintf (file, "ult");
1eb8759b
RH
5384 else if (c == UNORDERED)
5385 fprintf (file, "un");
bdd4c95a
RK
5386 else
5387 fprintf (file, "%s", GET_RTX_NAME (c));
5388 }
ab561e66
RK
5389 break;
5390
a6f12d7c
RK
5391 case 'E':
5392 /* Write the divide or modulus operator. */
5393 switch (GET_CODE (x))
5394 {
5395 case DIV:
5396 fprintf (file, "div%s", GET_MODE (x) == SImode ? "l" : "q");
5397 break;
5398 case UDIV:
5399 fprintf (file, "div%su", GET_MODE (x) == SImode ? "l" : "q");
5400 break;
5401 case MOD:
5402 fprintf (file, "rem%s", GET_MODE (x) == SImode ? "l" : "q");
5403 break;
5404 case UMOD:
5405 fprintf (file, "rem%su", GET_MODE (x) == SImode ? "l" : "q");
5406 break;
5407 default:
5408 output_operand_lossage ("invalid %%E value");
5409 break;
5410 }
5411 break;
5412
a6f12d7c
RK
5413 case 'A':
5414 /* Write "_u" for unaligned access. */
7d83f4f5 5415 if (MEM_P (x) && GET_CODE (XEXP (x, 0)) == AND)
a6f12d7c
RK
5416 fprintf (file, "_u");
5417 break;
5418
5419 case 0:
7d83f4f5 5420 if (REG_P (x))
a6f12d7c 5421 fprintf (file, "%s", reg_names[REGNO (x)]);
7d83f4f5 5422 else if (MEM_P (x))
a6f12d7c 5423 output_address (XEXP (x, 0));
6f9b006d
RH
5424 else if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == UNSPEC)
5425 {
5426 switch (XINT (XEXP (x, 0), 1))
5427 {
5428 case UNSPEC_DTPREL:
5429 case UNSPEC_TPREL:
5430 output_addr_const (file, XVECEXP (XEXP (x, 0), 0, 0));
5431 break;
5432 default:
5433 output_operand_lossage ("unknown relocation unspec");
5434 break;
5435 }
5436 }
a6f12d7c
RK
5437 else
5438 output_addr_const (file, x);
5439 break;
5440
5441 default:
5442 output_operand_lossage ("invalid %%xn code");
5443 }
5444}
714b019c
RH
5445
5446void
a5c24926 5447print_operand_address (FILE *file, rtx addr)
714b019c 5448{
e03ec28f 5449 int basereg = 31;
714b019c
RH
5450 HOST_WIDE_INT offset = 0;
5451
5452 if (GET_CODE (addr) == AND)
5453 addr = XEXP (addr, 0);
714b019c 5454
e03ec28f 5455 if (GET_CODE (addr) == PLUS
7d83f4f5 5456 && CONST_INT_P (XEXP (addr, 1)))
714b019c
RH
5457 {
5458 offset = INTVAL (XEXP (addr, 1));
e03ec28f 5459 addr = XEXP (addr, 0);
714b019c 5460 }
1eb356b9
RH
5461
5462 if (GET_CODE (addr) == LO_SUM)
5463 {
6f9b006d
RH
5464 const char *reloc16, *reloclo;
5465 rtx op1 = XEXP (addr, 1);
5466
5467 if (GET_CODE (op1) == CONST && GET_CODE (XEXP (op1, 0)) == UNSPEC)
5468 {
5469 op1 = XEXP (op1, 0);
5470 switch (XINT (op1, 1))
5471 {
5472 case UNSPEC_DTPREL:
5473 reloc16 = NULL;
5474 reloclo = (alpha_tls_size == 16 ? "dtprel" : "dtprello");
5475 break;
5476 case UNSPEC_TPREL:
5477 reloc16 = NULL;
5478 reloclo = (alpha_tls_size == 16 ? "tprel" : "tprello");
5479 break;
5480 default:
5481 output_operand_lossage ("unknown relocation unspec");
5482 return;
5483 }
5484
5485 output_addr_const (file, XVECEXP (op1, 0, 0));
5486 }
5487 else
5488 {
5489 reloc16 = "gprel";
5490 reloclo = "gprellow";
5491 output_addr_const (file, op1);
5492 }
5493
1eb356b9 5494 if (offset)
4a0a75dd 5495 fprintf (file, "+" HOST_WIDE_INT_PRINT_DEC, offset);
f676971a 5496
1eb356b9 5497 addr = XEXP (addr, 0);
56daab84
NS
5498 switch (GET_CODE (addr))
5499 {
5500 case REG:
5501 basereg = REGNO (addr);
5502 break;
5503
5504 case SUBREG:
5505 basereg = subreg_regno (addr);
5506 break;
5507
5508 default:
5509 gcc_unreachable ();
5510 }
133d3133
RH
5511
5512 fprintf (file, "($%d)\t\t!%s", basereg,
6f9b006d 5513 (basereg == 29 ? reloc16 : reloclo));
1eb356b9
RH
5514 return;
5515 }
5516
56daab84
NS
5517 switch (GET_CODE (addr))
5518 {
5519 case REG:
5520 basereg = REGNO (addr);
5521 break;
5522
5523 case SUBREG:
5524 basereg = subreg_regno (addr);
5525 break;
5526
5527 case CONST_INT:
5528 offset = INTVAL (addr);
5529 break;
1330f7d5
DR
5530
5531#if TARGET_ABI_OPEN_VMS
56daab84 5532 case SYMBOL_REF:
1330f7d5
DR
5533 fprintf (file, "%s", XSTR (addr, 0));
5534 return;
56daab84
NS
5535
5536 case CONST:
5537 gcc_assert (GET_CODE (XEXP (addr, 0)) == PLUS
5538 && GET_CODE (XEXP (XEXP (addr, 0), 0)) == SYMBOL_REF);
74eda121 5539 fprintf (file, "%s+" HOST_WIDE_INT_PRINT_DEC,
1330f7d5
DR
5540 XSTR (XEXP (XEXP (addr, 0), 0), 0),
5541 INTVAL (XEXP (XEXP (addr, 0), 1)));
5542 return;
56daab84 5543
1330f7d5 5544#endif
56daab84
NS
5545 default:
5546 gcc_unreachable ();
5547 }
714b019c 5548
4a0a75dd 5549 fprintf (file, HOST_WIDE_INT_PRINT_DEC "($%d)", offset, basereg);
714b019c 5550}
a6f12d7c 5551\f
9ec36da5 5552/* Emit RTL insns to initialize the variable parts of a trampoline at
2d7b663a
RH
5553 M_TRAMP. FNDECL is target function's decl. CHAIN_VALUE is an rtx
5554 for the static chain value for the function. */
c714f03d 5555
2d7b663a
RH
5556static void
5557alpha_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
9ec36da5 5558{
2d7b663a
RH
5559 rtx fnaddr, mem, word1, word2;
5560
5561 fnaddr = XEXP (DECL_RTL (fndecl), 0);
9ec36da5 5562
d2692ef8 5563#ifdef POINTERS_EXTEND_UNSIGNED
2d7b663a
RH
5564 fnaddr = convert_memory_address (Pmode, fnaddr);
5565 chain_value = convert_memory_address (Pmode, chain_value);
d2692ef8
DT
5566#endif
5567
fe2786f5
DR
5568 if (TARGET_ABI_OPEN_VMS)
5569 {
fe2786f5
DR
5570 const char *fnname;
5571 char *trname;
5572
5573 /* Construct the name of the trampoline entry point. */
5574 fnname = XSTR (fnaddr, 0);
5575 trname = (char *) alloca (strlen (fnname) + 5);
5576 strcpy (trname, fnname);
5577 strcat (trname, "..tr");
2d7b663a
RH
5578 fnname = ggc_alloc_string (trname, strlen (trname) + 1);
5579 word2 = gen_rtx_SYMBOL_REF (Pmode, fnname);
fe2786f5
DR
5580
5581 /* Trampoline (or "bounded") procedure descriptor is constructed from
5582 the function's procedure descriptor with certain fields zeroed IAW
5583 the VMS calling standard. This is stored in the first quadword. */
2d7b663a
RH
5584 word1 = force_reg (DImode, gen_const_mem (DImode, fnaddr));
5585 word1 = expand_and (DImode, word1, GEN_INT (0xffff0fff0000fff0), NULL);
fe2786f5 5586 }
2d7b663a
RH
5587 else
5588 {
5589 /* These 4 instructions are:
5590 ldq $1,24($27)
5591 ldq $27,16($27)
5592 jmp $31,($27),0
5593 nop
5594 We don't bother setting the HINT field of the jump; the nop
5595 is merely there for padding. */
5596 word1 = GEN_INT (0xa77b0010a43b0018);
5597 word2 = GEN_INT (0x47ff041f6bfb0000);
5598 }
5599
5600 /* Store the first two words, as computed above. */
5601 mem = adjust_address (m_tramp, DImode, 0);
5602 emit_move_insn (mem, word1);
5603 mem = adjust_address (m_tramp, DImode, 8);
5604 emit_move_insn (mem, word2);
5605
5606 /* Store function address and static chain value. */
5607 mem = adjust_address (m_tramp, Pmode, 16);
5608 emit_move_insn (mem, fnaddr);
5609 mem = adjust_address (m_tramp, Pmode, 24);
5610 emit_move_insn (mem, chain_value);
fe2786f5 5611
2d7b663a
RH
5612 if (!TARGET_ABI_OPEN_VMS)
5613 {
5614 emit_insn (gen_imb ());
e7a742ec 5615#ifdef ENABLE_EXECUTE_STACK
2d7b663a
RH
5616 emit_library_call (init_one_libfunc ("__enable_execute_stack"),
5617 LCT_NORMAL, VOIDmode, 1, XEXP (m_tramp, 0), Pmode);
9ec36da5 5618#endif
2d7b663a 5619 }
9ec36da5
JL
5620}
5621\f
5495cc55
RH
5622/* Determine where to put an argument to a function.
5623 Value is zero to push the argument on the stack,
5624 or a hard register in which to store the argument.
5625
5626 MODE is the argument's machine mode.
5627 TYPE is the data type of the argument (as a tree).
5628 This is null for libcalls where that information may
5629 not be available.
5630 CUM is a variable of type CUMULATIVE_ARGS which gives info about
5631 the preceding args and about the function being called.
5632 NAMED is nonzero if this argument is a named parameter
5633 (otherwise it is an extra parameter matching an ellipsis).
5634
5635 On Alpha the first 6 words of args are normally in registers
5636 and the rest are pushed. */
5637
5638rtx
a5c24926
RH
5639function_arg (CUMULATIVE_ARGS cum, enum machine_mode mode, tree type,
5640 int named ATTRIBUTE_UNUSED)
5495cc55
RH
5641{
5642 int basereg;
a82c7f05 5643 int num_args;
5495cc55 5644
7e4fb06a
RH
5645 /* Don't get confused and pass small structures in FP registers. */
5646 if (type && AGGREGATE_TYPE_P (type))
30102605 5647 basereg = 16;
7e4fb06a
RH
5648 else
5649 {
5650#ifdef ENABLE_CHECKING
42ba5130 5651 /* With alpha_split_complex_arg, we shouldn't see any raw complex
7e4fb06a 5652 values here. */
56daab84 5653 gcc_assert (!COMPLEX_MODE_P (mode));
7e4fb06a
RH
5654#endif
5655
5656 /* Set up defaults for FP operands passed in FP registers, and
5657 integral operands passed in integer registers. */
5658 if (TARGET_FPREGS && GET_MODE_CLASS (mode) == MODE_FLOAT)
5659 basereg = 32 + 16;
5660 else
5661 basereg = 16;
5662 }
30102605
RH
5663
5664 /* ??? Irritatingly, the definition of CUMULATIVE_ARGS is different for
5665 the three platforms, so we can't avoid conditional compilation. */
be7b80f4 5666#if TARGET_ABI_OPEN_VMS
30102605
RH
5667 {
5668 if (mode == VOIDmode)
5669 return alpha_arg_info_reg_val (cum);
be7b80f4 5670
30102605 5671 num_args = cum.num_args;
fe984136
RH
5672 if (num_args >= 6
5673 || targetm.calls.must_pass_in_stack (mode, type))
30102605
RH
5674 return NULL_RTX;
5675 }
7e4fb06a 5676#elif TARGET_ABI_UNICOSMK
30102605
RH
5677 {
5678 int size;
5495cc55 5679
30102605
RH
5680 /* If this is the last argument, generate the call info word (CIW). */
5681 /* ??? We don't include the caller's line number in the CIW because
5682 I don't know how to determine it if debug infos are turned off. */
5683 if (mode == VOIDmode)
5684 {
5685 int i;
5686 HOST_WIDE_INT lo;
5687 HOST_WIDE_INT hi;
5688 rtx ciw;
5689
5690 lo = 0;
5691
5692 for (i = 0; i < cum.num_reg_words && i < 5; i++)
5693 if (cum.reg_args_type[i])
5694 lo |= (1 << (7 - i));
5695
5696 if (cum.num_reg_words == 6 && cum.reg_args_type[5])
5697 lo |= 7;
5698 else
5699 lo |= cum.num_reg_words;
5700
5701#if HOST_BITS_PER_WIDE_INT == 32
5702 hi = (cum.num_args << 20) | cum.num_arg_words;
5703#else
999c746f
KG
5704 lo = lo | ((HOST_WIDE_INT) cum.num_args << 52)
5705 | ((HOST_WIDE_INT) cum.num_arg_words << 32);
30102605
RH
5706 hi = 0;
5707#endif
5708 ciw = immed_double_const (lo, hi, DImode);
5709
5710 return gen_rtx_UNSPEC (DImode, gen_rtvec (1, ciw),
5711 UNSPEC_UMK_LOAD_CIW);
5712 }
5713
5714 size = ALPHA_ARG_SIZE (mode, type, named);
5715 num_args = cum.num_reg_words;
fe984136
RH
5716 if (cum.force_stack
5717 || cum.num_reg_words + size > 6
5718 || targetm.calls.must_pass_in_stack (mode, type))
30102605
RH
5719 return NULL_RTX;
5720 else if (type && TYPE_MODE (type) == BLKmode)
5721 {
5722 rtx reg1, reg2;
5723
5724 reg1 = gen_rtx_REG (DImode, num_args + 16);
5725 reg1 = gen_rtx_EXPR_LIST (DImode, reg1, const0_rtx);
5726
5727 /* The argument fits in two registers. Note that we still need to
5728 reserve a register for empty structures. */
5729 if (size == 0)
5730 return NULL_RTX;
5731 else if (size == 1)
5732 return gen_rtx_PARALLEL (mode, gen_rtvec (1, reg1));
5733 else
5734 {
5735 reg2 = gen_rtx_REG (DImode, num_args + 17);
5736 reg2 = gen_rtx_EXPR_LIST (DImode, reg2, GEN_INT (8));
5737 return gen_rtx_PARALLEL (mode, gen_rtvec (2, reg1, reg2));
5738 }
5739 }
5740 }
7e4fb06a 5741#elif TARGET_ABI_OSF
30102605
RH
5742 {
5743 if (cum >= 6)
5744 return NULL_RTX;
5745 num_args = cum;
5746
5747 /* VOID is passed as a special flag for "last argument". */
5748 if (type == void_type_node)
5749 basereg = 16;
fe984136 5750 else if (targetm.calls.must_pass_in_stack (mode, type))
30102605 5751 return NULL_RTX;
30102605 5752 }
7e4fb06a
RH
5753#else
5754#error Unhandled ABI
5755#endif
5495cc55 5756
a82c7f05 5757 return gen_rtx_REG (mode, num_args + basereg);
5495cc55
RH
5758}
5759
78a52f11
RH
5760static int
5761alpha_arg_partial_bytes (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED,
5762 enum machine_mode mode ATTRIBUTE_UNUSED,
5763 tree type ATTRIBUTE_UNUSED,
5764 bool named ATTRIBUTE_UNUSED)
5765{
5766 int words = 0;
5767
5768#if TARGET_ABI_OPEN_VMS
5769 if (cum->num_args < 6
5770 && 6 < cum->num_args + ALPHA_ARG_SIZE (mode, type, named))
907f033f 5771 words = 6 - cum->num_args;
78a52f11
RH
5772#elif TARGET_ABI_UNICOSMK
5773 /* Never any split arguments. */
5774#elif TARGET_ABI_OSF
5775 if (*cum < 6 && 6 < *cum + ALPHA_ARG_SIZE (mode, type, named))
5776 words = 6 - *cum;
5777#else
5778#error Unhandled ABI
5779#endif
5780
5781 return words * UNITS_PER_WORD;
5782}
5783
5784
7e4fb06a
RH
5785/* Return true if TYPE must be returned in memory, instead of in registers. */
5786
f93c2180 5787static bool
586de218 5788alpha_return_in_memory (const_tree type, const_tree fndecl ATTRIBUTE_UNUSED)
7e4fb06a 5789{
f93c2180 5790 enum machine_mode mode = VOIDmode;
7e4fb06a
RH
5791 int size;
5792
5793 if (type)
5794 {
5795 mode = TYPE_MODE (type);
5796
050d3f9d
VF
5797 /* All aggregates are returned in memory, except on OpenVMS where
5798 records that fit 64 bits should be returned by immediate value
5799 as required by section 3.8.7.1 of the OpenVMS Calling Standard. */
5800 if (TARGET_ABI_OPEN_VMS
5801 && TREE_CODE (type) != ARRAY_TYPE
5802 && (unsigned HOST_WIDE_INT) int_size_in_bytes(type) <= 8)
5803 return false;
5804
7e4fb06a
RH
5805 if (AGGREGATE_TYPE_P (type))
5806 return true;
5807 }
5808
5809 size = GET_MODE_SIZE (mode);
5810 switch (GET_MODE_CLASS (mode))
5811 {
5812 case MODE_VECTOR_FLOAT:
5813 /* Pass all float vectors in memory, like an aggregate. */
5814 return true;
5815
5816 case MODE_COMPLEX_FLOAT:
5817 /* We judge complex floats on the size of their element,
5818 not the size of the whole type. */
5819 size = GET_MODE_UNIT_SIZE (mode);
5820 break;
5821
5822 case MODE_INT:
5823 case MODE_FLOAT:
5824 case MODE_COMPLEX_INT:
5825 case MODE_VECTOR_INT:
5826 break;
5827
5828 default:
f676971a 5829 /* ??? We get called on all sorts of random stuff from
56daab84
NS
5830 aggregate_value_p. We must return something, but it's not
5831 clear what's safe to return. Pretend it's a struct I
5832 guess. */
7e4fb06a
RH
5833 return true;
5834 }
5835
5836 /* Otherwise types must fit in one register. */
5837 return size > UNITS_PER_WORD;
5838}
5839
8cd5a4e0
RH
5840/* Return true if TYPE should be passed by invisible reference. */
5841
5842static bool
5843alpha_pass_by_reference (CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED,
5844 enum machine_mode mode,
586de218 5845 const_tree type ATTRIBUTE_UNUSED,
8cd5a4e0
RH
5846 bool named ATTRIBUTE_UNUSED)
5847{
5848 return mode == TFmode || mode == TCmode;
5849}
5850
7e4fb06a
RH
5851/* Define how to find the value returned by a function. VALTYPE is the
5852 data type of the value (as a tree). If the precise function being
5853 called is known, FUNC is its FUNCTION_DECL; otherwise, FUNC is 0.
5854 MODE is set instead of VALTYPE for libcalls.
5855
5856 On Alpha the value is found in $0 for integer functions and
5857 $f0 for floating-point functions. */
5858
5859rtx
586de218 5860function_value (const_tree valtype, const_tree func ATTRIBUTE_UNUSED,
7e4fb06a
RH
5861 enum machine_mode mode)
5862{
d58770e7 5863 unsigned int regnum, dummy ATTRIBUTE_UNUSED;
0a2aaacc 5864 enum mode_class mclass;
7e4fb06a 5865
56daab84 5866 gcc_assert (!valtype || !alpha_return_in_memory (valtype, func));
7e4fb06a
RH
5867
5868 if (valtype)
5869 mode = TYPE_MODE (valtype);
5870
0a2aaacc
KG
5871 mclass = GET_MODE_CLASS (mode);
5872 switch (mclass)
7e4fb06a
RH
5873 {
5874 case MODE_INT:
050d3f9d
VF
5875 /* Do the same thing as PROMOTE_MODE except for libcalls on VMS,
5876 where we have them returning both SImode and DImode. */
5877 if (!(TARGET_ABI_OPEN_VMS && valtype && AGGREGATE_TYPE_P (valtype)))
5878 PROMOTE_MODE (mode, dummy, valtype);
5efb1046 5879 /* FALLTHRU */
7e4fb06a
RH
5880
5881 case MODE_COMPLEX_INT:
5882 case MODE_VECTOR_INT:
5883 regnum = 0;
5884 break;
5885
5886 case MODE_FLOAT:
5887 regnum = 32;
5888 break;
5889
5890 case MODE_COMPLEX_FLOAT:
5891 {
5892 enum machine_mode cmode = GET_MODE_INNER (mode);
5893
5894 return gen_rtx_PARALLEL
5895 (VOIDmode,
5896 gen_rtvec (2,
5897 gen_rtx_EXPR_LIST (VOIDmode, gen_rtx_REG (cmode, 32),
a556fd39 5898 const0_rtx),
7e4fb06a
RH
5899 gen_rtx_EXPR_LIST (VOIDmode, gen_rtx_REG (cmode, 33),
5900 GEN_INT (GET_MODE_SIZE (cmode)))));
5901 }
5902
050d3f9d
VF
5903 case MODE_RANDOM:
5904 /* We should only reach here for BLKmode on VMS. */
5905 gcc_assert (TARGET_ABI_OPEN_VMS && mode == BLKmode);
5906 regnum = 0;
5907 break;
5908
7e4fb06a 5909 default:
56daab84 5910 gcc_unreachable ();
7e4fb06a
RH
5911 }
5912
5913 return gen_rtx_REG (mode, regnum);
5914}
5915
f676971a 5916/* TCmode complex values are passed by invisible reference. We
42ba5130
RH
5917 should not split these values. */
5918
5919static bool
3101faab 5920alpha_split_complex_arg (const_tree type)
42ba5130
RH
5921{
5922 return TYPE_MODE (type) != TCmode;
5923}
5924
c35d187f
RH
5925static tree
5926alpha_build_builtin_va_list (void)
a6f12d7c 5927{
5849d27c 5928 tree base, ofs, space, record, type_decl;
a6f12d7c 5929
30102605 5930 if (TARGET_ABI_OPEN_VMS || TARGET_ABI_UNICOSMK)
63966b3b
RH
5931 return ptr_type_node;
5932
f1e639b1 5933 record = (*lang_hooks.types.make_type) (RECORD_TYPE);
4c4bde29
AH
5934 type_decl = build_decl (BUILTINS_LOCATION,
5935 TYPE_DECL, get_identifier ("__va_list_tag"), record);
d4b15af9
RH
5936 TREE_CHAIN (record) = type_decl;
5937 TYPE_NAME (record) = type_decl;
5938
63966b3b 5939 /* C++? SET_IS_AGGR_TYPE (record, 1); */
a6f12d7c 5940
5849d27c 5941 /* Dummy field to prevent alignment warnings. */
4c4bde29
AH
5942 space = build_decl (BUILTINS_LOCATION,
5943 FIELD_DECL, NULL_TREE, integer_type_node);
5849d27c
RH
5944 DECL_FIELD_CONTEXT (space) = record;
5945 DECL_ARTIFICIAL (space) = 1;
5946 DECL_IGNORED_P (space) = 1;
5947
4c4bde29
AH
5948 ofs = build_decl (BUILTINS_LOCATION,
5949 FIELD_DECL, get_identifier ("__offset"),
63966b3b
RH
5950 integer_type_node);
5951 DECL_FIELD_CONTEXT (ofs) = record;
910ad8de 5952 DECL_CHAIN (ofs) = space;
fea8c257
UB
5953 /* ??? This is a hack, __offset is marked volatile to prevent
5954 DCE that confuses stdarg optimization and results in
5955 gcc.c-torture/execute/stdarg-1.c failure. See PR 41089. */
5956 TREE_THIS_VOLATILE (ofs) = 1;
29587b1c 5957
4c4bde29
AH
5958 base = build_decl (BUILTINS_LOCATION,
5959 FIELD_DECL, get_identifier ("__base"),
63966b3b
RH
5960 ptr_type_node);
5961 DECL_FIELD_CONTEXT (base) = record;
910ad8de 5962 DECL_CHAIN (base) = ofs;
29587b1c 5963
63966b3b
RH
5964 TYPE_FIELDS (record) = base;
5965 layout_type (record);
5966
9d30f3c1 5967 va_list_gpr_counter_field = ofs;
63966b3b
RH
5968 return record;
5969}
5970
3f620b5f 5971#if TARGET_ABI_OSF
9d30f3c1
JJ
5972/* Helper function for alpha_stdarg_optimize_hook. Skip over casts
5973 and constant additions. */
5974
777b1fbe 5975static gimple
9d30f3c1
JJ
5976va_list_skip_additions (tree lhs)
5977{
777b1fbe 5978 gimple stmt;
9d30f3c1
JJ
5979
5980 for (;;)
5981 {
777b1fbe
JJ
5982 enum tree_code code;
5983
9d30f3c1
JJ
5984 stmt = SSA_NAME_DEF_STMT (lhs);
5985
777b1fbe 5986 if (gimple_code (stmt) == GIMPLE_PHI)
9d30f3c1
JJ
5987 return stmt;
5988
777b1fbe
JJ
5989 if (!is_gimple_assign (stmt)
5990 || gimple_assign_lhs (stmt) != lhs)
5991 return NULL;
9d30f3c1 5992
777b1fbe
JJ
5993 if (TREE_CODE (gimple_assign_rhs1 (stmt)) != SSA_NAME)
5994 return stmt;
5995 code = gimple_assign_rhs_code (stmt);
5996 if (!CONVERT_EXPR_CODE_P (code)
5997 && ((code != PLUS_EXPR && code != POINTER_PLUS_EXPR)
5998 || TREE_CODE (gimple_assign_rhs2 (stmt)) != INTEGER_CST
5999 || !host_integerp (gimple_assign_rhs2 (stmt), 1)))
6000 return stmt;
9d30f3c1 6001
777b1fbe 6002 lhs = gimple_assign_rhs1 (stmt);
9d30f3c1
JJ
6003 }
6004}
6005
6006/* Check if LHS = RHS statement is
6007 LHS = *(ap.__base + ap.__offset + cst)
6008 or
6009 LHS = *(ap.__base
6010 + ((ap.__offset + cst <= 47)
6011 ? ap.__offset + cst - 48 : ap.__offset + cst) + cst2).
6012 If the former, indicate that GPR registers are needed,
6013 if the latter, indicate that FPR registers are needed.
138ae41e
RH
6014
6015 Also look for LHS = (*ptr).field, where ptr is one of the forms
6016 listed above.
6017
9d30f3c1 6018 On alpha, cfun->va_list_gpr_size is used as size of the needed
138ae41e
RH
6019 regs and cfun->va_list_fpr_size is a bitmask, bit 0 set if GPR
6020 registers are needed and bit 1 set if FPR registers are needed.
6021 Return true if va_list references should not be scanned for the
6022 current statement. */
9d30f3c1
JJ
6023
6024static bool
726a989a 6025alpha_stdarg_optimize_hook (struct stdarg_info *si, const_gimple stmt)
9d30f3c1 6026{
777b1fbe 6027 tree base, offset, rhs;
9d30f3c1 6028 int offset_arg = 1;
777b1fbe 6029 gimple base_stmt;
9d30f3c1 6030
777b1fbe
JJ
6031 if (get_gimple_rhs_class (gimple_assign_rhs_code (stmt))
6032 != GIMPLE_SINGLE_RHS)
6033 return false;
6034
6035 rhs = gimple_assign_rhs1 (stmt);
138ae41e
RH
6036 while (handled_component_p (rhs))
6037 rhs = TREE_OPERAND (rhs, 0);
70f34814 6038 if (TREE_CODE (rhs) != MEM_REF
9d30f3c1
JJ
6039 || TREE_CODE (TREE_OPERAND (rhs, 0)) != SSA_NAME)
6040 return false;
6041
777b1fbe
JJ
6042 stmt = va_list_skip_additions (TREE_OPERAND (rhs, 0));
6043 if (stmt == NULL
6044 || !is_gimple_assign (stmt)
6045 || gimple_assign_rhs_code (stmt) != POINTER_PLUS_EXPR)
9d30f3c1
JJ
6046 return false;
6047
777b1fbe 6048 base = gimple_assign_rhs1 (stmt);
9d30f3c1 6049 if (TREE_CODE (base) == SSA_NAME)
777b1fbe
JJ
6050 {
6051 base_stmt = va_list_skip_additions (base);
6052 if (base_stmt
6053 && is_gimple_assign (base_stmt)
6054 && gimple_assign_rhs_code (base_stmt) == COMPONENT_REF)
6055 base = gimple_assign_rhs1 (base_stmt);
6056 }
9d30f3c1
JJ
6057
6058 if (TREE_CODE (base) != COMPONENT_REF
6059 || TREE_OPERAND (base, 1) != TYPE_FIELDS (va_list_type_node))
6060 {
777b1fbe 6061 base = gimple_assign_rhs2 (stmt);
9d30f3c1 6062 if (TREE_CODE (base) == SSA_NAME)
777b1fbe
JJ
6063 {
6064 base_stmt = va_list_skip_additions (base);
6065 if (base_stmt
6066 && is_gimple_assign (base_stmt)
6067 && gimple_assign_rhs_code (base_stmt) == COMPONENT_REF)
6068 base = gimple_assign_rhs1 (base_stmt);
6069 }
9d30f3c1
JJ
6070
6071 if (TREE_CODE (base) != COMPONENT_REF
6072 || TREE_OPERAND (base, 1) != TYPE_FIELDS (va_list_type_node))
6073 return false;
6074
6075 offset_arg = 0;
6076 }
6077
6078 base = get_base_address (base);
6079 if (TREE_CODE (base) != VAR_DECL
6cb718e4 6080 || !bitmap_bit_p (si->va_list_vars, DECL_UID (base)))
9d30f3c1
JJ
6081 return false;
6082
777b1fbe 6083 offset = gimple_op (stmt, 1 + offset_arg);
9d30f3c1 6084 if (TREE_CODE (offset) == SSA_NAME)
9d30f3c1 6085 {
777b1fbe 6086 gimple offset_stmt = va_list_skip_additions (offset);
9d30f3c1 6087
777b1fbe
JJ
6088 if (offset_stmt
6089 && gimple_code (offset_stmt) == GIMPLE_PHI)
9d30f3c1 6090 {
777b1fbe
JJ
6091 HOST_WIDE_INT sub;
6092 gimple arg1_stmt, arg2_stmt;
6093 tree arg1, arg2;
6094 enum tree_code code1, code2;
9d30f3c1 6095
777b1fbe 6096 if (gimple_phi_num_args (offset_stmt) != 2)
3f620b5f 6097 goto escapes;
9d30f3c1 6098
777b1fbe
JJ
6099 arg1_stmt
6100 = va_list_skip_additions (gimple_phi_arg_def (offset_stmt, 0));
6101 arg2_stmt
6102 = va_list_skip_additions (gimple_phi_arg_def (offset_stmt, 1));
6103 if (arg1_stmt == NULL
6104 || !is_gimple_assign (arg1_stmt)
6105 || arg2_stmt == NULL
6106 || !is_gimple_assign (arg2_stmt))
6107 goto escapes;
9d30f3c1 6108
777b1fbe
JJ
6109 code1 = gimple_assign_rhs_code (arg1_stmt);
6110 code2 = gimple_assign_rhs_code (arg2_stmt);
6111 if (code1 == COMPONENT_REF
6112 && (code2 == MINUS_EXPR || code2 == PLUS_EXPR))
6113 /* Do nothing. */;
6114 else if (code2 == COMPONENT_REF
6115 && (code1 == MINUS_EXPR || code1 == PLUS_EXPR))
6116 {
6117 gimple tem = arg1_stmt;
6118 code2 = code1;
6119 arg1_stmt = arg2_stmt;
6120 arg2_stmt = tem;
6121 }
6122 else
6123 goto escapes;
3f620b5f 6124
777b1fbe
JJ
6125 if (!host_integerp (gimple_assign_rhs2 (arg2_stmt), 0))
6126 goto escapes;
3f620b5f 6127
777b1fbe
JJ
6128 sub = tree_low_cst (gimple_assign_rhs2 (arg2_stmt), 0);
6129 if (code2 == MINUS_EXPR)
6130 sub = -sub;
6131 if (sub < -48 || sub > -32)
6132 goto escapes;
9d30f3c1 6133
777b1fbe
JJ
6134 arg1 = gimple_assign_rhs1 (arg1_stmt);
6135 arg2 = gimple_assign_rhs1 (arg2_stmt);
6136 if (TREE_CODE (arg2) == SSA_NAME)
6137 {
6138 arg2_stmt = va_list_skip_additions (arg2);
6139 if (arg2_stmt == NULL
6140 || !is_gimple_assign (arg2_stmt)
6141 || gimple_assign_rhs_code (arg2_stmt) != COMPONENT_REF)
6142 goto escapes;
6143 arg2 = gimple_assign_rhs1 (arg2_stmt);
6144 }
6145 if (arg1 != arg2)
6146 goto escapes;
6147
6148 if (TREE_CODE (arg1) != COMPONENT_REF
6149 || TREE_OPERAND (arg1, 1) != va_list_gpr_counter_field
6150 || get_base_address (arg1) != base)
6151 goto escapes;
6152
6153 /* Need floating point regs. */
6154 cfun->va_list_fpr_size |= 2;
6155 return false;
6156 }
6157 if (offset_stmt
6158 && is_gimple_assign (offset_stmt)
6159 && gimple_assign_rhs_code (offset_stmt) == COMPONENT_REF)
6160 offset = gimple_assign_rhs1 (offset_stmt);
6161 }
6162 if (TREE_CODE (offset) != COMPONENT_REF
6163 || TREE_OPERAND (offset, 1) != va_list_gpr_counter_field
6164 || get_base_address (offset) != base)
9d30f3c1
JJ
6165 goto escapes;
6166 else
6167 /* Need general regs. */
6168 cfun->va_list_fpr_size |= 1;
6169 return false;
6170
6171escapes:
6172 si->va_list_escapes = true;
6173 return false;
6174}
3f620b5f 6175#endif
9d30f3c1 6176
35d9c403 6177/* Perform any needed actions needed for a function that is receiving a
f93c2180 6178 variable number of arguments. */
35d9c403 6179
f93c2180 6180static void
bae47977
RH
6181alpha_setup_incoming_varargs (CUMULATIVE_ARGS *pcum, enum machine_mode mode,
6182 tree type, int *pretend_size, int no_rtl)
f93c2180 6183{
bae47977
RH
6184 CUMULATIVE_ARGS cum = *pcum;
6185
6186 /* Skip the current argument. */
6187 FUNCTION_ARG_ADVANCE (cum, mode, type, 1);
6188
f93c2180
RH
6189#if TARGET_ABI_UNICOSMK
6190 /* On Unicos/Mk, the standard subroutine __T3E_MISMATCH stores all register
6191 arguments on the stack. Unfortunately, it doesn't always store the first
6192 one (i.e. the one that arrives in $16 or $f16). This is not a problem
6193 with stdargs as we always have at least one named argument there. */
bae47977 6194 if (cum.num_reg_words < 6)
f93c2180
RH
6195 {
6196 if (!no_rtl)
6197 {
bae47977 6198 emit_insn (gen_umk_mismatch_args (GEN_INT (cum.num_reg_words)));
f93c2180
RH
6199 emit_insn (gen_arg_home_umk ());
6200 }
6201 *pretend_size = 0;
6202 }
6203#elif TARGET_ABI_OPEN_VMS
6204 /* For VMS, we allocate space for all 6 arg registers plus a count.
35d9c403 6205
f93c2180
RH
6206 However, if NO registers need to be saved, don't allocate any space.
6207 This is not only because we won't need the space, but because AP
6208 includes the current_pretend_args_size and we don't want to mess up
6209 any ap-relative addresses already made. */
bae47977 6210 if (cum.num_args < 6)
f93c2180
RH
6211 {
6212 if (!no_rtl)
6213 {
6214 emit_move_insn (gen_rtx_REG (DImode, 1), virtual_incoming_args_rtx);
6215 emit_insn (gen_arg_home ());
6216 }
6217 *pretend_size = 7 * UNITS_PER_WORD;
6218 }
6219#else
6220 /* On OSF/1 and friends, we allocate space for all 12 arg registers, but
6221 only push those that are remaining. However, if NO registers need to
6222 be saved, don't allocate any space. This is not only because we won't
6223 need the space, but because AP includes the current_pretend_args_size
6224 and we don't want to mess up any ap-relative addresses already made.
6225
6226 If we are not to use the floating-point registers, save the integer
6227 registers where we would put the floating-point registers. This is
6228 not the most efficient way to implement varargs with just one register
6229 class, but it isn't worth doing anything more efficient in this rare
6230 case. */
35d9c403
RH
6231 if (cum >= 6)
6232 return;
6233
6234 if (!no_rtl)
6235 {
4862826d
ILT
6236 int count;
6237 alias_set_type set = get_varargs_alias_set ();
35d9c403
RH
6238 rtx tmp;
6239
3f620b5f
RH
6240 count = cfun->va_list_gpr_size / UNITS_PER_WORD;
6241 if (count > 6 - cum)
6242 count = 6 - cum;
35d9c403 6243
3f620b5f
RH
6244 /* Detect whether integer registers or floating-point registers
6245 are needed by the detected va_arg statements. See above for
6246 how these values are computed. Note that the "escape" value
6247 is VA_LIST_MAX_FPR_SIZE, which is 255, which has both of
6248 these bits set. */
6249 gcc_assert ((VA_LIST_MAX_FPR_SIZE & 3) == 3);
6250
6251 if (cfun->va_list_fpr_size & 1)
6252 {
6253 tmp = gen_rtx_MEM (BLKmode,
6254 plus_constant (virtual_incoming_args_rtx,
6255 (cum + 6) * UNITS_PER_WORD));
8476af98 6256 MEM_NOTRAP_P (tmp) = 1;
3f620b5f
RH
6257 set_mem_alias_set (tmp, set);
6258 move_block_from_reg (16 + cum, tmp, count);
6259 }
6260
6261 if (cfun->va_list_fpr_size & 2)
6262 {
6263 tmp = gen_rtx_MEM (BLKmode,
6264 plus_constant (virtual_incoming_args_rtx,
6265 cum * UNITS_PER_WORD));
8476af98 6266 MEM_NOTRAP_P (tmp) = 1;
3f620b5f
RH
6267 set_mem_alias_set (tmp, set);
6268 move_block_from_reg (16 + cum + TARGET_FPREGS*32, tmp, count);
6269 }
6270 }
35d9c403 6271 *pretend_size = 12 * UNITS_PER_WORD;
a5fe455b 6272#endif
f93c2180 6273}
35d9c403 6274
d7bd8aeb 6275static void
a5c24926 6276alpha_va_start (tree valist, rtx nextarg ATTRIBUTE_UNUSED)
63966b3b
RH
6277{
6278 HOST_WIDE_INT offset;
6279 tree t, offset_field, base_field;
29587b1c 6280
bdb429a5
RK
6281 if (TREE_CODE (TREE_TYPE (valist)) == ERROR_MARK)
6282 return;
6283
f7130778 6284 if (TARGET_ABI_UNICOSMK)
e5faf155 6285 std_expand_builtin_va_start (valist, nextarg);
63966b3b 6286
bd5bd7ac 6287 /* For Unix, TARGET_SETUP_INCOMING_VARARGS moves the starting address base
63966b3b
RH
6288 up by 48, storing fp arg registers in the first 48 bytes, and the
6289 integer arg registers in the next 48 bytes. This is only done,
6290 however, if any integer registers need to be stored.
6291
6292 If no integer registers need be stored, then we must subtract 48
6293 in order to account for the integer arg registers which are counted
35d9c403
RH
6294 in argsize above, but which are not actually stored on the stack.
6295 Must further be careful here about structures straddling the last
f676971a 6296 integer argument register; that futzes with pretend_args_size,
35d9c403 6297 which changes the meaning of AP. */
63966b3b 6298
bae47977 6299 if (NUM_ARGS < 6)
f7130778 6300 offset = TARGET_ABI_OPEN_VMS ? UNITS_PER_WORD : 6 * UNITS_PER_WORD;
89cfc2c6 6301 else
38173d38 6302 offset = -6 * UNITS_PER_WORD + crtl->args.pretend_args_size;
63966b3b 6303
f7130778
DR
6304 if (TARGET_ABI_OPEN_VMS)
6305 {
050d3f9d
VF
6306 t = make_tree (ptr_type_node, virtual_incoming_args_rtx);
6307 t = build2 (POINTER_PLUS_EXPR, ptr_type_node, t,
6308 size_int (offset + NUM_ARGS * UNITS_PER_WORD));
6309 t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist, t);
f7130778 6310 TREE_SIDE_EFFECTS (t) = 1;
f7130778
DR
6311 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
6312 }
6313 else
6314 {
6315 base_field = TYPE_FIELDS (TREE_TYPE (valist));
910ad8de 6316 offset_field = DECL_CHAIN (base_field);
f7130778 6317
47a25a46
RG
6318 base_field = build3 (COMPONENT_REF, TREE_TYPE (base_field),
6319 valist, base_field, NULL_TREE);
6320 offset_field = build3 (COMPONENT_REF, TREE_TYPE (offset_field),
6321 valist, offset_field, NULL_TREE);
f7130778
DR
6322
6323 t = make_tree (ptr_type_node, virtual_incoming_args_rtx);
5a4ac684
AP
6324 t = build2 (POINTER_PLUS_EXPR, ptr_type_node, t,
6325 size_int (offset));
726a989a 6326 t = build2 (MODIFY_EXPR, TREE_TYPE (base_field), base_field, t);
f7130778
DR
6327 TREE_SIDE_EFFECTS (t) = 1;
6328 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
6329
7d60be94 6330 t = build_int_cst (NULL_TREE, NUM_ARGS * UNITS_PER_WORD);
726a989a 6331 t = build2 (MODIFY_EXPR, TREE_TYPE (offset_field), offset_field, t);
f7130778
DR
6332 TREE_SIDE_EFFECTS (t) = 1;
6333 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
6334 }
63966b3b
RH
6335}
6336
28245018 6337static tree
777b1fbe 6338alpha_gimplify_va_arg_1 (tree type, tree base, tree offset,
726a989a 6339 gimple_seq *pre_p)
28245018 6340{
777b1fbe
JJ
6341 tree type_size, ptr_type, addend, t, addr;
6342 gimple_seq internal_post;
28245018 6343
28245018
RH
6344 /* If the type could not be passed in registers, skip the block
6345 reserved for the registers. */
fe984136 6346 if (targetm.calls.must_pass_in_stack (TYPE_MODE (type), type))
28245018 6347 {
7d60be94 6348 t = build_int_cst (TREE_TYPE (offset), 6*8);
726a989a
RB
6349 gimplify_assign (offset,
6350 build2 (MAX_EXPR, TREE_TYPE (offset), offset, t),
6351 pre_p);
28245018
RH
6352 }
6353
6354 addend = offset;
1f063d10 6355 ptr_type = build_pointer_type_for_mode (type, ptr_mode, true);
28245018 6356
08b0dc1b 6357 if (TREE_CODE (type) == COMPLEX_TYPE)
28245018
RH
6358 {
6359 tree real_part, imag_part, real_temp;
6360
65da5a20
RH
6361 real_part = alpha_gimplify_va_arg_1 (TREE_TYPE (type), base,
6362 offset, pre_p);
6363
6364 /* Copy the value into a new temporary, lest the formal temporary
28245018 6365 be reused out from under us. */
65da5a20 6366 real_temp = get_initialized_tmp_var (real_part, pre_p, NULL);
28245018 6367
65da5a20
RH
6368 imag_part = alpha_gimplify_va_arg_1 (TREE_TYPE (type), base,
6369 offset, pre_p);
28245018 6370
47a25a46 6371 return build2 (COMPLEX_EXPR, type, real_temp, imag_part);
28245018
RH
6372 }
6373 else if (TREE_CODE (type) == REAL_TYPE)
6374 {
6375 tree fpaddend, cond, fourtyeight;
6376
7d60be94 6377 fourtyeight = build_int_cst (TREE_TYPE (addend), 6*8);
47a25a46
RG
6378 fpaddend = fold_build2 (MINUS_EXPR, TREE_TYPE (addend),
6379 addend, fourtyeight);
6380 cond = fold_build2 (LT_EXPR, boolean_type_node, addend, fourtyeight);
6381 addend = fold_build3 (COND_EXPR, TREE_TYPE (addend), cond,
6382 fpaddend, addend);
28245018
RH
6383 }
6384
6385 /* Build the final address and force that value into a temporary. */
5a4ac684
AP
6386 addr = build2 (POINTER_PLUS_EXPR, ptr_type, fold_convert (ptr_type, base),
6387 fold_convert (sizetype, addend));
65da5a20
RH
6388 internal_post = NULL;
6389 gimplify_expr (&addr, pre_p, &internal_post, is_gimple_val, fb_rvalue);
777b1fbe 6390 gimple_seq_add_seq (pre_p, internal_post);
28245018
RH
6391
6392 /* Update the offset field. */
65da5a20
RH
6393 type_size = TYPE_SIZE_UNIT (TYPE_MAIN_VARIANT (type));
6394 if (type_size == NULL || TREE_OVERFLOW (type_size))
6395 t = size_zero_node;
6396 else
6397 {
6398 t = size_binop (PLUS_EXPR, type_size, size_int (7));
6399 t = size_binop (TRUNC_DIV_EXPR, t, size_int (8));
6400 t = size_binop (MULT_EXPR, t, size_int (8));
6401 }
6402 t = fold_convert (TREE_TYPE (offset), t);
726a989a
RB
6403 gimplify_assign (offset, build2 (PLUS_EXPR, TREE_TYPE (offset), offset, t),
6404 pre_p);
28245018 6405
d6e9821f 6406 return build_va_arg_indirect_ref (addr);
28245018
RH
6407}
6408
23a60a04 6409static tree
726a989a
RB
6410alpha_gimplify_va_arg (tree valist, tree type, gimple_seq *pre_p,
6411 gimple_seq *post_p)
28245018 6412{
23a60a04 6413 tree offset_field, base_field, offset, base, t, r;
08b0dc1b 6414 bool indirect;
28245018
RH
6415
6416 if (TARGET_ABI_OPEN_VMS || TARGET_ABI_UNICOSMK)
23a60a04 6417 return std_gimplify_va_arg_expr (valist, type, pre_p, post_p);
28245018
RH
6418
6419 base_field = TYPE_FIELDS (va_list_type_node);
910ad8de 6420 offset_field = DECL_CHAIN (base_field);
47a25a46
RG
6421 base_field = build3 (COMPONENT_REF, TREE_TYPE (base_field),
6422 valist, base_field, NULL_TREE);
6423 offset_field = build3 (COMPONENT_REF, TREE_TYPE (offset_field),
6424 valist, offset_field, NULL_TREE);
28245018 6425
65da5a20
RH
6426 /* Pull the fields of the structure out into temporaries. Since we never
6427 modify the base field, we can use a formal temporary. Sign-extend the
6428 offset field so that it's the proper width for pointer arithmetic. */
6429 base = get_formal_tmp_var (base_field, pre_p);
28245018 6430
65da5a20
RH
6431 t = fold_convert (lang_hooks.types.type_for_size (64, 0), offset_field);
6432 offset = get_initialized_tmp_var (t, pre_p, NULL);
28245018 6433
08b0dc1b
RH
6434 indirect = pass_by_reference (NULL, TYPE_MODE (type), type, false);
6435 if (indirect)
1f063d10 6436 type = build_pointer_type_for_mode (type, ptr_mode, true);
08b0dc1b 6437
28245018
RH
6438 /* Find the value. Note that this will be a stable indirection, or
6439 a composite of stable indirections in the case of complex. */
65da5a20 6440 r = alpha_gimplify_va_arg_1 (type, base, offset, pre_p);
28245018
RH
6441
6442 /* Stuff the offset temporary back into its field. */
777b1fbe 6443 gimplify_assign (unshare_expr (offset_field),
726a989a 6444 fold_convert (TREE_TYPE (offset_field), offset), pre_p);
23a60a04 6445
08b0dc1b 6446 if (indirect)
d6e9821f 6447 r = build_va_arg_indirect_ref (r);
08b0dc1b 6448
23a60a04 6449 return r;
28245018 6450}
a6f12d7c 6451\f
6d8fd7bb
RH
6452/* Builtins. */
6453
6454enum alpha_builtin
6455{
6456 ALPHA_BUILTIN_CMPBGE,
c4b50f1a
RH
6457 ALPHA_BUILTIN_EXTBL,
6458 ALPHA_BUILTIN_EXTWL,
6459 ALPHA_BUILTIN_EXTLL,
6d8fd7bb 6460 ALPHA_BUILTIN_EXTQL,
c4b50f1a
RH
6461 ALPHA_BUILTIN_EXTWH,
6462 ALPHA_BUILTIN_EXTLH,
6d8fd7bb 6463 ALPHA_BUILTIN_EXTQH,
c4b50f1a
RH
6464 ALPHA_BUILTIN_INSBL,
6465 ALPHA_BUILTIN_INSWL,
6466 ALPHA_BUILTIN_INSLL,
6467 ALPHA_BUILTIN_INSQL,
6468 ALPHA_BUILTIN_INSWH,
6469 ALPHA_BUILTIN_INSLH,
6470 ALPHA_BUILTIN_INSQH,
6471 ALPHA_BUILTIN_MSKBL,
6472 ALPHA_BUILTIN_MSKWL,
6473 ALPHA_BUILTIN_MSKLL,
6474 ALPHA_BUILTIN_MSKQL,
6475 ALPHA_BUILTIN_MSKWH,
6476 ALPHA_BUILTIN_MSKLH,
6477 ALPHA_BUILTIN_MSKQH,
6478 ALPHA_BUILTIN_UMULH,
6d8fd7bb
RH
6479 ALPHA_BUILTIN_ZAP,
6480 ALPHA_BUILTIN_ZAPNOT,
6481 ALPHA_BUILTIN_AMASK,
6482 ALPHA_BUILTIN_IMPLVER,
6483 ALPHA_BUILTIN_RPCC,
116b7a5e
RH
6484 ALPHA_BUILTIN_THREAD_POINTER,
6485 ALPHA_BUILTIN_SET_THREAD_POINTER,
221cf9ab
OH
6486 ALPHA_BUILTIN_ESTABLISH_VMS_CONDITION_HANDLER,
6487 ALPHA_BUILTIN_REVERT_VMS_CONDITION_HANDLER,
6d8fd7bb
RH
6488
6489 /* TARGET_MAX */
6490 ALPHA_BUILTIN_MINUB8,
6491 ALPHA_BUILTIN_MINSB8,
6492 ALPHA_BUILTIN_MINUW4,
6493 ALPHA_BUILTIN_MINSW4,
6494 ALPHA_BUILTIN_MAXUB8,
6495 ALPHA_BUILTIN_MAXSB8,
6496 ALPHA_BUILTIN_MAXUW4,
6497 ALPHA_BUILTIN_MAXSW4,
6498 ALPHA_BUILTIN_PERR,
6499 ALPHA_BUILTIN_PKLB,
6500 ALPHA_BUILTIN_PKWB,
6501 ALPHA_BUILTIN_UNPKBL,
6502 ALPHA_BUILTIN_UNPKBW,
6503
c4b50f1a
RH
6504 /* TARGET_CIX */
6505 ALPHA_BUILTIN_CTTZ,
6506 ALPHA_BUILTIN_CTLZ,
6507 ALPHA_BUILTIN_CTPOP,
6508
6d8fd7bb
RH
6509 ALPHA_BUILTIN_max
6510};
6511
e3136fa2 6512static enum insn_code const code_for_builtin[ALPHA_BUILTIN_max] = {
c4b50f1a
RH
6513 CODE_FOR_builtin_cmpbge,
6514 CODE_FOR_builtin_extbl,
6515 CODE_FOR_builtin_extwl,
6516 CODE_FOR_builtin_extll,
6517 CODE_FOR_builtin_extql,
6518 CODE_FOR_builtin_extwh,
6519 CODE_FOR_builtin_extlh,
6520 CODE_FOR_builtin_extqh,
6521 CODE_FOR_builtin_insbl,
6522 CODE_FOR_builtin_inswl,
6523 CODE_FOR_builtin_insll,
6524 CODE_FOR_builtin_insql,
6525 CODE_FOR_builtin_inswh,
6526 CODE_FOR_builtin_inslh,
6527 CODE_FOR_builtin_insqh,
6528 CODE_FOR_builtin_mskbl,
6529 CODE_FOR_builtin_mskwl,
6530 CODE_FOR_builtin_mskll,
6531 CODE_FOR_builtin_mskql,
6532 CODE_FOR_builtin_mskwh,
6533 CODE_FOR_builtin_msklh,
6534 CODE_FOR_builtin_mskqh,
6535 CODE_FOR_umuldi3_highpart,
6536 CODE_FOR_builtin_zap,
6537 CODE_FOR_builtin_zapnot,
6538 CODE_FOR_builtin_amask,
6539 CODE_FOR_builtin_implver,
6540 CODE_FOR_builtin_rpcc,
116b7a5e
RH
6541 CODE_FOR_load_tp,
6542 CODE_FOR_set_tp,
221cf9ab
OH
6543 CODE_FOR_builtin_establish_vms_condition_handler,
6544 CODE_FOR_builtin_revert_vms_condition_handler,
c4b50f1a
RH
6545
6546 /* TARGET_MAX */
6547 CODE_FOR_builtin_minub8,
6548 CODE_FOR_builtin_minsb8,
6549 CODE_FOR_builtin_minuw4,
6550 CODE_FOR_builtin_minsw4,
6551 CODE_FOR_builtin_maxub8,
6552 CODE_FOR_builtin_maxsb8,
6553 CODE_FOR_builtin_maxuw4,
6554 CODE_FOR_builtin_maxsw4,
6555 CODE_FOR_builtin_perr,
6556 CODE_FOR_builtin_pklb,
6557 CODE_FOR_builtin_pkwb,
6558 CODE_FOR_builtin_unpkbl,
6559 CODE_FOR_builtin_unpkbw,
6560
6561 /* TARGET_CIX */
36013987
RH
6562 CODE_FOR_ctzdi2,
6563 CODE_FOR_clzdi2,
6564 CODE_FOR_popcountdi2
c4b50f1a
RH
6565};
6566
6d8fd7bb
RH
6567struct alpha_builtin_def
6568{
6569 const char *name;
6570 enum alpha_builtin code;
6571 unsigned int target_mask;
36013987 6572 bool is_const;
6d8fd7bb
RH
6573};
6574
6575static struct alpha_builtin_def const zero_arg_builtins[] = {
36013987
RH
6576 { "__builtin_alpha_implver", ALPHA_BUILTIN_IMPLVER, 0, true },
6577 { "__builtin_alpha_rpcc", ALPHA_BUILTIN_RPCC, 0, false }
6d8fd7bb
RH
6578};
6579
6580static struct alpha_builtin_def const one_arg_builtins[] = {
36013987
RH
6581 { "__builtin_alpha_amask", ALPHA_BUILTIN_AMASK, 0, true },
6582 { "__builtin_alpha_pklb", ALPHA_BUILTIN_PKLB, MASK_MAX, true },
6583 { "__builtin_alpha_pkwb", ALPHA_BUILTIN_PKWB, MASK_MAX, true },
6584 { "__builtin_alpha_unpkbl", ALPHA_BUILTIN_UNPKBL, MASK_MAX, true },
6585 { "__builtin_alpha_unpkbw", ALPHA_BUILTIN_UNPKBW, MASK_MAX, true },
6586 { "__builtin_alpha_cttz", ALPHA_BUILTIN_CTTZ, MASK_CIX, true },
6587 { "__builtin_alpha_ctlz", ALPHA_BUILTIN_CTLZ, MASK_CIX, true },
6588 { "__builtin_alpha_ctpop", ALPHA_BUILTIN_CTPOP, MASK_CIX, true }
6d8fd7bb
RH
6589};
6590
6591static struct alpha_builtin_def const two_arg_builtins[] = {
36013987
RH
6592 { "__builtin_alpha_cmpbge", ALPHA_BUILTIN_CMPBGE, 0, true },
6593 { "__builtin_alpha_extbl", ALPHA_BUILTIN_EXTBL, 0, true },
6594 { "__builtin_alpha_extwl", ALPHA_BUILTIN_EXTWL, 0, true },
6595 { "__builtin_alpha_extll", ALPHA_BUILTIN_EXTLL, 0, true },
6596 { "__builtin_alpha_extql", ALPHA_BUILTIN_EXTQL, 0, true },
6597 { "__builtin_alpha_extwh", ALPHA_BUILTIN_EXTWH, 0, true },
6598 { "__builtin_alpha_extlh", ALPHA_BUILTIN_EXTLH, 0, true },
6599 { "__builtin_alpha_extqh", ALPHA_BUILTIN_EXTQH, 0, true },
6600 { "__builtin_alpha_insbl", ALPHA_BUILTIN_INSBL, 0, true },
6601 { "__builtin_alpha_inswl", ALPHA_BUILTIN_INSWL, 0, true },
6602 { "__builtin_alpha_insll", ALPHA_BUILTIN_INSLL, 0, true },
6603 { "__builtin_alpha_insql", ALPHA_BUILTIN_INSQL, 0, true },
6604 { "__builtin_alpha_inswh", ALPHA_BUILTIN_INSWH, 0, true },
6605 { "__builtin_alpha_inslh", ALPHA_BUILTIN_INSLH, 0, true },
6606 { "__builtin_alpha_insqh", ALPHA_BUILTIN_INSQH, 0, true },
6607 { "__builtin_alpha_mskbl", ALPHA_BUILTIN_MSKBL, 0, true },
6608 { "__builtin_alpha_mskwl", ALPHA_BUILTIN_MSKWL, 0, true },
6609 { "__builtin_alpha_mskll", ALPHA_BUILTIN_MSKLL, 0, true },
6610 { "__builtin_alpha_mskql", ALPHA_BUILTIN_MSKQL, 0, true },
6611 { "__builtin_alpha_mskwh", ALPHA_BUILTIN_MSKWH, 0, true },
6612 { "__builtin_alpha_msklh", ALPHA_BUILTIN_MSKLH, 0, true },
6613 { "__builtin_alpha_mskqh", ALPHA_BUILTIN_MSKQH, 0, true },
6614 { "__builtin_alpha_umulh", ALPHA_BUILTIN_UMULH, 0, true },
6615 { "__builtin_alpha_zap", ALPHA_BUILTIN_ZAP, 0, true },
6616 { "__builtin_alpha_zapnot", ALPHA_BUILTIN_ZAPNOT, 0, true },
6617 { "__builtin_alpha_minub8", ALPHA_BUILTIN_MINUB8, MASK_MAX, true },
6618 { "__builtin_alpha_minsb8", ALPHA_BUILTIN_MINSB8, MASK_MAX, true },
6619 { "__builtin_alpha_minuw4", ALPHA_BUILTIN_MINUW4, MASK_MAX, true },
6620 { "__builtin_alpha_minsw4", ALPHA_BUILTIN_MINSW4, MASK_MAX, true },
6621 { "__builtin_alpha_maxub8", ALPHA_BUILTIN_MAXUB8, MASK_MAX, true },
6622 { "__builtin_alpha_maxsb8", ALPHA_BUILTIN_MAXSB8, MASK_MAX, true },
6623 { "__builtin_alpha_maxuw4", ALPHA_BUILTIN_MAXUW4, MASK_MAX, true },
6624 { "__builtin_alpha_maxsw4", ALPHA_BUILTIN_MAXSW4, MASK_MAX, true },
6625 { "__builtin_alpha_perr", ALPHA_BUILTIN_PERR, MASK_MAX, true }
6d8fd7bb
RH
6626};
6627
36013987
RH
6628static GTY(()) tree alpha_v8qi_u;
6629static GTY(()) tree alpha_v8qi_s;
6630static GTY(()) tree alpha_v4hi_u;
6631static GTY(()) tree alpha_v4hi_s;
6632
b6e46ca1
RS
6633/* Helper function of alpha_init_builtins. Add the COUNT built-in
6634 functions pointed to by P, with function type FTYPE. */
6635
6636static void
6637alpha_add_builtins (const struct alpha_builtin_def *p, size_t count,
6638 tree ftype)
6639{
6640 tree decl;
6641 size_t i;
6642
6643 for (i = 0; i < count; ++i, ++p)
6644 if ((target_flags & p->target_mask) == p->target_mask)
6645 {
6646 decl = add_builtin_function (p->name, ftype, p->code, BUILT_IN_MD,
6647 NULL, NULL);
6648 if (p->is_const)
6649 TREE_READONLY (decl) = 1;
6650 TREE_NOTHROW (decl) = 1;
6651 }
6652}
6653
6654
6d8fd7bb 6655static void
a5c24926 6656alpha_init_builtins (void)
6d8fd7bb 6657{
f001093a 6658 tree dimode_integer_type_node;
b6e46ca1 6659 tree ftype, decl;
6d8fd7bb 6660
f001093a
EB
6661 dimode_integer_type_node = lang_hooks.types.type_for_mode (DImode, 0);
6662
b0d0a8a7
DR
6663 /* Fwrite on VMS is non-standard. */
6664#if TARGET_ABI_OPEN_VMS
6665 implicit_built_in_decls[(int) BUILT_IN_FWRITE] = NULL_TREE;
6666 implicit_built_in_decls[(int) BUILT_IN_FWRITE_UNLOCKED] = NULL_TREE;
6667#endif
6668
f001093a 6669 ftype = build_function_type (dimode_integer_type_node, void_list_node);
b6e46ca1
RS
6670 alpha_add_builtins (zero_arg_builtins, ARRAY_SIZE (zero_arg_builtins),
6671 ftype);
6d8fd7bb 6672
f001093a
EB
6673 ftype = build_function_type_list (dimode_integer_type_node,
6674 dimode_integer_type_node, NULL_TREE);
b6e46ca1
RS
6675 alpha_add_builtins (one_arg_builtins, ARRAY_SIZE (one_arg_builtins),
6676 ftype);
6d8fd7bb 6677
f001093a
EB
6678 ftype = build_function_type_list (dimode_integer_type_node,
6679 dimode_integer_type_node,
6680 dimode_integer_type_node, NULL_TREE);
b6e46ca1
RS
6681 alpha_add_builtins (two_arg_builtins, ARRAY_SIZE (two_arg_builtins),
6682 ftype);
116b7a5e
RH
6683
6684 ftype = build_function_type (ptr_type_node, void_list_node);
b6e46ca1
RS
6685 decl = add_builtin_function ("__builtin_thread_pointer", ftype,
6686 ALPHA_BUILTIN_THREAD_POINTER, BUILT_IN_MD,
6687 NULL, NULL);
6688 TREE_NOTHROW (decl) = 1;
116b7a5e 6689
b4de2f7d 6690 ftype = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
b6e46ca1
RS
6691 decl = add_builtin_function ("__builtin_set_thread_pointer", ftype,
6692 ALPHA_BUILTIN_SET_THREAD_POINTER, BUILT_IN_MD,
6693 NULL, NULL);
6694 TREE_NOTHROW (decl) = 1;
36013987 6695
221cf9ab
OH
6696 if (TARGET_ABI_OPEN_VMS)
6697 {
6698 ftype = build_function_type_list (ptr_type_node, ptr_type_node,
6699 NULL_TREE);
6700 add_builtin_function ("__builtin_establish_vms_condition_handler", ftype,
6701 ALPHA_BUILTIN_ESTABLISH_VMS_CONDITION_HANDLER,
6702 BUILT_IN_MD, NULL, NULL_TREE);
6703
6704 ftype = build_function_type_list (ptr_type_node, void_type_node,
6705 NULL_TREE);
6706 add_builtin_function ("__builtin_revert_vms_condition_handler", ftype,
6707 ALPHA_BUILTIN_REVERT_VMS_CONDITION_HANDLER,
6708 BUILT_IN_MD, NULL, NULL_TREE);
6709 }
6710
36013987
RH
6711 alpha_v8qi_u = build_vector_type (unsigned_intQI_type_node, 8);
6712 alpha_v8qi_s = build_vector_type (intQI_type_node, 8);
6713 alpha_v4hi_u = build_vector_type (unsigned_intHI_type_node, 4);
6714 alpha_v4hi_s = build_vector_type (intHI_type_node, 4);
6d8fd7bb
RH
6715}
6716
6717/* Expand an expression EXP that calls a built-in function,
6718 with result going to TARGET if that's convenient
6719 (and in mode MODE if that's convenient).
6720 SUBTARGET may be used as the target for computing one of EXP's operands.
6721 IGNORE is nonzero if the value is to be ignored. */
6722
6723static rtx
a5c24926
RH
6724alpha_expand_builtin (tree exp, rtx target,
6725 rtx subtarget ATTRIBUTE_UNUSED,
6726 enum machine_mode mode ATTRIBUTE_UNUSED,
6727 int ignore ATTRIBUTE_UNUSED)
6d8fd7bb 6728{
6d8fd7bb
RH
6729#define MAX_ARGS 2
6730
5039610b 6731 tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
6d8fd7bb 6732 unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
5039610b
SL
6733 tree arg;
6734 call_expr_arg_iterator iter;
6d8fd7bb
RH
6735 enum insn_code icode;
6736 rtx op[MAX_ARGS], pat;
6737 int arity;
116b7a5e 6738 bool nonvoid;
6d8fd7bb
RH
6739
6740 if (fcode >= ALPHA_BUILTIN_max)
6741 internal_error ("bad builtin fcode");
6742 icode = code_for_builtin[fcode];
6743 if (icode == 0)
6744 internal_error ("bad builtin fcode");
6745
116b7a5e
RH
6746 nonvoid = TREE_TYPE (TREE_TYPE (fndecl)) != void_type_node;
6747
5039610b
SL
6748 arity = 0;
6749 FOR_EACH_CALL_EXPR_ARG (arg, iter, exp)
6d8fd7bb
RH
6750 {
6751 const struct insn_operand_data *insn_op;
6752
6d8fd7bb
RH
6753 if (arg == error_mark_node)
6754 return NULL_RTX;
6755 if (arity > MAX_ARGS)
6756 return NULL_RTX;
6757
116b7a5e
RH
6758 insn_op = &insn_data[icode].operand[arity + nonvoid];
6759
bf758008 6760 op[arity] = expand_expr (arg, NULL_RTX, insn_op->mode, EXPAND_NORMAL);
6d8fd7bb 6761
6d8fd7bb
RH
6762 if (!(*insn_op->predicate) (op[arity], insn_op->mode))
6763 op[arity] = copy_to_mode_reg (insn_op->mode, op[arity]);
5039610b 6764 arity++;
6d8fd7bb
RH
6765 }
6766
116b7a5e
RH
6767 if (nonvoid)
6768 {
6769 enum machine_mode tmode = insn_data[icode].operand[0].mode;
6770 if (!target
6771 || GET_MODE (target) != tmode
6772 || !(*insn_data[icode].operand[0].predicate) (target, tmode))
6773 target = gen_reg_rtx (tmode);
6774 }
6d8fd7bb
RH
6775
6776 switch (arity)
6777 {
6778 case 0:
6779 pat = GEN_FCN (icode) (target);
6780 break;
6781 case 1:
116b7a5e
RH
6782 if (nonvoid)
6783 pat = GEN_FCN (icode) (target, op[0]);
6784 else
6785 pat = GEN_FCN (icode) (op[0]);
6d8fd7bb
RH
6786 break;
6787 case 2:
6788 pat = GEN_FCN (icode) (target, op[0], op[1]);
6789 break;
6790 default:
56daab84 6791 gcc_unreachable ();
6d8fd7bb
RH
6792 }
6793 if (!pat)
6794 return NULL_RTX;
6795 emit_insn (pat);
6796
116b7a5e
RH
6797 if (nonvoid)
6798 return target;
6799 else
6800 return const0_rtx;
6d8fd7bb 6801}
36013987
RH
6802
6803
6804/* Several bits below assume HWI >= 64 bits. This should be enforced
6805 by config.gcc. */
6806#if HOST_BITS_PER_WIDE_INT < 64
6807# error "HOST_WIDE_INT too small"
6808#endif
6809
6810/* Fold the builtin for the CMPBGE instruction. This is a vector comparison
a50aa827 6811 with an 8-bit output vector. OPINT contains the integer operands; bit N
36013987
RH
6812 of OP_CONST is set if OPINT[N] is valid. */
6813
6814static tree
6815alpha_fold_builtin_cmpbge (unsigned HOST_WIDE_INT opint[], long op_const)
6816{
6817 if (op_const == 3)
6818 {
6819 int i, val;
6820 for (i = 0, val = 0; i < 8; ++i)
6821 {
6822 unsigned HOST_WIDE_INT c0 = (opint[0] >> (i * 8)) & 0xff;
6823 unsigned HOST_WIDE_INT c1 = (opint[1] >> (i * 8)) & 0xff;
6824 if (c0 >= c1)
6825 val |= 1 << i;
6826 }
6827 return build_int_cst (long_integer_type_node, val);
6828 }
18410793 6829 else if (op_const == 2 && opint[1] == 0)
36013987
RH
6830 return build_int_cst (long_integer_type_node, 0xff);
6831 return NULL;
6832}
6833
6834/* Fold the builtin for the ZAPNOT instruction. This is essentially a
6835 specialized form of an AND operation. Other byte manipulation instructions
6836 are defined in terms of this instruction, so this is also used as a
6837 subroutine for other builtins.
6838
6839 OP contains the tree operands; OPINT contains the extracted integer values.
6840 Bit N of OP_CONST it set if OPINT[N] is valid. OP may be null if only
6841 OPINT may be considered. */
6842
6843static tree
6844alpha_fold_builtin_zapnot (tree *op, unsigned HOST_WIDE_INT opint[],
6845 long op_const)
6846{
6847 if (op_const & 2)
6848 {
6849 unsigned HOST_WIDE_INT mask = 0;
6850 int i;
6851
6852 for (i = 0; i < 8; ++i)
6853 if ((opint[1] >> i) & 1)
6854 mask |= (unsigned HOST_WIDE_INT)0xff << (i * 8);
6855
6856 if (op_const & 1)
6857 return build_int_cst (long_integer_type_node, opint[0] & mask);
6858
6859 if (op)
31ff73b5
KG
6860 return fold_build2 (BIT_AND_EXPR, long_integer_type_node, op[0],
6861 build_int_cst (long_integer_type_node, mask));
36013987
RH
6862 }
6863 else if ((op_const & 1) && opint[0] == 0)
6864 return build_int_cst (long_integer_type_node, 0);
6865 return NULL;
6866}
6867
6868/* Fold the builtins for the EXT family of instructions. */
6869
6870static tree
6871alpha_fold_builtin_extxx (tree op[], unsigned HOST_WIDE_INT opint[],
6872 long op_const, unsigned HOST_WIDE_INT bytemask,
6873 bool is_high)
6874{
6875 long zap_const = 2;
6876 tree *zap_op = NULL;
6877
6878 if (op_const & 2)
6879 {
6880 unsigned HOST_WIDE_INT loc;
6881
6882 loc = opint[1] & 7;
6883 if (BYTES_BIG_ENDIAN)
6884 loc ^= 7;
6885 loc *= 8;
6886
6887 if (loc != 0)
6888 {
6889 if (op_const & 1)
6890 {
6891 unsigned HOST_WIDE_INT temp = opint[0];
6892 if (is_high)
6893 temp <<= loc;
6894 else
6895 temp >>= loc;
6896 opint[0] = temp;
6897 zap_const = 3;
6898 }
6899 }
6900 else
6901 zap_op = op;
6902 }
6903
6904 opint[1] = bytemask;
6905 return alpha_fold_builtin_zapnot (zap_op, opint, zap_const);
6906}
6907
6908/* Fold the builtins for the INS family of instructions. */
6909
6910static tree
6911alpha_fold_builtin_insxx (tree op[], unsigned HOST_WIDE_INT opint[],
6912 long op_const, unsigned HOST_WIDE_INT bytemask,
6913 bool is_high)
6914{
6915 if ((op_const & 1) && opint[0] == 0)
6916 return build_int_cst (long_integer_type_node, 0);
6917
6918 if (op_const & 2)
6919 {
6920 unsigned HOST_WIDE_INT temp, loc, byteloc;
6921 tree *zap_op = NULL;
6922
6923 loc = opint[1] & 7;
6924 if (BYTES_BIG_ENDIAN)
6925 loc ^= 7;
6926 bytemask <<= loc;
6927
6928 temp = opint[0];
6929 if (is_high)
6930 {
6931 byteloc = (64 - (loc * 8)) & 0x3f;
6932 if (byteloc == 0)
6933 zap_op = op;
6934 else
6935 temp >>= byteloc;
6936 bytemask >>= 8;
6937 }
6938 else
6939 {
6940 byteloc = loc * 8;
6941 if (byteloc == 0)
6942 zap_op = op;
6943 else
6944 temp <<= byteloc;
6945 }
6946
6947 opint[0] = temp;
6948 opint[1] = bytemask;
6949 return alpha_fold_builtin_zapnot (zap_op, opint, op_const);
6950 }
6951
6952 return NULL;
6953}
6954
6955static tree
6956alpha_fold_builtin_mskxx (tree op[], unsigned HOST_WIDE_INT opint[],
6957 long op_const, unsigned HOST_WIDE_INT bytemask,
6958 bool is_high)
6959{
6960 if (op_const & 2)
6961 {
6962 unsigned HOST_WIDE_INT loc;
6963
6964 loc = opint[1] & 7;
6965 if (BYTES_BIG_ENDIAN)
6966 loc ^= 7;
6967 bytemask <<= loc;
6968
6969 if (is_high)
6970 bytemask >>= 8;
6971
6972 opint[1] = bytemask ^ 0xff;
6973 }
6974
6975 return alpha_fold_builtin_zapnot (op, opint, op_const);
6976}
6977
6978static tree
6979alpha_fold_builtin_umulh (unsigned HOST_WIDE_INT opint[], long op_const)
6980{
6981 switch (op_const)
6982 {
6983 case 3:
6984 {
6985 unsigned HOST_WIDE_INT l;
6986 HOST_WIDE_INT h;
6987
6988 mul_double (opint[0], 0, opint[1], 0, &l, &h);
6989
6990#if HOST_BITS_PER_WIDE_INT > 64
6991# error fixme
6992#endif
6993
6994 return build_int_cst (long_integer_type_node, h);
6995 }
6996
6997 case 1:
6998 opint[1] = opint[0];
6999 /* FALLTHRU */
7000 case 2:
7001 /* Note that (X*1) >> 64 == 0. */
7002 if (opint[1] == 0 || opint[1] == 1)
7003 return build_int_cst (long_integer_type_node, 0);
7004 break;
7005 }
7006 return NULL;
7007}
7008
7009static tree
7010alpha_fold_vector_minmax (enum tree_code code, tree op[], tree vtype)
7011{
7012 tree op0 = fold_convert (vtype, op[0]);
7013 tree op1 = fold_convert (vtype, op[1]);
31ff73b5 7014 tree val = fold_build2 (code, vtype, op0, op1);
ec46190f 7015 return fold_build1 (VIEW_CONVERT_EXPR, long_integer_type_node, val);
36013987
RH
7016}
7017
7018static tree
7019alpha_fold_builtin_perr (unsigned HOST_WIDE_INT opint[], long op_const)
7020{
7021 unsigned HOST_WIDE_INT temp = 0;
7022 int i;
7023
7024 if (op_const != 3)
7025 return NULL;
7026
7027 for (i = 0; i < 8; ++i)
7028 {
7029 unsigned HOST_WIDE_INT a = (opint[0] >> (i * 8)) & 0xff;
7030 unsigned HOST_WIDE_INT b = (opint[1] >> (i * 8)) & 0xff;
7031 if (a >= b)
7032 temp += a - b;
7033 else
7034 temp += b - a;
7035 }
7036
7037 return build_int_cst (long_integer_type_node, temp);
7038}
7039
7040static tree
7041alpha_fold_builtin_pklb (unsigned HOST_WIDE_INT opint[], long op_const)
7042{
7043 unsigned HOST_WIDE_INT temp;
7044
7045 if (op_const == 0)
7046 return NULL;
7047
7048 temp = opint[0] & 0xff;
7049 temp |= (opint[0] >> 24) & 0xff00;
7050
7051 return build_int_cst (long_integer_type_node, temp);
7052}
7053
7054static tree
7055alpha_fold_builtin_pkwb (unsigned HOST_WIDE_INT opint[], long op_const)
7056{
7057 unsigned HOST_WIDE_INT temp;
7058
7059 if (op_const == 0)
7060 return NULL;
7061
7062 temp = opint[0] & 0xff;
7063 temp |= (opint[0] >> 8) & 0xff00;
7064 temp |= (opint[0] >> 16) & 0xff0000;
7065 temp |= (opint[0] >> 24) & 0xff000000;
7066
7067 return build_int_cst (long_integer_type_node, temp);
7068}
7069
7070static tree
7071alpha_fold_builtin_unpkbl (unsigned HOST_WIDE_INT opint[], long op_const)
7072{
7073 unsigned HOST_WIDE_INT temp;
7074
7075 if (op_const == 0)
7076 return NULL;
7077
7078 temp = opint[0] & 0xff;
7079 temp |= (opint[0] & 0xff00) << 24;
7080
7081 return build_int_cst (long_integer_type_node, temp);
7082}
7083
7084static tree
7085alpha_fold_builtin_unpkbw (unsigned HOST_WIDE_INT opint[], long op_const)
7086{
7087 unsigned HOST_WIDE_INT temp;
7088
7089 if (op_const == 0)
7090 return NULL;
7091
7092 temp = opint[0] & 0xff;
7093 temp |= (opint[0] & 0x0000ff00) << 8;
7094 temp |= (opint[0] & 0x00ff0000) << 16;
7095 temp |= (opint[0] & 0xff000000) << 24;
7096
7097 return build_int_cst (long_integer_type_node, temp);
7098}
7099
7100static tree
7101alpha_fold_builtin_cttz (unsigned HOST_WIDE_INT opint[], long op_const)
7102{
7103 unsigned HOST_WIDE_INT temp;
7104
7105 if (op_const == 0)
7106 return NULL;
7107
7108 if (opint[0] == 0)
7109 temp = 64;
7110 else
7111 temp = exact_log2 (opint[0] & -opint[0]);
7112
7113 return build_int_cst (long_integer_type_node, temp);
7114}
7115
7116static tree
7117alpha_fold_builtin_ctlz (unsigned HOST_WIDE_INT opint[], long op_const)
7118{
7119 unsigned HOST_WIDE_INT temp;
7120
7121 if (op_const == 0)
7122 return NULL;
7123
7124 if (opint[0] == 0)
7125 temp = 64;
7126 else
7127 temp = 64 - floor_log2 (opint[0]) - 1;
7128
7129 return build_int_cst (long_integer_type_node, temp);
7130}
7131
7132static tree
7133alpha_fold_builtin_ctpop (unsigned HOST_WIDE_INT opint[], long op_const)
7134{
7135 unsigned HOST_WIDE_INT temp, op;
7136
7137 if (op_const == 0)
7138 return NULL;
7139
7140 op = opint[0];
7141 temp = 0;
7142 while (op)
7143 temp++, op &= op - 1;
7144
7145 return build_int_cst (long_integer_type_node, temp);
7146}
7147
7148/* Fold one of our builtin functions. */
7149
7150static tree
f311c3b4
NF
7151alpha_fold_builtin (tree fndecl, int n_args, tree *op,
7152 bool ignore ATTRIBUTE_UNUSED)
36013987 7153{
36013987 7154 unsigned HOST_WIDE_INT opint[MAX_ARGS];
58a11859 7155 long op_const = 0;
f311c3b4 7156 int i;
36013987 7157
f311c3b4
NF
7158 if (n_args >= MAX_ARGS)
7159 return NULL;
7160
7161 for (i = 0; i < n_args; i++)
36013987 7162 {
f311c3b4 7163 tree arg = op[i];
36013987
RH
7164 if (arg == error_mark_node)
7165 return NULL;
36013987 7166
f311c3b4 7167 opint[i] = 0;
36013987
RH
7168 if (TREE_CODE (arg) == INTEGER_CST)
7169 {
f311c3b4
NF
7170 op_const |= 1L << i;
7171 opint[i] = int_cst_value (arg);
36013987
RH
7172 }
7173 }
7174
7175 switch (DECL_FUNCTION_CODE (fndecl))
7176 {
7177 case ALPHA_BUILTIN_CMPBGE:
7178 return alpha_fold_builtin_cmpbge (opint, op_const);
7179
7180 case ALPHA_BUILTIN_EXTBL:
7181 return alpha_fold_builtin_extxx (op, opint, op_const, 0x01, false);
7182 case ALPHA_BUILTIN_EXTWL:
7183 return alpha_fold_builtin_extxx (op, opint, op_const, 0x03, false);
7184 case ALPHA_BUILTIN_EXTLL:
7185 return alpha_fold_builtin_extxx (op, opint, op_const, 0x0f, false);
7186 case ALPHA_BUILTIN_EXTQL:
7187 return alpha_fold_builtin_extxx (op, opint, op_const, 0xff, false);
7188 case ALPHA_BUILTIN_EXTWH:
7189 return alpha_fold_builtin_extxx (op, opint, op_const, 0x03, true);
7190 case ALPHA_BUILTIN_EXTLH:
7191 return alpha_fold_builtin_extxx (op, opint, op_const, 0x0f, true);
7192 case ALPHA_BUILTIN_EXTQH:
7193 return alpha_fold_builtin_extxx (op, opint, op_const, 0xff, true);
7194
7195 case ALPHA_BUILTIN_INSBL:
7196 return alpha_fold_builtin_insxx (op, opint, op_const, 0x01, false);
7197 case ALPHA_BUILTIN_INSWL:
7198 return alpha_fold_builtin_insxx (op, opint, op_const, 0x03, false);
7199 case ALPHA_BUILTIN_INSLL:
7200 return alpha_fold_builtin_insxx (op, opint, op_const, 0x0f, false);
7201 case ALPHA_BUILTIN_INSQL:
7202 return alpha_fold_builtin_insxx (op, opint, op_const, 0xff, false);
7203 case ALPHA_BUILTIN_INSWH:
7204 return alpha_fold_builtin_insxx (op, opint, op_const, 0x03, true);
7205 case ALPHA_BUILTIN_INSLH:
7206 return alpha_fold_builtin_insxx (op, opint, op_const, 0x0f, true);
7207 case ALPHA_BUILTIN_INSQH:
7208 return alpha_fold_builtin_insxx (op, opint, op_const, 0xff, true);
7209
7210 case ALPHA_BUILTIN_MSKBL:
7211 return alpha_fold_builtin_mskxx (op, opint, op_const, 0x01, false);
7212 case ALPHA_BUILTIN_MSKWL:
7213 return alpha_fold_builtin_mskxx (op, opint, op_const, 0x03, false);
7214 case ALPHA_BUILTIN_MSKLL:
7215 return alpha_fold_builtin_mskxx (op, opint, op_const, 0x0f, false);
7216 case ALPHA_BUILTIN_MSKQL:
7217 return alpha_fold_builtin_mskxx (op, opint, op_const, 0xff, false);
7218 case ALPHA_BUILTIN_MSKWH:
7219 return alpha_fold_builtin_mskxx (op, opint, op_const, 0x03, true);
7220 case ALPHA_BUILTIN_MSKLH:
7221 return alpha_fold_builtin_mskxx (op, opint, op_const, 0x0f, true);
7222 case ALPHA_BUILTIN_MSKQH:
7223 return alpha_fold_builtin_mskxx (op, opint, op_const, 0xff, true);
7224
7225 case ALPHA_BUILTIN_UMULH:
7226 return alpha_fold_builtin_umulh (opint, op_const);
7227
7228 case ALPHA_BUILTIN_ZAP:
7229 opint[1] ^= 0xff;
7230 /* FALLTHRU */
7231 case ALPHA_BUILTIN_ZAPNOT:
7232 return alpha_fold_builtin_zapnot (op, opint, op_const);
7233
7234 case ALPHA_BUILTIN_MINUB8:
7235 return alpha_fold_vector_minmax (MIN_EXPR, op, alpha_v8qi_u);
7236 case ALPHA_BUILTIN_MINSB8:
7237 return alpha_fold_vector_minmax (MIN_EXPR, op, alpha_v8qi_s);
7238 case ALPHA_BUILTIN_MINUW4:
7239 return alpha_fold_vector_minmax (MIN_EXPR, op, alpha_v4hi_u);
7240 case ALPHA_BUILTIN_MINSW4:
7241 return alpha_fold_vector_minmax (MIN_EXPR, op, alpha_v4hi_s);
7242 case ALPHA_BUILTIN_MAXUB8:
7243 return alpha_fold_vector_minmax (MAX_EXPR, op, alpha_v8qi_u);
7244 case ALPHA_BUILTIN_MAXSB8:
7245 return alpha_fold_vector_minmax (MAX_EXPR, op, alpha_v8qi_s);
7246 case ALPHA_BUILTIN_MAXUW4:
7247 return alpha_fold_vector_minmax (MAX_EXPR, op, alpha_v4hi_u);
7248 case ALPHA_BUILTIN_MAXSW4:
7249 return alpha_fold_vector_minmax (MAX_EXPR, op, alpha_v4hi_s);
7250
7251 case ALPHA_BUILTIN_PERR:
7252 return alpha_fold_builtin_perr (opint, op_const);
7253 case ALPHA_BUILTIN_PKLB:
7254 return alpha_fold_builtin_pklb (opint, op_const);
7255 case ALPHA_BUILTIN_PKWB:
7256 return alpha_fold_builtin_pkwb (opint, op_const);
7257 case ALPHA_BUILTIN_UNPKBL:
7258 return alpha_fold_builtin_unpkbl (opint, op_const);
7259 case ALPHA_BUILTIN_UNPKBW:
7260 return alpha_fold_builtin_unpkbw (opint, op_const);
7261
7262 case ALPHA_BUILTIN_CTTZ:
7263 return alpha_fold_builtin_cttz (opint, op_const);
7264 case ALPHA_BUILTIN_CTLZ:
7265 return alpha_fold_builtin_ctlz (opint, op_const);
7266 case ALPHA_BUILTIN_CTPOP:
7267 return alpha_fold_builtin_ctpop (opint, op_const);
7268
7269 case ALPHA_BUILTIN_AMASK:
7270 case ALPHA_BUILTIN_IMPLVER:
7271 case ALPHA_BUILTIN_RPCC:
7272 case ALPHA_BUILTIN_THREAD_POINTER:
7273 case ALPHA_BUILTIN_SET_THREAD_POINTER:
7274 /* None of these are foldable at compile-time. */
7275 default:
7276 return NULL;
7277 }
7278}
6d8fd7bb 7279\f
a6f12d7c
RK
7280/* This page contains routines that are used to determine what the function
7281 prologue and epilogue code will do and write them out. */
7282
7283/* Compute the size of the save area in the stack. */
7284
89cfc2c6
RK
7285/* These variables are used for communication between the following functions.
7286 They indicate various things about the current function being compiled
7287 that are used to tell what kind of prologue, epilogue and procedure
839a4992 7288 descriptor to generate. */
89cfc2c6
RK
7289
7290/* Nonzero if we need a stack procedure. */
c2ea1ac6
DR
7291enum alpha_procedure_types {PT_NULL = 0, PT_REGISTER = 1, PT_STACK = 2};
7292static enum alpha_procedure_types alpha_procedure_type;
89cfc2c6
RK
7293
7294/* Register number (either FP or SP) that is used to unwind the frame. */
9c0e94a5 7295static int vms_unwind_regno;
89cfc2c6
RK
7296
7297/* Register number used to save FP. We need not have one for RA since
7298 we don't modify it for register procedures. This is only defined
7299 for register frame procedures. */
9c0e94a5 7300static int vms_save_fp_regno;
89cfc2c6
RK
7301
7302/* Register number used to reference objects off our PV. */
9c0e94a5 7303static int vms_base_regno;
89cfc2c6 7304
acd92049 7305/* Compute register masks for saved registers. */
89cfc2c6
RK
7306
7307static void
a5c24926 7308alpha_sa_mask (unsigned long *imaskP, unsigned long *fmaskP)
89cfc2c6
RK
7309{
7310 unsigned long imask = 0;
7311 unsigned long fmask = 0;
1eb356b9 7312 unsigned int i;
89cfc2c6 7313
dd292d0a
MM
7314 /* When outputting a thunk, we don't have valid register life info,
7315 but assemble_start_function wants to output .frame and .mask
7316 directives. */
3c072c6b 7317 if (cfun->is_thunk)
acd92049 7318 {
14691f8d
RH
7319 *imaskP = 0;
7320 *fmaskP = 0;
7321 return;
7322 }
89cfc2c6 7323
c2ea1ac6 7324 if (TARGET_ABI_OPEN_VMS && alpha_procedure_type == PT_STACK)
409f52d3 7325 imask |= (1UL << HARD_FRAME_POINTER_REGNUM);
89cfc2c6 7326
14691f8d
RH
7327 /* One for every register we have to save. */
7328 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
7329 if (! fixed_regs[i] && ! call_used_regs[i]
6fb5fa3c 7330 && df_regs_ever_live_p (i) && i != REG_RA
14691f8d
RH
7331 && (!TARGET_ABI_UNICOSMK || i != HARD_FRAME_POINTER_REGNUM))
7332 {
7333 if (i < 32)
409f52d3 7334 imask |= (1UL << i);
14691f8d 7335 else
409f52d3 7336 fmask |= (1UL << (i - 32));
14691f8d
RH
7337 }
7338
7339 /* We need to restore these for the handler. */
e3b5732b 7340 if (crtl->calls_eh_return)
ed80cd68
RH
7341 {
7342 for (i = 0; ; ++i)
7343 {
7344 unsigned regno = EH_RETURN_DATA_REGNO (i);
7345 if (regno == INVALID_REGNUM)
7346 break;
7347 imask |= 1UL << regno;
7348 }
ed80cd68 7349 }
f676971a 7350
14691f8d
RH
7351 /* If any register spilled, then spill the return address also. */
7352 /* ??? This is required by the Digital stack unwind specification
7353 and isn't needed if we're doing Dwarf2 unwinding. */
7354 if (imask || fmask || alpha_ra_ever_killed ())
409f52d3 7355 imask |= (1UL << REG_RA);
9c0e94a5 7356
89cfc2c6
RK
7357 *imaskP = imask;
7358 *fmaskP = fmask;
89cfc2c6
RK
7359}
7360
7361int
a5c24926 7362alpha_sa_size (void)
89cfc2c6 7363{
61334ebe 7364 unsigned long mask[2];
89cfc2c6 7365 int sa_size = 0;
61334ebe 7366 int i, j;
89cfc2c6 7367
61334ebe
RH
7368 alpha_sa_mask (&mask[0], &mask[1]);
7369
7370 if (TARGET_ABI_UNICOSMK)
7371 {
7372 if (mask[0] || mask[1])
7373 sa_size = 14;
7374 }
acd92049 7375 else
acd92049 7376 {
61334ebe
RH
7377 for (j = 0; j < 2; ++j)
7378 for (i = 0; i < 32; ++i)
7379 if ((mask[j] >> i) & 1)
7380 sa_size++;
acd92049 7381 }
89cfc2c6 7382
30102605
RH
7383 if (TARGET_ABI_UNICOSMK)
7384 {
7385 /* We might not need to generate a frame if we don't make any calls
7386 (including calls to __T3E_MISMATCH if this is a vararg function),
7387 don't have any local variables which require stack slots, don't
7388 use alloca and have not determined that we need a frame for other
7389 reasons. */
7390
c2ea1ac6
DR
7391 alpha_procedure_type
7392 = (sa_size || get_frame_size() != 0
38173d38 7393 || crtl->outgoing_args_size
e3b5732b 7394 || cfun->stdarg || cfun->calls_alloca
c2ea1ac6
DR
7395 || frame_pointer_needed)
7396 ? PT_STACK : PT_REGISTER;
30102605
RH
7397
7398 /* Always reserve space for saving callee-saved registers if we
7399 need a frame as required by the calling convention. */
c2ea1ac6 7400 if (alpha_procedure_type == PT_STACK)
30102605
RH
7401 sa_size = 14;
7402 }
7403 else if (TARGET_ABI_OPEN_VMS)
9c0e94a5 7404 {
1d3499d8
OH
7405 /* Start with a stack procedure if we make any calls (REG_RA used), or
7406 need a frame pointer, with a register procedure if we otherwise need
7407 at least a slot, and with a null procedure in other cases. */
7408 if ((mask[0] >> REG_RA) & 1 || frame_pointer_needed)
c2ea1ac6
DR
7409 alpha_procedure_type = PT_STACK;
7410 else if (get_frame_size() != 0)
7411 alpha_procedure_type = PT_REGISTER;
7412 else
7413 alpha_procedure_type = PT_NULL;
61334ebe 7414
cb9a8e97 7415 /* Don't reserve space for saving FP & RA yet. Do that later after we've
61334ebe 7416 made the final decision on stack procedure vs register procedure. */
c2ea1ac6 7417 if (alpha_procedure_type == PT_STACK)
cb9a8e97 7418 sa_size -= 2;
9c0e94a5
RH
7419
7420 /* Decide whether to refer to objects off our PV via FP or PV.
7421 If we need FP for something else or if we receive a nonlocal
7422 goto (which expects PV to contain the value), we must use PV.
7423 Otherwise, start by assuming we can use FP. */
c2ea1ac6
DR
7424
7425 vms_base_regno
7426 = (frame_pointer_needed
e3b5732b 7427 || cfun->has_nonlocal_label
c2ea1ac6 7428 || alpha_procedure_type == PT_STACK
38173d38 7429 || crtl->outgoing_args_size)
c2ea1ac6 7430 ? REG_PV : HARD_FRAME_POINTER_REGNUM;
9c0e94a5
RH
7431
7432 /* If we want to copy PV into FP, we need to find some register
7433 in which to save FP. */
7434
7435 vms_save_fp_regno = -1;
7436 if (vms_base_regno == HARD_FRAME_POINTER_REGNUM)
7437 for (i = 0; i < 32; i++)
6fb5fa3c 7438 if (! fixed_regs[i] && call_used_regs[i] && ! df_regs_ever_live_p (i))
9c0e94a5
RH
7439 vms_save_fp_regno = i;
7440
221cf9ab
OH
7441 /* A VMS condition handler requires a stack procedure in our
7442 implementation. (not required by the calling standard). */
7443 if ((vms_save_fp_regno == -1 && alpha_procedure_type == PT_REGISTER)
7444 || cfun->machine->uses_condition_handler)
c2ea1ac6
DR
7445 vms_base_regno = REG_PV, alpha_procedure_type = PT_STACK;
7446 else if (alpha_procedure_type == PT_NULL)
7447 vms_base_regno = REG_PV;
9c0e94a5
RH
7448
7449 /* Stack unwinding should be done via FP unless we use it for PV. */
7450 vms_unwind_regno = (vms_base_regno == REG_PV
7451 ? HARD_FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM);
7452
221cf9ab
OH
7453 /* If this is a stack procedure, allow space for saving FP, RA and
7454 a condition handler slot if needed. */
c2ea1ac6 7455 if (alpha_procedure_type == PT_STACK)
221cf9ab 7456 sa_size += 2 + cfun->machine->uses_condition_handler;
9c0e94a5
RH
7457 }
7458 else
7459 {
9c0e94a5
RH
7460 /* Our size must be even (multiple of 16 bytes). */
7461 if (sa_size & 1)
7462 sa_size++;
7463 }
89cfc2c6
RK
7464
7465 return sa_size * 8;
7466}
7467
35d9c403
RH
7468/* Define the offset between two registers, one to be eliminated,
7469 and the other its replacement, at the start of a routine. */
7470
7471HOST_WIDE_INT
a5c24926
RH
7472alpha_initial_elimination_offset (unsigned int from,
7473 unsigned int to ATTRIBUTE_UNUSED)
35d9c403
RH
7474{
7475 HOST_WIDE_INT ret;
7476
7477 ret = alpha_sa_size ();
38173d38 7478 ret += ALPHA_ROUND (crtl->outgoing_args_size);
35d9c403 7479
56daab84
NS
7480 switch (from)
7481 {
7482 case FRAME_POINTER_REGNUM:
7483 break;
7484
7485 case ARG_POINTER_REGNUM:
7486 ret += (ALPHA_ROUND (get_frame_size ()
38173d38
JH
7487 + crtl->args.pretend_args_size)
7488 - crtl->args.pretend_args_size);
56daab84
NS
7489 break;
7490
7491 default:
7492 gcc_unreachable ();
7493 }
35d9c403
RH
7494
7495 return ret;
7496}
7497
1d3499d8
OH
7498#if TARGET_ABI_OPEN_VMS
7499
7b5cbb57
AS
7500/* Worker function for TARGET_CAN_ELIMINATE. */
7501
7502static bool
7503alpha_vms_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
89cfc2c6 7504{
1d3499d8 7505 /* We need the alpha_procedure_type to decide. Evaluate it now. */
89cfc2c6 7506 alpha_sa_size ();
1d3499d8
OH
7507
7508 switch (alpha_procedure_type)
7509 {
7510 case PT_NULL:
7511 /* NULL procedures have no frame of their own and we only
7512 know how to resolve from the current stack pointer. */
7513 return to == STACK_POINTER_REGNUM;
7514
7515 case PT_REGISTER:
7516 case PT_STACK:
7517 /* We always eliminate except to the stack pointer if there is no
7518 usable frame pointer at hand. */
7519 return (to != STACK_POINTER_REGNUM
7520 || vms_unwind_regno != HARD_FRAME_POINTER_REGNUM);
7521 }
7522
7523 gcc_unreachable ();
89cfc2c6
RK
7524}
7525
1d3499d8
OH
7526/* FROM is to be eliminated for TO. Return the offset so that TO+offset
7527 designates the same location as FROM. */
7528
7529HOST_WIDE_INT
7530alpha_vms_initial_elimination_offset (unsigned int from, unsigned int to)
7531{
7532 /* The only possible attempts we ever expect are ARG or FRAME_PTR to
7533 HARD_FRAME or STACK_PTR. We need the alpha_procedure_type to decide
7534 on the proper computations and will need the register save area size
7535 in most cases. */
7536
7537 HOST_WIDE_INT sa_size = alpha_sa_size ();
7538
7539 /* PT_NULL procedures have no frame of their own and we only allow
7540 elimination to the stack pointer. This is the argument pointer and we
7541 resolve the soft frame pointer to that as well. */
7542
7543 if (alpha_procedure_type == PT_NULL)
7544 return 0;
7545
7546 /* For a PT_STACK procedure the frame layout looks as follows
7547
7548 -----> decreasing addresses
7549
7550 < size rounded up to 16 | likewise >
7551 --------------#------------------------------+++--------------+++-------#
7552 incoming args # pretended args | "frame" | regs sa | PV | outgoing args #
7553 --------------#---------------------------------------------------------#
7554 ^ ^ ^ ^
7555 ARG_PTR FRAME_PTR HARD_FRAME_PTR STACK_PTR
7556
7557
7558 PT_REGISTER procedures are similar in that they may have a frame of their
7559 own. They have no regs-sa/pv/outgoing-args area.
7560
7561 We first compute offset to HARD_FRAME_PTR, then add what we need to get
7562 to STACK_PTR if need be. */
7563
7564 {
7565 HOST_WIDE_INT offset;
7566 HOST_WIDE_INT pv_save_size = alpha_procedure_type == PT_STACK ? 8 : 0;
7567
7568 switch (from)
7569 {
7570 case FRAME_POINTER_REGNUM:
7571 offset = ALPHA_ROUND (sa_size + pv_save_size);
7572 break;
7573 case ARG_POINTER_REGNUM:
7574 offset = (ALPHA_ROUND (sa_size + pv_save_size
7575 + get_frame_size ()
7576 + crtl->args.pretend_args_size)
7577 - crtl->args.pretend_args_size);
7578 break;
7579 default:
7580 gcc_unreachable ();
7581 }
7582
7583 if (to == STACK_POINTER_REGNUM)
7584 offset += ALPHA_ROUND (crtl->outgoing_args_size);
7585
7586 return offset;
7587 }
89cfc2c6
RK
7588}
7589
18fd5621
EB
7590#define COMMON_OBJECT "common_object"
7591
7592static tree
7593common_object_handler (tree *node, tree name ATTRIBUTE_UNUSED,
7594 tree args ATTRIBUTE_UNUSED, int flags ATTRIBUTE_UNUSED,
7595 bool *no_add_attrs ATTRIBUTE_UNUSED)
7596{
7597 tree decl = *node;
7598 gcc_assert (DECL_P (decl));
7599
7600 DECL_COMMON (decl) = 1;
7601 return NULL_TREE;
7602}
8289c43b 7603
6bc7bc14 7604static const struct attribute_spec vms_attribute_table[] =
a6f12d7c 7605{
91d231cb 7606 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
18fd5621
EB
7607 { COMMON_OBJECT, 0, 1, true, false, false, common_object_handler },
7608 { NULL, 0, 0, false, false, false, NULL }
91d231cb 7609};
a6f12d7c 7610
18fd5621
EB
7611void
7612vms_output_aligned_decl_common(FILE *file, tree decl, const char *name,
7613 unsigned HOST_WIDE_INT size,
7614 unsigned int align)
7615{
7616 tree attr = DECL_ATTRIBUTES (decl);
7617 fprintf (file, "%s", COMMON_ASM_OP);
7618 assemble_name (file, name);
7619 fprintf (file, "," HOST_WIDE_INT_PRINT_UNSIGNED, size);
7620 /* ??? Unlike on OSF/1, the alignment factor is not in log units. */
7621 fprintf (file, ",%u", align / BITS_PER_UNIT);
7622 if (attr)
7623 {
7624 attr = lookup_attribute (COMMON_OBJECT, attr);
7625 if (attr)
7626 fprintf (file, ",%s",
7627 IDENTIFIER_POINTER (TREE_VALUE (TREE_VALUE (attr))));
7628 }
7629 fputc ('\n', file);
7630}
7631
7632#undef COMMON_OBJECT
7633
8289c43b
NB
7634#endif
7635
1eb356b9 7636static int
a5c24926 7637find_lo_sum_using_gp (rtx *px, void *data ATTRIBUTE_UNUSED)
1eb356b9 7638{
77480b0b
RH
7639 return GET_CODE (*px) == LO_SUM && XEXP (*px, 0) == pic_offset_table_rtx;
7640}
7641
7642int
a5c24926 7643alpha_find_lo_sum_using_gp (rtx insn)
77480b0b
RH
7644{
7645 return for_each_rtx (&PATTERN (insn), find_lo_sum_using_gp, NULL) > 0;
1eb356b9
RH
7646}
7647
9c0e94a5 7648static int
a5c24926 7649alpha_does_function_need_gp (void)
9c0e94a5
RH
7650{
7651 rtx insn;
a6f12d7c 7652
30102605
RH
7653 /* The GP being variable is an OSF abi thing. */
7654 if (! TARGET_ABI_OSF)
9c0e94a5 7655 return 0;
a6f12d7c 7656
b64de1fe 7657 /* We need the gp to load the address of __mcount. */
e3b5732b 7658 if (TARGET_PROFILING_NEEDS_GP && crtl->profile)
9c0e94a5 7659 return 1;
d60a05a1 7660
b64de1fe 7661 /* The code emitted by alpha_output_mi_thunk_osf uses the gp. */
3c072c6b 7662 if (cfun->is_thunk)
acd92049 7663 return 1;
acd92049 7664
b64de1fe
RH
7665 /* The nonlocal receiver pattern assumes that the gp is valid for
7666 the nested function. Reasonable because it's almost always set
7667 correctly already. For the cases where that's wrong, make sure
7668 the nested function loads its gp on entry. */
e3b5732b 7669 if (crtl->has_nonlocal_goto)
b64de1fe
RH
7670 return 1;
7671
f676971a 7672 /* If we need a GP (we have a LDSYM insn or a CALL_INSN), load it first.
9c0e94a5
RH
7673 Even if we are a static function, we still need to do this in case
7674 our address is taken and passed to something like qsort. */
a6f12d7c 7675
9c0e94a5
RH
7676 push_topmost_sequence ();
7677 insn = get_insns ();
7678 pop_topmost_sequence ();
89cfc2c6 7679
9c0e94a5 7680 for (; insn; insn = NEXT_INSN (insn))
14e58be0 7681 if (NONDEBUG_INSN_P (insn)
807bdfb6 7682 && ! JUMP_TABLE_DATA_P (insn)
9c0e94a5 7683 && GET_CODE (PATTERN (insn)) != USE
77480b0b
RH
7684 && GET_CODE (PATTERN (insn)) != CLOBBER
7685 && get_attr_usegp (insn))
7686 return 1;
a6f12d7c 7687
9c0e94a5 7688 return 0;
a6f12d7c
RK
7689}
7690
ec6840c1 7691\f
6abc6f40
RH
7692/* Helper function to set RTX_FRAME_RELATED_P on instructions, including
7693 sequences. */
7694
7695static rtx
a5c24926 7696set_frame_related_p (void)
6abc6f40 7697{
2f937369
DM
7698 rtx seq = get_insns ();
7699 rtx insn;
7700
6abc6f40
RH
7701 end_sequence ();
7702
2f937369
DM
7703 if (!seq)
7704 return NULL_RTX;
7705
7706 if (INSN_P (seq))
6abc6f40 7707 {
2f937369
DM
7708 insn = seq;
7709 while (insn != NULL_RTX)
7710 {
7711 RTX_FRAME_RELATED_P (insn) = 1;
7712 insn = NEXT_INSN (insn);
7713 }
7714 seq = emit_insn (seq);
6abc6f40
RH
7715 }
7716 else
7717 {
7718 seq = emit_insn (seq);
7719 RTX_FRAME_RELATED_P (seq) = 1;
6abc6f40 7720 }
2f937369 7721 return seq;
6abc6f40
RH
7722}
7723
7724#define FRP(exp) (start_sequence (), exp, set_frame_related_p ())
7725
45f413e4 7726/* Generates a store with the proper unwind info attached. VALUE is
0e40b5f2 7727 stored at BASE_REG+BASE_OFS. If FRAME_BIAS is nonzero, then BASE_REG
45f413e4
RH
7728 contains SP+FRAME_BIAS, and that is the unwind info that should be
7729 generated. If FRAME_REG != VALUE, then VALUE is being stored on
7730 behalf of FRAME_REG, and FRAME_REG should be present in the unwind. */
7731
7732static void
7733emit_frame_store_1 (rtx value, rtx base_reg, HOST_WIDE_INT frame_bias,
7734 HOST_WIDE_INT base_ofs, rtx frame_reg)
7735{
7736 rtx addr, mem, insn;
7737
7738 addr = plus_constant (base_reg, base_ofs);
7739 mem = gen_rtx_MEM (DImode, addr);
7740 set_mem_alias_set (mem, alpha_sr_alias_set);
7741
7742 insn = emit_move_insn (mem, value);
7743 RTX_FRAME_RELATED_P (insn) = 1;
7744
7745 if (frame_bias || value != frame_reg)
7746 {
7747 if (frame_bias)
7748 {
7749 addr = plus_constant (stack_pointer_rtx, frame_bias + base_ofs);
7750 mem = gen_rtx_MEM (DImode, addr);
7751 }
7752
bf758008
UB
7753 add_reg_note (insn, REG_FRAME_RELATED_EXPR,
7754 gen_rtx_SET (VOIDmode, mem, frame_reg));
45f413e4
RH
7755 }
7756}
7757
7758static void
7759emit_frame_store (unsigned int regno, rtx base_reg,
7760 HOST_WIDE_INT frame_bias, HOST_WIDE_INT base_ofs)
7761{
7762 rtx reg = gen_rtx_REG (DImode, regno);
7763 emit_frame_store_1 (reg, base_reg, frame_bias, base_ofs, reg);
7764}
7765
d3c12306
EB
7766/* Compute the frame size. SIZE is the size of the "naked" frame
7767 and SA_SIZE is the size of the register save area. */
7768
7769static HOST_WIDE_INT
7770compute_frame_size (HOST_WIDE_INT size, HOST_WIDE_INT sa_size)
7771{
7772 if (TARGET_ABI_OPEN_VMS)
7773 return ALPHA_ROUND (sa_size
7774 + (alpha_procedure_type == PT_STACK ? 8 : 0)
7775 + size
7776 + crtl->args.pretend_args_size);
7777 else if (TARGET_ABI_UNICOSMK)
7778 /* We have to allocate space for the DSIB if we generate a frame. */
7779 return ALPHA_ROUND (sa_size
7780 + (alpha_procedure_type == PT_STACK ? 48 : 0))
7781 + ALPHA_ROUND (size
7782 + crtl->outgoing_args_size);
7783 else
7784 return ALPHA_ROUND (crtl->outgoing_args_size)
7785 + sa_size
7786 + ALPHA_ROUND (size
7787 + crtl->args.pretend_args_size);
7788}
7789
a6f12d7c
RK
7790/* Write function prologue. */
7791
89cfc2c6
RK
7792/* On vms we have two kinds of functions:
7793
7794 - stack frame (PROC_STACK)
7795 these are 'normal' functions with local vars and which are
7796 calling other functions
7797 - register frame (PROC_REGISTER)
7798 keeps all data in registers, needs no stack
7799
7800 We must pass this to the assembler so it can generate the
7801 proper pdsc (procedure descriptor)
7802 This is done with the '.pdesc' command.
7803
9c0e94a5
RH
7804 On not-vms, we don't really differentiate between the two, as we can
7805 simply allocate stack without saving registers. */
89cfc2c6
RK
7806
7807void
a5c24926 7808alpha_expand_prologue (void)
89cfc2c6 7809{
9c0e94a5 7810 /* Registers to save. */
89cfc2c6
RK
7811 unsigned long imask = 0;
7812 unsigned long fmask = 0;
7813 /* Stack space needed for pushing registers clobbered by us. */
7814 HOST_WIDE_INT sa_size;
7815 /* Complete stack size needed. */
7816 HOST_WIDE_INT frame_size;
7817 /* Offset from base reg to register save area. */
9c0e94a5 7818 HOST_WIDE_INT reg_offset;
45f413e4 7819 rtx sa_reg;
89cfc2c6
RK
7820 int i;
7821
7822 sa_size = alpha_sa_size ();
d3c12306 7823 frame_size = compute_frame_size (get_frame_size (), sa_size);
89cfc2c6 7824
d3c12306
EB
7825 if (flag_stack_usage)
7826 current_function_static_stack_size = frame_size;
89cfc2c6 7827
be7b80f4 7828 if (TARGET_ABI_OPEN_VMS)
221cf9ab 7829 reg_offset = 8 + 8 * cfun->machine->uses_condition_handler;
9c0e94a5 7830 else
38173d38 7831 reg_offset = ALPHA_ROUND (crtl->outgoing_args_size);
89cfc2c6 7832
9c0e94a5 7833 alpha_sa_mask (&imask, &fmask);
89cfc2c6 7834
941cc05a 7835 /* Emit an insn to reload GP, if needed. */
be7b80f4 7836 if (TARGET_ABI_OSF)
941cc05a
RK
7837 {
7838 alpha_function_needs_gp = alpha_does_function_need_gp ();
7839 if (alpha_function_needs_gp)
7840 emit_insn (gen_prologue_ldgp ());
7841 }
7842
4f1c5cce
RH
7843 /* TARGET_PROFILING_NEEDS_GP actually implies that we need to insert
7844 the call to mcount ourselves, rather than having the linker do it
7845 magically in response to -pg. Since _mcount has special linkage,
7846 don't represent the call as a call. */
e3b5732b 7847 if (TARGET_PROFILING_NEEDS_GP && crtl->profile)
4f1c5cce 7848 emit_insn (gen_prologue_mcount ());
30102605
RH
7849
7850 if (TARGET_ABI_UNICOSMK)
7851 unicosmk_gen_dsib (&imask);
7852
89cfc2c6
RK
7853 /* Adjust the stack by the frame size. If the frame size is > 4096
7854 bytes, we need to be sure we probe somewhere in the first and last
7855 4096 bytes (we can probably get away without the latter test) and
7856 every 8192 bytes in between. If the frame size is > 32768, we
7857 do this in a loop. Otherwise, we generate the explicit probe
f676971a 7858 instructions.
89cfc2c6
RK
7859
7860 Note that we are only allowed to adjust sp once in the prologue. */
7861
9c0e94a5 7862 if (frame_size <= 32768)
89cfc2c6
RK
7863 {
7864 if (frame_size > 4096)
7865 {
11eef578 7866 int probed;
89cfc2c6 7867
11eef578 7868 for (probed = 4096; probed < frame_size; probed += 8192)
30102605
RH
7869 emit_insn (gen_probe_stack (GEN_INT (TARGET_ABI_UNICOSMK
7870 ? -probed + 64
7871 : -probed)));
89cfc2c6
RK
7872
7873 /* We only have to do this probe if we aren't saving registers. */
11eef578 7874 if (sa_size == 0 && frame_size > probed - 4096)
9c0e94a5 7875 emit_insn (gen_probe_stack (GEN_INT (-frame_size)));
89cfc2c6
RK
7876 }
7877
7878 if (frame_size != 0)
8207e7c6 7879 FRP (emit_insn (gen_adddi3 (stack_pointer_rtx, stack_pointer_rtx,
30102605
RH
7880 GEN_INT (TARGET_ABI_UNICOSMK
7881 ? -frame_size + 64
7882 : -frame_size))));
89cfc2c6
RK
7883 }
7884 else
7885 {
9c0e94a5 7886 /* Here we generate code to set R22 to SP + 4096 and set R23 to the
89cfc2c6
RK
7887 number of 8192 byte blocks to probe. We then probe each block
7888 in the loop and then set SP to the proper location. If the
7889 amount remaining is > 4096, we have to do one more probe if we
7890 are not saving any registers. */
7891
7892 HOST_WIDE_INT blocks = (frame_size + 4096) / 8192;
7893 HOST_WIDE_INT leftover = frame_size + 4096 - blocks * 8192;
9c0e94a5
RH
7894 rtx ptr = gen_rtx_REG (DImode, 22);
7895 rtx count = gen_rtx_REG (DImode, 23);
37679e06 7896 rtx seq;
89cfc2c6 7897
9c0e94a5 7898 emit_move_insn (count, GEN_INT (blocks));
30102605
RH
7899 emit_insn (gen_adddi3 (ptr, stack_pointer_rtx,
7900 GEN_INT (TARGET_ABI_UNICOSMK ? 4096 - 64 : 4096)));
89cfc2c6 7901
9c0e94a5
RH
7902 /* Because of the difficulty in emitting a new basic block this
7903 late in the compilation, generate the loop as a single insn. */
7904 emit_insn (gen_prologue_stack_probe_loop (count, ptr));
89cfc2c6
RK
7905
7906 if (leftover > 4096 && sa_size == 0)
9c0e94a5
RH
7907 {
7908 rtx last = gen_rtx_MEM (DImode, plus_constant (ptr, -leftover));
7909 MEM_VOLATILE_P (last) = 1;
7910 emit_move_insn (last, const0_rtx);
7911 }
89cfc2c6 7912
be7b80f4 7913 if (TARGET_ABI_WINDOWS_NT)
f9d7e5cd
RH
7914 {
7915 /* For NT stack unwind (done by 'reverse execution'), it's
7916 not OK to take the result of a loop, even though the value
7917 is already in ptr, so we reload it via a single operation
f676971a 7918 and subtract it to sp.
37679e06
RH
7919
7920 Yes, that's correct -- we have to reload the whole constant
5c9948f4 7921 into a temporary via ldah+lda then subtract from sp. */
f9d7e5cd
RH
7922
7923 HOST_WIDE_INT lo, hi;
14eecd34
RH
7924 lo = ((frame_size & 0xffff) ^ 0x8000) - 0x8000;
7925 hi = frame_size - lo;
6abc6f40 7926
37679e06 7927 emit_move_insn (ptr, GEN_INT (hi));
5c9948f4 7928 emit_insn (gen_adddi3 (ptr, ptr, GEN_INT (lo)));
37679e06
RH
7929 seq = emit_insn (gen_subdi3 (stack_pointer_rtx, stack_pointer_rtx,
7930 ptr));
f9d7e5cd
RH
7931 }
7932 else
7933 {
f9d7e5cd
RH
7934 seq = emit_insn (gen_adddi3 (stack_pointer_rtx, ptr,
7935 GEN_INT (-leftover)));
f9d7e5cd 7936 }
37679e06
RH
7937
7938 /* This alternative is special, because the DWARF code cannot
7939 possibly intuit through the loop above. So we invent this
7940 note it looks at instead. */
7941 RTX_FRAME_RELATED_P (seq) = 1;
bf758008
UB
7942 add_reg_note (seq, REG_FRAME_RELATED_EXPR,
7943 gen_rtx_SET (VOIDmode, stack_pointer_rtx,
7944 gen_rtx_PLUS (Pmode, stack_pointer_rtx,
7945 GEN_INT (TARGET_ABI_UNICOSMK
7946 ? -frame_size + 64
7947 : -frame_size))));
89cfc2c6
RK
7948 }
7949
30102605 7950 if (!TARGET_ABI_UNICOSMK)
89cfc2c6 7951 {
45f413e4
RH
7952 HOST_WIDE_INT sa_bias = 0;
7953
30102605
RH
7954 /* Cope with very large offsets to the register save area. */
7955 sa_reg = stack_pointer_rtx;
7956 if (reg_offset + sa_size > 0x8000)
7957 {
7958 int low = ((reg_offset & 0xffff) ^ 0x8000) - 0x8000;
45f413e4 7959 rtx sa_bias_rtx;
89cfc2c6 7960
30102605 7961 if (low + sa_size <= 0x8000)
45f413e4 7962 sa_bias = reg_offset - low, reg_offset = low;
f676971a 7963 else
45f413e4 7964 sa_bias = reg_offset, reg_offset = 0;
89cfc2c6 7965
30102605 7966 sa_reg = gen_rtx_REG (DImode, 24);
45f413e4
RH
7967 sa_bias_rtx = GEN_INT (sa_bias);
7968
7969 if (add_operand (sa_bias_rtx, DImode))
7970 emit_insn (gen_adddi3 (sa_reg, stack_pointer_rtx, sa_bias_rtx));
7971 else
7972 {
7973 emit_move_insn (sa_reg, sa_bias_rtx);
7974 emit_insn (gen_adddi3 (sa_reg, stack_pointer_rtx, sa_reg));
7975 }
30102605 7976 }
f676971a 7977
30102605 7978 /* Save regs in stack order. Beginning with VMS PV. */
c2ea1ac6 7979 if (TARGET_ABI_OPEN_VMS && alpha_procedure_type == PT_STACK)
45f413e4 7980 emit_frame_store (REG_PV, stack_pointer_rtx, 0, 0);
89cfc2c6 7981
30102605 7982 /* Save register RA next. */
409f52d3 7983 if (imask & (1UL << REG_RA))
30102605 7984 {
45f413e4 7985 emit_frame_store (REG_RA, sa_reg, sa_bias, reg_offset);
409f52d3 7986 imask &= ~(1UL << REG_RA);
30102605
RH
7987 reg_offset += 8;
7988 }
89cfc2c6 7989
30102605 7990 /* Now save any other registers required to be saved. */
ed80cd68 7991 for (i = 0; i < 31; i++)
409f52d3 7992 if (imask & (1UL << i))
30102605 7993 {
45f413e4 7994 emit_frame_store (i, sa_reg, sa_bias, reg_offset);
30102605
RH
7995 reg_offset += 8;
7996 }
89cfc2c6 7997
ed80cd68 7998 for (i = 0; i < 31; i++)
409f52d3 7999 if (fmask & (1UL << i))
30102605 8000 {
45f413e4 8001 emit_frame_store (i+32, sa_reg, sa_bias, reg_offset);
30102605
RH
8002 reg_offset += 8;
8003 }
8004 }
c2ea1ac6 8005 else if (TARGET_ABI_UNICOSMK && alpha_procedure_type == PT_STACK)
30102605
RH
8006 {
8007 /* The standard frame on the T3E includes space for saving registers.
8008 We just have to use it. We don't have to save the return address and
8009 the old frame pointer here - they are saved in the DSIB. */
8010
8011 reg_offset = -56;
8012 for (i = 9; i < 15; i++)
409f52d3 8013 if (imask & (1UL << i))
30102605 8014 {
45f413e4 8015 emit_frame_store (i, hard_frame_pointer_rtx, 0, reg_offset);
30102605
RH
8016 reg_offset -= 8;
8017 }
8018 for (i = 2; i < 10; i++)
409f52d3 8019 if (fmask & (1UL << i))
30102605 8020 {
45f413e4 8021 emit_frame_store (i+32, hard_frame_pointer_rtx, 0, reg_offset);
30102605
RH
8022 reg_offset -= 8;
8023 }
8024 }
89cfc2c6 8025
be7b80f4 8026 if (TARGET_ABI_OPEN_VMS)
89cfc2c6 8027 {
15cb981a 8028 /* Register frame procedures save the fp. */
c2ea1ac6 8029 if (alpha_procedure_type == PT_REGISTER)
15cb981a
RH
8030 {
8031 rtx insn = emit_move_insn (gen_rtx_REG (DImode, vms_save_fp_regno),
8032 hard_frame_pointer_rtx);
8033 add_reg_note (insn, REG_CFA_REGISTER, NULL);
8034 RTX_FRAME_RELATED_P (insn) = 1;
8035 }
89cfc2c6 8036
c2ea1ac6 8037 if (alpha_procedure_type != PT_NULL && vms_base_regno != REG_PV)
54aaa4ea
RH
8038 emit_insn (gen_force_movdi (gen_rtx_REG (DImode, vms_base_regno),
8039 gen_rtx_REG (DImode, REG_PV)));
89cfc2c6 8040
c2ea1ac6
DR
8041 if (alpha_procedure_type != PT_NULL
8042 && vms_unwind_regno == HARD_FRAME_POINTER_REGNUM)
8207e7c6 8043 FRP (emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx));
89cfc2c6 8044
9c0e94a5 8045 /* If we have to allocate space for outgoing args, do it now. */
38173d38 8046 if (crtl->outgoing_args_size != 0)
c1238896
OH
8047 {
8048 rtx seq
f676971a 8049 = emit_move_insn (stack_pointer_rtx,
c1238896
OH
8050 plus_constant
8051 (hard_frame_pointer_rtx,
8052 - (ALPHA_ROUND
38173d38 8053 (crtl->outgoing_args_size))));
f676971a 8054
c1238896
OH
8055 /* Only set FRAME_RELATED_P on the stack adjustment we just emitted
8056 if ! frame_pointer_needed. Setting the bit will change the CFA
8057 computation rule to use sp again, which would be wrong if we had
8058 frame_pointer_needed, as this means sp might move unpredictably
8059 later on.
8060
8061 Also, note that
8062 frame_pointer_needed
8063 => vms_unwind_regno == HARD_FRAME_POINTER_REGNUM
8064 and
38173d38 8065 crtl->outgoing_args_size != 0
c1238896
OH
8066 => alpha_procedure_type != PT_NULL,
8067
8068 so when we are not setting the bit here, we are guaranteed to
093354e0 8069 have emitted an FRP frame pointer update just before. */
c1238896
OH
8070 RTX_FRAME_RELATED_P (seq) = ! frame_pointer_needed;
8071 }
9c0e94a5 8072 }
30102605 8073 else if (!TARGET_ABI_UNICOSMK)
9c0e94a5
RH
8074 {
8075 /* If we need a frame pointer, set it from the stack pointer. */
8076 if (frame_pointer_needed)
8077 {
8078 if (TARGET_CAN_FAULT_IN_PROLOGUE)
6abc6f40 8079 FRP (emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx));
89cfc2c6 8080 else
8207e7c6
RK
8081 /* This must always be the last instruction in the
8082 prologue, thus we emit a special move + clobber. */
6abc6f40
RH
8083 FRP (emit_insn (gen_init_fp (hard_frame_pointer_rtx,
8084 stack_pointer_rtx, sa_reg)));
89cfc2c6 8085 }
89cfc2c6
RK
8086 }
8087
9c0e94a5
RH
8088 /* The ABIs for VMS and OSF/1 say that while we can schedule insns into
8089 the prologue, for exception handling reasons, we cannot do this for
8090 any insn that might fault. We could prevent this for mems with a
8091 (clobber:BLK (scratch)), but this doesn't work for fp insns. So we
8092 have to prevent all such scheduling with a blockage.
89cfc2c6 8093
f676971a 8094 Linux, on the other hand, never bothered to implement OSF/1's
9c0e94a5
RH
8095 exception handling, and so doesn't care about such things. Anyone
8096 planning to use dwarf2 frame-unwind info can also omit the blockage. */
89cfc2c6 8097
9c0e94a5
RH
8098 if (! TARGET_CAN_FAULT_IN_PROLOGUE)
8099 emit_insn (gen_blockage ());
ef86d2ee
WL
8100}
8101
3e487b21 8102/* Count the number of .file directives, so that .loc is up to date. */
93a27b7b 8103int num_source_filenames = 0;
3e487b21 8104
acd92049 8105/* Output the textual info surrounding the prologue. */
89cfc2c6 8106
9c0e94a5 8107void
a5c24926
RH
8108alpha_start_function (FILE *file, const char *fnname,
8109 tree decl ATTRIBUTE_UNUSED)
9ecc37f0 8110{
9c0e94a5
RH
8111 unsigned long imask = 0;
8112 unsigned long fmask = 0;
8113 /* Stack space needed for pushing registers clobbered by us. */
8114 HOST_WIDE_INT sa_size;
8115 /* Complete stack size needed. */
3ee10665 8116 unsigned HOST_WIDE_INT frame_size;
b598cb38
RS
8117 /* The maximum debuggable frame size (512 Kbytes using Tru64 as). */
8118 unsigned HOST_WIDE_INT max_frame_size = TARGET_ABI_OSF && !TARGET_GAS
8119 ? 524288
8120 : 1UL << 31;
9c0e94a5
RH
8121 /* Offset from base reg to register save area. */
8122 HOST_WIDE_INT reg_offset;
acd92049 8123 char *entry_label = (char *) alloca (strlen (fnname) + 6);
fe2786f5 8124 char *tramp_label = (char *) alloca (strlen (fnname) + 6);
9c0e94a5 8125 int i;
9ecc37f0 8126
30102605
RH
8127 /* Don't emit an extern directive for functions defined in the same file. */
8128 if (TARGET_ABI_UNICOSMK)
8129 {
8130 tree name_tree;
8131 name_tree = get_identifier (fnname);
8132 TREE_ASM_WRITTEN (name_tree) = 1;
8133 }
8134
5ea8f977
DR
8135#if TARGET_ABI_OPEN_VMS
8136 if (vms_debug_main
8137 && strncmp (vms_debug_main, fnname, strlen (vms_debug_main)) == 0)
8138 {
8139 targetm.asm_out.globalize_label (asm_out_file, VMS_DEBUG_MAIN_POINTER);
8140 ASM_OUTPUT_DEF (asm_out_file, VMS_DEBUG_MAIN_POINTER, fnname);
8141 switch_to_section (text_section);
8142 vms_debug_main = NULL;
8143 }
8144#endif
8145
941cc05a 8146 alpha_fnname = fnname;
9c0e94a5 8147 sa_size = alpha_sa_size ();
d3c12306 8148 frame_size = compute_frame_size (get_frame_size (), sa_size);
9ecc37f0 8149
be7b80f4 8150 if (TARGET_ABI_OPEN_VMS)
221cf9ab 8151 reg_offset = 8 + 8 * cfun->machine->uses_condition_handler;
9c0e94a5 8152 else
38173d38 8153 reg_offset = ALPHA_ROUND (crtl->outgoing_args_size);
9ecc37f0 8154
9c0e94a5 8155 alpha_sa_mask (&imask, &fmask);
a6f12d7c 8156
d60a05a1 8157 /* Ecoff can handle multiple .file directives, so put out file and lineno.
48f6bfac
RK
8158 We have to do that before the .ent directive as we cannot switch
8159 files within procedures with native ecoff because line numbers are
8160 linked to procedure descriptors.
8161 Outputting the lineno helps debugging of one line functions as they
8162 would otherwise get no line number at all. Please note that we would
ddd5a7c1 8163 like to put out last_linenum from final.c, but it is not accessible. */
48f6bfac
RK
8164
8165 if (write_symbols == SDB_DEBUG)
8166 {
30102605 8167#ifdef ASM_OUTPUT_SOURCE_FILENAME
f31686a3
RH
8168 ASM_OUTPUT_SOURCE_FILENAME (file,
8169 DECL_SOURCE_FILE (current_function_decl));
30102605 8170#endif
3e487b21 8171#ifdef SDB_OUTPUT_SOURCE_LINE
48f6bfac 8172 if (debug_info_level != DINFO_LEVEL_TERSE)
3e487b21
ZW
8173 SDB_OUTPUT_SOURCE_LINE (file,
8174 DECL_SOURCE_LINE (current_function_decl));
30102605 8175#endif
48f6bfac
RK
8176 }
8177
9c0e94a5 8178 /* Issue function start and label. */
30102605
RH
8179 if (TARGET_ABI_OPEN_VMS
8180 || (!TARGET_ABI_UNICOSMK && !flag_inhibit_size_directive))
33d01c33 8181 {
9c0e94a5 8182 fputs ("\t.ent ", file);
acd92049 8183 assemble_name (file, fnname);
9c0e94a5 8184 putc ('\n', file);
941cc05a
RK
8185
8186 /* If the function needs GP, we'll write the "..ng" label there.
8187 Otherwise, do it here. */
14691f8d
RH
8188 if (TARGET_ABI_OSF
8189 && ! alpha_function_needs_gp
3c072c6b 8190 && ! cfun->is_thunk)
941cc05a
RK
8191 {
8192 putc ('$', file);
8193 assemble_name (file, fnname);
8194 fputs ("..ng:\n", file);
8195 }
33d01c33 8196 }
fe2786f5
DR
8197 /* Nested functions on VMS that are potentially called via trampoline
8198 get a special transfer entry point that loads the called functions
8199 procedure descriptor and static chain. */
8200 if (TARGET_ABI_OPEN_VMS
8201 && !TREE_PUBLIC (decl)
8202 && DECL_CONTEXT (decl)
8203 && !TYPE_P (DECL_CONTEXT (decl)))
8204 {
8205 strcpy (tramp_label, fnname);
8206 strcat (tramp_label, "..tr");
8207 ASM_OUTPUT_LABEL (file, tramp_label);
8208 fprintf (file, "\tldq $1,24($27)\n");
8209 fprintf (file, "\tldq $27,16($27)\n");
8210 }
48f6bfac 8211
acd92049 8212 strcpy (entry_label, fnname);
be7b80f4 8213 if (TARGET_ABI_OPEN_VMS)
9c0e94a5 8214 strcat (entry_label, "..en");
30102605
RH
8215
8216 /* For public functions, the label must be globalized by appending an
8217 additional colon. */
8218 if (TARGET_ABI_UNICOSMK && TREE_PUBLIC (decl))
8219 strcat (entry_label, ":");
8220
9c0e94a5
RH
8221 ASM_OUTPUT_LABEL (file, entry_label);
8222 inside_function = TRUE;
48f6bfac 8223
be7b80f4 8224 if (TARGET_ABI_OPEN_VMS)
9c0e94a5 8225 fprintf (file, "\t.base $%d\n", vms_base_regno);
a6f12d7c 8226
30102605 8227 if (!TARGET_ABI_OPEN_VMS && !TARGET_ABI_UNICOSMK && TARGET_IEEE_CONFORMANT
9c0e94a5 8228 && !flag_inhibit_size_directive)
9973f4a2 8229 {
9c0e94a5
RH
8230 /* Set flags in procedure descriptor to request IEEE-conformant
8231 math-library routines. The value we set it to is PDSC_EXC_IEEE
285a5742 8232 (/usr/include/pdsc.h). */
9c0e94a5 8233 fputs ("\t.eflag 48\n", file);
9973f4a2 8234 }
a6f12d7c 8235
9c0e94a5 8236 /* Set up offsets to alpha virtual arg/local debugging pointer. */
38173d38 8237 alpha_auto_offset = -frame_size + crtl->args.pretend_args_size;
9c0e94a5 8238 alpha_arg_offset = -frame_size + 48;
c97e3db7 8239
9c0e94a5
RH
8240 /* Describe our frame. If the frame size is larger than an integer,
8241 print it as zero to avoid an assembler error. We won't be
8242 properly describing such a frame, but that's the best we can do. */
30102605
RH
8243 if (TARGET_ABI_UNICOSMK)
8244 ;
8245 else if (TARGET_ABI_OPEN_VMS)
4a0a75dd
KG
8246 fprintf (file, "\t.frame $%d," HOST_WIDE_INT_PRINT_DEC ",$26,"
8247 HOST_WIDE_INT_PRINT_DEC "\n",
8248 vms_unwind_regno,
8249 frame_size >= (1UL << 31) ? 0 : frame_size,
8250 reg_offset);
9c0e94a5 8251 else if (!flag_inhibit_size_directive)
4a0a75dd
KG
8252 fprintf (file, "\t.frame $%d," HOST_WIDE_INT_PRINT_DEC ",$26,%d\n",
8253 (frame_pointer_needed
8254 ? HARD_FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM),
b598cb38 8255 frame_size >= max_frame_size ? 0 : frame_size,
38173d38 8256 crtl->args.pretend_args_size);
0d24ff5d 8257
9c0e94a5 8258 /* Describe which registers were spilled. */
30102605
RH
8259 if (TARGET_ABI_UNICOSMK)
8260 ;
8261 else if (TARGET_ABI_OPEN_VMS)
0d24ff5d 8262 {
9c0e94a5 8263 if (imask)
30102605 8264 /* ??? Does VMS care if mask contains ra? The old code didn't
9c0e94a5 8265 set it, so I don't here. */
409f52d3 8266 fprintf (file, "\t.mask 0x%lx,0\n", imask & ~(1UL << REG_RA));
9c0e94a5 8267 if (fmask)
3c303f52 8268 fprintf (file, "\t.fmask 0x%lx,0\n", fmask);
c2ea1ac6 8269 if (alpha_procedure_type == PT_REGISTER)
9c0e94a5
RH
8270 fprintf (file, "\t.fp_save $%d\n", vms_save_fp_regno);
8271 }
8272 else if (!flag_inhibit_size_directive)
8273 {
8274 if (imask)
0d24ff5d 8275 {
4a0a75dd 8276 fprintf (file, "\t.mask 0x%lx," HOST_WIDE_INT_PRINT_DEC "\n", imask,
b598cb38 8277 frame_size >= max_frame_size ? 0 : reg_offset - frame_size);
9c0e94a5
RH
8278
8279 for (i = 0; i < 32; ++i)
409f52d3 8280 if (imask & (1UL << i))
9c0e94a5 8281 reg_offset += 8;
0d24ff5d 8282 }
9c0e94a5
RH
8283
8284 if (fmask)
4a0a75dd 8285 fprintf (file, "\t.fmask 0x%lx," HOST_WIDE_INT_PRINT_DEC "\n", fmask,
b598cb38 8286 frame_size >= max_frame_size ? 0 : reg_offset - frame_size);
a6f12d7c
RK
8287 }
8288
be7b80f4 8289#if TARGET_ABI_OPEN_VMS
221cf9ab
OH
8290 /* If a user condition handler has been installed at some point, emit
8291 the procedure descriptor bits to point the Condition Handling Facility
8292 at the indirection wrapper, and state the fp offset at which the user
8293 handler may be found. */
8294 if (cfun->machine->uses_condition_handler)
8295 {
8296 fprintf (file, "\t.handler __gcc_shell_handler\n");
8297 fprintf (file, "\t.handler_data %d\n", VMS_COND_HANDLER_FP_OFFSET);
8298 }
8299
d48bc59a 8300 /* Ifdef'ed cause link_section are only available then. */
d6b5193b 8301 switch_to_section (readonly_data_section);
9c0e94a5 8302 fprintf (file, "\t.align 3\n");
acd92049 8303 assemble_name (file, fnname); fputs ("..na:\n", file);
9c0e94a5 8304 fputs ("\t.ascii \"", file);
acd92049 8305 assemble_name (file, fnname);
9c0e94a5 8306 fputs ("\\0\"\n", file);
acd92049 8307 alpha_need_linkage (fnname, 1);
d6b5193b 8308 switch_to_section (text_section);
9c0e94a5
RH
8309#endif
8310}
a6f12d7c 8311
9c0e94a5 8312/* Emit the .prologue note at the scheduled end of the prologue. */
0f33506c 8313
b4c25db2 8314static void
a5c24926 8315alpha_output_function_end_prologue (FILE *file)
9c0e94a5 8316{
30102605
RH
8317 if (TARGET_ABI_UNICOSMK)
8318 ;
8319 else if (TARGET_ABI_OPEN_VMS)
9c0e94a5 8320 fputs ("\t.prologue\n", file);
be7b80f4 8321 else if (TARGET_ABI_WINDOWS_NT)
9c0e94a5
RH
8322 fputs ("\t.prologue 0\n", file);
8323 else if (!flag_inhibit_size_directive)
14691f8d 8324 fprintf (file, "\t.prologue %d\n",
3c072c6b 8325 alpha_function_needs_gp || cfun->is_thunk);
a6f12d7c
RK
8326}
8327
8328/* Write function epilogue. */
8329
8330void
a5c24926 8331alpha_expand_epilogue (void)
a6f12d7c 8332{
9c0e94a5
RH
8333 /* Registers to save. */
8334 unsigned long imask = 0;
8335 unsigned long fmask = 0;
8336 /* Stack space needed for pushing registers clobbered by us. */
8337 HOST_WIDE_INT sa_size;
8338 /* Complete stack size needed. */
8339 HOST_WIDE_INT frame_size;
8340 /* Offset from base reg to register save area. */
8341 HOST_WIDE_INT reg_offset;
8342 int fp_is_frame_pointer, fp_offset;
8343 rtx sa_reg, sa_reg_exp = NULL;
15cb981a 8344 rtx sp_adj1, sp_adj2, mem, reg, insn;
01439aee 8345 rtx eh_ofs;
15cb981a 8346 rtx cfa_restores = NULL_RTX;
a6f12d7c
RK
8347 int i;
8348
9c0e94a5 8349 sa_size = alpha_sa_size ();
d3c12306 8350 frame_size = compute_frame_size (get_frame_size (), sa_size);
a6f12d7c 8351
be7b80f4 8352 if (TARGET_ABI_OPEN_VMS)
c2ea1ac6
DR
8353 {
8354 if (alpha_procedure_type == PT_STACK)
221cf9ab 8355 reg_offset = 8 + 8 * cfun->machine->uses_condition_handler;
c2ea1ac6
DR
8356 else
8357 reg_offset = 0;
8358 }
9c0e94a5 8359 else
38173d38 8360 reg_offset = ALPHA_ROUND (crtl->outgoing_args_size);
9c0e94a5
RH
8361
8362 alpha_sa_mask (&imask, &fmask);
8363
c2ea1ac6
DR
8364 fp_is_frame_pointer
8365 = ((TARGET_ABI_OPEN_VMS && alpha_procedure_type == PT_STACK)
8366 || (!TARGET_ABI_OPEN_VMS && frame_pointer_needed));
c8d8ed65
RK
8367 fp_offset = 0;
8368 sa_reg = stack_pointer_rtx;
9c0e94a5 8369
e3b5732b 8370 if (crtl->calls_eh_return)
4573b4de
RH
8371 eh_ofs = EH_RETURN_STACKADJ_RTX;
8372 else
8373 eh_ofs = NULL_RTX;
8374
30102605 8375 if (!TARGET_ABI_UNICOSMK && sa_size)
9c0e94a5
RH
8376 {
8377 /* If we have a frame pointer, restore SP from it. */
be7b80f4 8378 if ((TARGET_ABI_OPEN_VMS
9c0e94a5 8379 && vms_unwind_regno == HARD_FRAME_POINTER_REGNUM)
be7b80f4 8380 || (!TARGET_ABI_OPEN_VMS && frame_pointer_needed))
15cb981a 8381 emit_move_insn (stack_pointer_rtx, hard_frame_pointer_rtx);
0d24ff5d 8382
9c0e94a5 8383 /* Cope with very large offsets to the register save area. */
9c0e94a5 8384 if (reg_offset + sa_size > 0x8000)
a6f12d7c 8385 {
9c0e94a5
RH
8386 int low = ((reg_offset & 0xffff) ^ 0x8000) - 0x8000;
8387 HOST_WIDE_INT bias;
8388
8389 if (low + sa_size <= 0x8000)
8390 bias = reg_offset - low, reg_offset = low;
f676971a 8391 else
9c0e94a5
RH
8392 bias = reg_offset, reg_offset = 0;
8393
8394 sa_reg = gen_rtx_REG (DImode, 22);
8395 sa_reg_exp = plus_constant (stack_pointer_rtx, bias);
8396
15cb981a 8397 emit_move_insn (sa_reg, sa_reg_exp);
a6f12d7c 8398 }
f676971a 8399
285a5742 8400 /* Restore registers in order, excepting a true frame pointer. */
a6f12d7c 8401
4573b4de 8402 mem = gen_rtx_MEM (DImode, plus_constant (sa_reg, reg_offset));
01439aee 8403 if (! eh_ofs)
ba4828e0 8404 set_mem_alias_set (mem, alpha_sr_alias_set);
15cb981a
RH
8405 reg = gen_rtx_REG (DImode, REG_RA);
8406 emit_move_insn (reg, mem);
8407 cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg, cfa_restores);
4573b4de 8408
9c0e94a5 8409 reg_offset += 8;
409f52d3 8410 imask &= ~(1UL << REG_RA);
0f33506c 8411
ed80cd68 8412 for (i = 0; i < 31; ++i)
409f52d3 8413 if (imask & (1UL << i))
a6f12d7c 8414 {
9c0e94a5 8415 if (i == HARD_FRAME_POINTER_REGNUM && fp_is_frame_pointer)
0f33506c
RK
8416 fp_offset = reg_offset;
8417 else
9c0e94a5 8418 {
3873d24b 8419 mem = gen_rtx_MEM (DImode, plus_constant(sa_reg, reg_offset));
ba4828e0 8420 set_mem_alias_set (mem, alpha_sr_alias_set);
15cb981a
RH
8421 reg = gen_rtx_REG (DImode, i);
8422 emit_move_insn (reg, mem);
8423 cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg,
8424 cfa_restores);
9c0e94a5 8425 }
a6f12d7c
RK
8426 reg_offset += 8;
8427 }
8428
ed80cd68 8429 for (i = 0; i < 31; ++i)
409f52d3 8430 if (fmask & (1UL << i))
a6f12d7c 8431 {
3873d24b 8432 mem = gen_rtx_MEM (DFmode, plus_constant(sa_reg, reg_offset));
ba4828e0 8433 set_mem_alias_set (mem, alpha_sr_alias_set);
15cb981a
RH
8434 reg = gen_rtx_REG (DFmode, i+32);
8435 emit_move_insn (reg, mem);
8436 cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg, cfa_restores);
a6f12d7c
RK
8437 reg_offset += 8;
8438 }
9c0e94a5 8439 }
c2ea1ac6 8440 else if (TARGET_ABI_UNICOSMK && alpha_procedure_type == PT_STACK)
30102605
RH
8441 {
8442 /* Restore callee-saved general-purpose registers. */
8443
8444 reg_offset = -56;
8445
8446 for (i = 9; i < 15; i++)
409f52d3 8447 if (imask & (1UL << i))
30102605
RH
8448 {
8449 mem = gen_rtx_MEM (DImode, plus_constant(hard_frame_pointer_rtx,
8450 reg_offset));
8451 set_mem_alias_set (mem, alpha_sr_alias_set);
15cb981a
RH
8452 reg = gen_rtx_REG (DImode, i);
8453 emit_move_insn (reg, mem);
8454 cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg, cfa_restores);
30102605
RH
8455 reg_offset -= 8;
8456 }
8457
8458 for (i = 2; i < 10; i++)
409f52d3 8459 if (fmask & (1UL << i))
30102605
RH
8460 {
8461 mem = gen_rtx_MEM (DFmode, plus_constant(hard_frame_pointer_rtx,
8462 reg_offset));
8463 set_mem_alias_set (mem, alpha_sr_alias_set);
15cb981a
RH
8464 reg = gen_rtx_REG (DFmode, i+32);
8465 emit_move_insn (reg, mem);
8466 cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg, cfa_restores);
30102605
RH
8467 reg_offset -= 8;
8468 }
8469
8470 /* Restore the return address from the DSIB. */
15cb981a 8471 mem = gen_rtx_MEM (DImode, plus_constant (hard_frame_pointer_rtx, -8));
30102605 8472 set_mem_alias_set (mem, alpha_sr_alias_set);
15cb981a
RH
8473 reg = gen_rtx_REG (DImode, REG_RA);
8474 emit_move_insn (reg, mem);
8475 cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg, cfa_restores);
30102605 8476 }
a6f12d7c 8477
01439aee 8478 if (frame_size || eh_ofs)
9c0e94a5 8479 {
71038426
RH
8480 sp_adj1 = stack_pointer_rtx;
8481
01439aee 8482 if (eh_ofs)
71038426
RH
8483 {
8484 sp_adj1 = gen_rtx_REG (DImode, 23);
8485 emit_move_insn (sp_adj1,
01439aee 8486 gen_rtx_PLUS (Pmode, stack_pointer_rtx, eh_ofs));
71038426
RH
8487 }
8488
9c0e94a5
RH
8489 /* If the stack size is large, begin computation into a temporary
8490 register so as not to interfere with a potential fp restore,
8491 which must be consecutive with an SP restore. */
30102605 8492 if (frame_size < 32768
e3b5732b 8493 && ! (TARGET_ABI_UNICOSMK && cfun->calls_alloca))
71038426 8494 sp_adj2 = GEN_INT (frame_size);
30102605
RH
8495 else if (TARGET_ABI_UNICOSMK)
8496 {
8497 sp_adj1 = gen_rtx_REG (DImode, 23);
15cb981a 8498 emit_move_insn (sp_adj1, hard_frame_pointer_rtx);
30102605
RH
8499 sp_adj2 = const0_rtx;
8500 }
9c0e94a5
RH
8501 else if (frame_size < 0x40007fffL)
8502 {
8503 int low = ((frame_size & 0xffff) ^ 0x8000) - 0x8000;
8504
71038426 8505 sp_adj2 = plus_constant (sp_adj1, frame_size - low);
9c0e94a5
RH
8506 if (sa_reg_exp && rtx_equal_p (sa_reg_exp, sp_adj2))
8507 sp_adj1 = sa_reg;
8508 else
8509 {
8510 sp_adj1 = gen_rtx_REG (DImode, 23);
15cb981a 8511 emit_move_insn (sp_adj1, sp_adj2);
9c0e94a5
RH
8512 }
8513 sp_adj2 = GEN_INT (low);
8514 }
d60a05a1 8515 else
9c0e94a5 8516 {
71038426 8517 rtx tmp = gen_rtx_REG (DImode, 23);
15cb981a 8518 sp_adj2 = alpha_emit_set_const (tmp, DImode, frame_size, 3, false);
71038426 8519 if (!sp_adj2)
9c0e94a5
RH
8520 {
8521 /* We can't drop new things to memory this late, afaik,
8522 so build it up by pieces. */
15cb981a
RH
8523 sp_adj2 = alpha_emit_set_long_const (tmp, frame_size,
8524 -(frame_size < 0));
56daab84 8525 gcc_assert (sp_adj2);
9c0e94a5 8526 }
9c0e94a5 8527 }
a6f12d7c 8528
9c0e94a5
RH
8529 /* From now on, things must be in order. So emit blockages. */
8530
8531 /* Restore the frame pointer. */
30102605
RH
8532 if (TARGET_ABI_UNICOSMK)
8533 {
8534 emit_insn (gen_blockage ());
8535 mem = gen_rtx_MEM (DImode,
8536 plus_constant (hard_frame_pointer_rtx, -16));
8537 set_mem_alias_set (mem, alpha_sr_alias_set);
15cb981a
RH
8538 emit_move_insn (hard_frame_pointer_rtx, mem);
8539 cfa_restores = alloc_reg_note (REG_CFA_RESTORE,
8540 hard_frame_pointer_rtx, cfa_restores);
30102605
RH
8541 }
8542 else if (fp_is_frame_pointer)
9c0e94a5
RH
8543 {
8544 emit_insn (gen_blockage ());
8207e7c6 8545 mem = gen_rtx_MEM (DImode, plus_constant (sa_reg, fp_offset));
ba4828e0 8546 set_mem_alias_set (mem, alpha_sr_alias_set);
15cb981a
RH
8547 emit_move_insn (hard_frame_pointer_rtx, mem);
8548 cfa_restores = alloc_reg_note (REG_CFA_RESTORE,
8549 hard_frame_pointer_rtx, cfa_restores);
9c0e94a5 8550 }
be7b80f4 8551 else if (TARGET_ABI_OPEN_VMS)
9c0e94a5
RH
8552 {
8553 emit_insn (gen_blockage ());
15cb981a
RH
8554 emit_move_insn (hard_frame_pointer_rtx,
8555 gen_rtx_REG (DImode, vms_save_fp_regno));
8556 cfa_restores = alloc_reg_note (REG_CFA_RESTORE,
8557 hard_frame_pointer_rtx, cfa_restores);
9c0e94a5
RH
8558 }
8559
8560 /* Restore the stack pointer. */
8561 emit_insn (gen_blockage ());
30102605 8562 if (sp_adj2 == const0_rtx)
15cb981a 8563 insn = emit_move_insn (stack_pointer_rtx, sp_adj1);
30102605 8564 else
15cb981a
RH
8565 insn = emit_move_insn (stack_pointer_rtx,
8566 gen_rtx_PLUS (DImode, sp_adj1, sp_adj2));
8567 REG_NOTES (insn) = cfa_restores;
8568 add_reg_note (insn, REG_CFA_DEF_CFA, stack_pointer_rtx);
8569 RTX_FRAME_RELATED_P (insn) = 1;
9c0e94a5 8570 }
f676971a 8571 else
9c0e94a5 8572 {
15cb981a
RH
8573 gcc_assert (cfa_restores == NULL);
8574
c2ea1ac6 8575 if (TARGET_ABI_OPEN_VMS && alpha_procedure_type == PT_REGISTER)
9c0e94a5
RH
8576 {
8577 emit_insn (gen_blockage ());
15cb981a
RH
8578 insn = emit_move_insn (hard_frame_pointer_rtx,
8579 gen_rtx_REG (DImode, vms_save_fp_regno));
8580 add_reg_note (insn, REG_CFA_RESTORE, hard_frame_pointer_rtx);
8581 RTX_FRAME_RELATED_P (insn) = 1;
9c0e94a5 8582 }
c2ea1ac6 8583 else if (TARGET_ABI_UNICOSMK && alpha_procedure_type != PT_STACK)
30102605
RH
8584 {
8585 /* Decrement the frame pointer if the function does not have a
8586 frame. */
30102605 8587 emit_insn (gen_blockage ());
15cb981a
RH
8588 emit_insn (gen_adddi3 (hard_frame_pointer_rtx,
8589 hard_frame_pointer_rtx, constm1_rtx));
30102605 8590 }
a6f12d7c 8591 }
9c0e94a5 8592}
1330f7d5 8593\f
9c0e94a5
RH
8594/* Output the rest of the textual info surrounding the epilogue. */
8595
8596void
a5c24926 8597alpha_end_function (FILE *file, const char *fnname, tree decl ATTRIBUTE_UNUSED)
9c0e94a5 8598{
e4bec638
RH
8599 rtx insn;
8600
8601 /* We output a nop after noreturn calls at the very end of the function to
8602 ensure that the return address always remains in the caller's code range,
8603 as not doing so might confuse unwinding engines. */
8604 insn = get_last_insn ();
8605 if (!INSN_P (insn))
8606 insn = prev_active_insn (insn);
3eb96d01 8607 if (insn && CALL_P (insn))
e4bec638
RH
8608 output_asm_insn (get_insn_template (CODE_FOR_nop, NULL), NULL);
8609
7053a0e2
BG
8610#if TARGET_ABI_OPEN_VMS
8611 alpha_write_linkage (file, fnname, decl);
8612#endif
8613
a6f12d7c 8614 /* End the function. */
30102605 8615 if (!TARGET_ABI_UNICOSMK && !flag_inhibit_size_directive)
33d01c33 8616 {
9c0e94a5 8617 fputs ("\t.end ", file);
acd92049 8618 assemble_name (file, fnname);
9c0e94a5 8619 putc ('\n', file);
33d01c33 8620 }
48f6bfac 8621 inside_function = FALSE;
9973f4a2 8622
30102605
RH
8623 /* Output jump tables and the static subroutine information block. */
8624 if (TARGET_ABI_UNICOSMK)
8625 {
8626 unicosmk_output_ssib (file, fnname);
8627 unicosmk_output_deferred_case_vectors (file);
8628 }
a6f12d7c 8629}
14691f8d 8630
5e3fef6c
DR
8631#if TARGET_ABI_OPEN_VMS
8632void avms_asm_output_external (FILE *file, tree decl ATTRIBUTE_UNUSED, const char *name)
8633{
8634#ifdef DO_CRTL_NAMES
8635 DO_CRTL_NAMES;
8636#endif
8637}
8638#endif
8639
c590b625
RH
8640#if TARGET_ABI_OSF
8641/* Emit a tail call to FUNCTION after adjusting THIS by DELTA.
14691f8d
RH
8642
8643 In order to avoid the hordes of differences between generated code
8644 with and without TARGET_EXPLICIT_RELOCS, and to avoid duplicating
8645 lots of code loading up large constants, generate rtl and emit it
8646 instead of going straight to text.
8647
8648 Not sure why this idea hasn't been explored before... */
8649
c590b625 8650static void
a5c24926
RH
8651alpha_output_mi_thunk_osf (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
8652 HOST_WIDE_INT delta, HOST_WIDE_INT vcall_offset,
8653 tree function)
14691f8d
RH
8654{
8655 HOST_WIDE_INT hi, lo;
0a2aaacc 8656 rtx this_rtx, insn, funexp;
14691f8d
RH
8657
8658 /* We always require a valid GP. */
8659 emit_insn (gen_prologue_ldgp ());
2e040219 8660 emit_note (NOTE_INSN_PROLOGUE_END);
14691f8d
RH
8661
8662 /* Find the "this" pointer. If the function returns a structure,
8663 the structure return pointer is in $16. */
61f71b34 8664 if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function))
0a2aaacc 8665 this_rtx = gen_rtx_REG (Pmode, 17);
14691f8d 8666 else
0a2aaacc 8667 this_rtx = gen_rtx_REG (Pmode, 16);
14691f8d
RH
8668
8669 /* Add DELTA. When possible we use ldah+lda. Otherwise load the
8670 entire constant for the add. */
8671 lo = ((delta & 0xffff) ^ 0x8000) - 0x8000;
8672 hi = (((delta - lo) & 0xffffffff) ^ 0x80000000) - 0x80000000;
8673 if (hi + lo == delta)
8674 {
8675 if (hi)
0a2aaacc 8676 emit_insn (gen_adddi3 (this_rtx, this_rtx, GEN_INT (hi)));
14691f8d 8677 if (lo)
0a2aaacc 8678 emit_insn (gen_adddi3 (this_rtx, this_rtx, GEN_INT (lo)));
14691f8d
RH
8679 }
8680 else
8681 {
8682 rtx tmp = alpha_emit_set_long_const (gen_rtx_REG (Pmode, 0),
8683 delta, -(delta < 0));
0a2aaacc 8684 emit_insn (gen_adddi3 (this_rtx, this_rtx, tmp));
14691f8d
RH
8685 }
8686
e2358068
RH
8687 /* Add a delta stored in the vtable at VCALL_OFFSET. */
8688 if (vcall_offset)
8689 {
8690 rtx tmp, tmp2;
8691
8692 tmp = gen_rtx_REG (Pmode, 0);
0a2aaacc 8693 emit_move_insn (tmp, gen_rtx_MEM (Pmode, this_rtx));
e2358068
RH
8694
8695 lo = ((vcall_offset & 0xffff) ^ 0x8000) - 0x8000;
8696 hi = (((vcall_offset - lo) & 0xffffffff) ^ 0x80000000) - 0x80000000;
8697 if (hi + lo == vcall_offset)
8698 {
8699 if (hi)
8700 emit_insn (gen_adddi3 (tmp, tmp, GEN_INT (hi)));
8701 }
8702 else
8703 {
8704 tmp2 = alpha_emit_set_long_const (gen_rtx_REG (Pmode, 1),
8705 vcall_offset, -(vcall_offset < 0));
8706 emit_insn (gen_adddi3 (tmp, tmp, tmp2));
8707 lo = 0;
8708 }
8709 if (lo)
8710 tmp2 = gen_rtx_PLUS (Pmode, tmp, GEN_INT (lo));
8711 else
8712 tmp2 = tmp;
8713 emit_move_insn (tmp, gen_rtx_MEM (Pmode, tmp2));
8714
0a2aaacc 8715 emit_insn (gen_adddi3 (this_rtx, this_rtx, tmp));
e2358068
RH
8716 }
8717
14691f8d
RH
8718 /* Generate a tail call to the target function. */
8719 if (! TREE_USED (function))
8720 {
8721 assemble_external (function);
8722 TREE_USED (function) = 1;
8723 }
8724 funexp = XEXP (DECL_RTL (function), 0);
8725 funexp = gen_rtx_MEM (FUNCTION_MODE, funexp);
8726 insn = emit_call_insn (gen_sibcall (funexp, const0_rtx));
8727 SIBLING_CALL_P (insn) = 1;
8728
8729 /* Run just enough of rest_of_compilation to get the insns emitted.
8730 There's not really enough bulk here to make other passes such as
8731 instruction scheduling worth while. Note that use_thunk calls
8732 assemble_start_function and assemble_end_function. */
8733 insn = get_insns ();
e139ab34 8734 insn_locators_alloc ();
14691f8d
RH
8735 shorten_branches (insn);
8736 final_start_function (insn, file, 1);
c9d691e9 8737 final (insn, file, 1);
14691f8d
RH
8738 final_end_function ();
8739}
c590b625 8740#endif /* TARGET_ABI_OSF */
48f6bfac
RK
8741\f
8742/* Debugging support. */
8743
8744#include "gstab.h"
8745
8746/* Count the number of sdb related labels are generated (to find block
8747 start and end boundaries). */
8748
8749int sdb_label_count = 0;
8750
48f6bfac
RK
8751/* Name of the file containing the current function. */
8752
df45c7ea 8753static const char *current_function_file = "";
48f6bfac
RK
8754
8755/* Offsets to alpha virtual arg/local debugging pointers. */
8756
8757long alpha_arg_offset;
8758long alpha_auto_offset;
8759\f
8760/* Emit a new filename to a stream. */
8761
8762void
a5c24926 8763alpha_output_filename (FILE *stream, const char *name)
48f6bfac
RK
8764{
8765 static int first_time = TRUE;
48f6bfac
RK
8766
8767 if (first_time)
8768 {
8769 first_time = FALSE;
8770 ++num_source_filenames;
8771 current_function_file = name;
8772 fprintf (stream, "\t.file\t%d ", num_source_filenames);
8773 output_quoted_string (stream, name);
8774 fprintf (stream, "\n");
8775 if (!TARGET_GAS && write_symbols == DBX_DEBUG)
8776 fprintf (stream, "\t#@stabs\n");
8777 }
8778
6af601b3 8779 else if (write_symbols == DBX_DEBUG)
3e487b21
ZW
8780 /* dbxout.c will emit an appropriate .stabs directive. */
8781 return;
48f6bfac
RK
8782
8783 else if (name != current_function_file
5665caa2 8784 && strcmp (name, current_function_file) != 0)
48f6bfac
RK
8785 {
8786 if (inside_function && ! TARGET_GAS)
8787 fprintf (stream, "\t#.file\t%d ", num_source_filenames);
8788 else
8789 {
8790 ++num_source_filenames;
8791 current_function_file = name;
8792 fprintf (stream, "\t.file\t%d ", num_source_filenames);
8793 }
8794
8795 output_quoted_string (stream, name);
8796 fprintf (stream, "\n");
8797 }
8798}
6245e3df
RK
8799\f
8800/* Structure to show the current status of registers and memory. */
8801
8802struct shadow_summary
8803{
8804 struct {
1d11bf18
RH
8805 unsigned int i : 31; /* Mask of int regs */
8806 unsigned int fp : 31; /* Mask of fp regs */
8807 unsigned int mem : 1; /* mem == imem | fpmem */
6245e3df
RK
8808 } used, defd;
8809};
8810
8811/* Summary the effects of expression X on the machine. Update SUM, a pointer
8812 to the summary structure. SET is nonzero if the insn is setting the
8813 object, otherwise zero. */
8814
8815static void
a5c24926 8816summarize_insn (rtx x, struct shadow_summary *sum, int set)
6245e3df 8817{
6f7d635c 8818 const char *format_ptr;
6245e3df
RK
8819 int i, j;
8820
8821 if (x == 0)
8822 return;
8823
8824 switch (GET_CODE (x))
8825 {
8826 /* ??? Note that this case would be incorrect if the Alpha had a
8827 ZERO_EXTRACT in SET_DEST. */
8828 case SET:
8829 summarize_insn (SET_SRC (x), sum, 0);
8830 summarize_insn (SET_DEST (x), sum, 1);
8831 break;
8832
8833 case CLOBBER:
8834 summarize_insn (XEXP (x, 0), sum, 1);
8835 break;
8836
8837 case USE:
8838 summarize_insn (XEXP (x, 0), sum, 0);
8839 break;
8840
f4e31cf5
RH
8841 case ASM_OPERANDS:
8842 for (i = ASM_OPERANDS_INPUT_LENGTH (x) - 1; i >= 0; i--)
8843 summarize_insn (ASM_OPERANDS_INPUT (x, i), sum, 0);
8844 break;
8845
6245e3df 8846 case PARALLEL:
8fed04e5 8847 for (i = XVECLEN (x, 0) - 1; i >= 0; i--)
6245e3df
RK
8848 summarize_insn (XVECEXP (x, 0, i), sum, 0);
8849 break;
8850
f4e31cf5 8851 case SUBREG:
9c0e94a5
RH
8852 summarize_insn (SUBREG_REG (x), sum, 0);
8853 break;
f4e31cf5 8854
6245e3df
RK
8855 case REG:
8856 {
8857 int regno = REGNO (x);
948068e2 8858 unsigned long mask = ((unsigned long) 1) << (regno % 32);
6245e3df
RK
8859
8860 if (regno == 31 || regno == 63)
8861 break;
8862
8863 if (set)
8864 {
8865 if (regno < 32)
8866 sum->defd.i |= mask;
8867 else
8868 sum->defd.fp |= mask;
8869 }
8870 else
8871 {
8872 if (regno < 32)
8873 sum->used.i |= mask;
8874 else
8875 sum->used.fp |= mask;
8876 }
8877 }
8878 break;
8879
8880 case MEM:
8881 if (set)
8882 sum->defd.mem = 1;
8883 else
8884 sum->used.mem = 1;
8885
8886 /* Find the regs used in memory address computation: */
8887 summarize_insn (XEXP (x, 0), sum, 0);
8888 break;
8889
8ba46994
RK
8890 case CONST_INT: case CONST_DOUBLE:
8891 case SYMBOL_REF: case LABEL_REF: case CONST:
368a1647 8892 case SCRATCH: case ASM_INPUT:
8ba46994
RK
8893 break;
8894
6245e3df
RK
8895 /* Handle common unary and binary ops for efficiency. */
8896 case COMPARE: case PLUS: case MINUS: case MULT: case DIV:
8897 case MOD: case UDIV: case UMOD: case AND: case IOR:
8898 case XOR: case ASHIFT: case ROTATE: case ASHIFTRT: case LSHIFTRT:
8899 case ROTATERT: case SMIN: case SMAX: case UMIN: case UMAX:
8900 case NE: case EQ: case GE: case GT: case LE:
8901 case LT: case GEU: case GTU: case LEU: case LTU:
8902 summarize_insn (XEXP (x, 0), sum, 0);
8903 summarize_insn (XEXP (x, 1), sum, 0);
8904 break;
8905
8906 case NEG: case NOT: case SIGN_EXTEND: case ZERO_EXTEND:
8907 case TRUNCATE: case FLOAT_EXTEND: case FLOAT_TRUNCATE: case FLOAT:
8908 case FIX: case UNSIGNED_FLOAT: case UNSIGNED_FIX: case ABS:
f676971a 8909 case SQRT: case FFS:
6245e3df
RK
8910 summarize_insn (XEXP (x, 0), sum, 0);
8911 break;
8912
8913 default:
8914 format_ptr = GET_RTX_FORMAT (GET_CODE (x));
8fed04e5 8915 for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
bed95fa1 8916 switch (format_ptr[i])
6245e3df
RK
8917 {
8918 case 'e':
8919 summarize_insn (XEXP (x, i), sum, 0);
8920 break;
8921
8922 case 'E':
8fed04e5 8923 for (j = XVECLEN (x, i) - 1; j >= 0; j--)
6245e3df
RK
8924 summarize_insn (XVECEXP (x, i, j), sum, 0);
8925 break;
8926
2b01d264
RH
8927 case 'i':
8928 break;
8929
6245e3df 8930 default:
56daab84 8931 gcc_unreachable ();
6245e3df
RK
8932 }
8933 }
8934}
6245e3df 8935
9c0e94a5
RH
8936/* Ensure a sufficient number of `trapb' insns are in the code when
8937 the user requests code with a trap precision of functions or
8938 instructions.
8939
8940 In naive mode, when the user requests a trap-precision of
8941 "instruction", a trapb is needed after every instruction that may
8942 generate a trap. This ensures that the code is resumption safe but
8943 it is also slow.
8944
8945 When optimizations are turned on, we delay issuing a trapb as long
8946 as possible. In this context, a trap shadow is the sequence of
8947 instructions that starts with a (potentially) trap generating
8948 instruction and extends to the next trapb or call_pal instruction
8949 (but GCC never generates call_pal by itself). We can delay (and
8950 therefore sometimes omit) a trapb subject to the following
8951 conditions:
8952
8953 (a) On entry to the trap shadow, if any Alpha register or memory
8954 location contains a value that is used as an operand value by some
8955 instruction in the trap shadow (live on entry), then no instruction
8956 in the trap shadow may modify the register or memory location.
8957
8958 (b) Within the trap shadow, the computation of the base register
8959 for a memory load or store instruction may not involve using the
8960 result of an instruction that might generate an UNPREDICTABLE
8961 result.
8962
8963 (c) Within the trap shadow, no register may be used more than once
8964 as a destination register. (This is to make life easier for the
8965 trap-handler.)
6245e3df 8966
2ea844d3 8967 (d) The trap shadow may not include any branch instructions. */
6245e3df 8968
2ea844d3 8969static void
a5c24926 8970alpha_handle_trap_shadows (void)
6245e3df 8971{
2ea844d3
RH
8972 struct shadow_summary shadow;
8973 int trap_pending, exception_nesting;
68aed21b 8974 rtx i, n;
6245e3df 8975
2ea844d3
RH
8976 trap_pending = 0;
8977 exception_nesting = 0;
8978 shadow.used.i = 0;
8979 shadow.used.fp = 0;
8980 shadow.used.mem = 0;
8981 shadow.defd = shadow.used;
f676971a 8982
18dbd950 8983 for (i = get_insns (); i ; i = NEXT_INSN (i))
2ea844d3 8984 {
7d83f4f5 8985 if (NOTE_P (i))
2ea844d3 8986 {
a38e7aa5 8987 switch (NOTE_KIND (i))
2ea844d3
RH
8988 {
8989 case NOTE_INSN_EH_REGION_BEG:
8990 exception_nesting++;
8991 if (trap_pending)
8992 goto close_shadow;
8993 break;
8994
8995 case NOTE_INSN_EH_REGION_END:
8996 exception_nesting--;
8997 if (trap_pending)
8998 goto close_shadow;
8999 break;
9000
9001 case NOTE_INSN_EPILOGUE_BEG:
9002 if (trap_pending && alpha_tp >= ALPHA_TP_FUNC)
9003 goto close_shadow;
9004 break;
9005 }
9006 }
9007 else if (trap_pending)
9008 {
9009 if (alpha_tp == ALPHA_TP_FUNC)
9010 {
7d83f4f5 9011 if (JUMP_P (i)
2ea844d3
RH
9012 && GET_CODE (PATTERN (i)) == RETURN)
9013 goto close_shadow;
9014 }
9015 else if (alpha_tp == ALPHA_TP_INSN)
9016 {
9017 if (optimize > 0)
9018 {
9019 struct shadow_summary sum;
9020
9021 sum.used.i = 0;
9022 sum.used.fp = 0;
9023 sum.used.mem = 0;
f4e31cf5 9024 sum.defd = sum.used;
2ea844d3
RH
9025
9026 switch (GET_CODE (i))
9027 {
9028 case INSN:
56daab84 9029 /* Annoyingly, get_attr_trap will die on these. */
bb02e7ea
RH
9030 if (GET_CODE (PATTERN (i)) == USE
9031 || GET_CODE (PATTERN (i)) == CLOBBER)
2ea844d3
RH
9032 break;
9033
9034 summarize_insn (PATTERN (i), &sum, 0);
9035
9036 if ((sum.defd.i & shadow.defd.i)
9037 || (sum.defd.fp & shadow.defd.fp))
9038 {
9039 /* (c) would be violated */
9040 goto close_shadow;
9041 }
9042
9043 /* Combine shadow with summary of current insn: */
9044 shadow.used.i |= sum.used.i;
9045 shadow.used.fp |= sum.used.fp;
9046 shadow.used.mem |= sum.used.mem;
9047 shadow.defd.i |= sum.defd.i;
9048 shadow.defd.fp |= sum.defd.fp;
9049 shadow.defd.mem |= sum.defd.mem;
9050
9051 if ((sum.defd.i & shadow.used.i)
9052 || (sum.defd.fp & shadow.used.fp)
9053 || (sum.defd.mem & shadow.used.mem))
9054 {
9055 /* (a) would be violated (also takes care of (b)) */
56daab84
NS
9056 gcc_assert (get_attr_trap (i) != TRAP_YES
9057 || (!(sum.defd.i & sum.used.i)
9058 && !(sum.defd.fp & sum.used.fp)));
2ea844d3
RH
9059
9060 goto close_shadow;
9061 }
9062 break;
9063
9064 case JUMP_INSN:
9065 case CALL_INSN:
9066 case CODE_LABEL:
9067 goto close_shadow;
9068
9069 default:
56daab84 9070 gcc_unreachable ();
2ea844d3
RH
9071 }
9072 }
9073 else
9074 {
9075 close_shadow:
68aed21b
RH
9076 n = emit_insn_before (gen_trapb (), i);
9077 PUT_MODE (n, TImode);
9078 PUT_MODE (i, TImode);
2ea844d3
RH
9079 trap_pending = 0;
9080 shadow.used.i = 0;
9081 shadow.used.fp = 0;
9082 shadow.used.mem = 0;
9083 shadow.defd = shadow.used;
9084 }
9085 }
9086 }
6245e3df 9087
4f3f5e9f 9088 if ((exception_nesting > 0 || alpha_tp >= ALPHA_TP_FUNC)
7d83f4f5 9089 && NONJUMP_INSN_P (i)
4f3f5e9f
RH
9090 && GET_CODE (PATTERN (i)) != USE
9091 && GET_CODE (PATTERN (i)) != CLOBBER
9092 && get_attr_trap (i) == TRAP_YES)
9093 {
9094 if (optimize && !trap_pending)
9095 summarize_insn (PATTERN (i), &shadow, 0);
9096 trap_pending = 1;
9097 }
6245e3df
RK
9098 }
9099}
68aed21b 9100\f
68aed21b 9101/* Alpha can only issue instruction groups simultaneously if they are
093354e0 9102 suitably aligned. This is very processor-specific. */
4ead2a39
RH
9103/* There are a number of entries in alphaev4_insn_pipe and alphaev5_insn_pipe
9104 that are marked "fake". These instructions do not exist on that target,
9105 but it is possible to see these insns with deranged combinations of
9106 command-line options, such as "-mtune=ev4 -mmax". Instead of aborting,
9107 choose a result at random. */
68aed21b 9108
3873d24b
RH
9109enum alphaev4_pipe {
9110 EV4_STOP = 0,
9111 EV4_IB0 = 1,
9112 EV4_IB1 = 2,
9113 EV4_IBX = 4
9114};
9115
68aed21b
RH
9116enum alphaev5_pipe {
9117 EV5_STOP = 0,
9118 EV5_NONE = 1,
9119 EV5_E01 = 2,
9120 EV5_E0 = 4,
9121 EV5_E1 = 8,
9122 EV5_FAM = 16,
9123 EV5_FA = 32,
9124 EV5_FM = 64
9125};
9126
3873d24b 9127static enum alphaev4_pipe
a5c24926 9128alphaev4_insn_pipe (rtx insn)
3873d24b
RH
9129{
9130 if (recog_memoized (insn) < 0)
9131 return EV4_STOP;
9132 if (get_attr_length (insn) != 4)
9133 return EV4_STOP;
9134
9135 switch (get_attr_type (insn))
9136 {
9137 case TYPE_ILD:
0b196b18 9138 case TYPE_LDSYM:
3873d24b 9139 case TYPE_FLD:
0b196b18 9140 case TYPE_LD_L:
3873d24b
RH
9141 return EV4_IBX;
9142
3873d24b
RH
9143 case TYPE_IADD:
9144 case TYPE_ILOG:
9145 case TYPE_ICMOV:
9146 case TYPE_ICMP:
3873d24b
RH
9147 case TYPE_FST:
9148 case TYPE_SHIFT:
9149 case TYPE_IMUL:
9150 case TYPE_FBR:
4ead2a39 9151 case TYPE_MVI: /* fake */
3873d24b
RH
9152 return EV4_IB0;
9153
0b196b18 9154 case TYPE_IST:
3873d24b
RH
9155 case TYPE_MISC:
9156 case TYPE_IBR:
9157 case TYPE_JSR:
d5909a79 9158 case TYPE_CALLPAL:
3873d24b
RH
9159 case TYPE_FCPYS:
9160 case TYPE_FCMOV:
9161 case TYPE_FADD:
9162 case TYPE_FDIV:
9163 case TYPE_FMUL:
0b196b18
RH
9164 case TYPE_ST_C:
9165 case TYPE_MB:
4ead2a39
RH
9166 case TYPE_FSQRT: /* fake */
9167 case TYPE_FTOI: /* fake */
9168 case TYPE_ITOF: /* fake */
3873d24b
RH
9169 return EV4_IB1;
9170
9171 default:
56daab84 9172 gcc_unreachable ();
3873d24b
RH
9173 }
9174}
9175
68aed21b 9176static enum alphaev5_pipe
a5c24926 9177alphaev5_insn_pipe (rtx insn)
68aed21b
RH
9178{
9179 if (recog_memoized (insn) < 0)
9180 return EV5_STOP;
9181 if (get_attr_length (insn) != 4)
9182 return EV5_STOP;
9183
9184 switch (get_attr_type (insn))
9185 {
9186 case TYPE_ILD:
9187 case TYPE_FLD:
9188 case TYPE_LDSYM:
9189 case TYPE_IADD:
9190 case TYPE_ILOG:
9191 case TYPE_ICMOV:
9192 case TYPE_ICMP:
9193 return EV5_E01;
9194
9195 case TYPE_IST:
9196 case TYPE_FST:
9197 case TYPE_SHIFT:
9198 case TYPE_IMUL:
9199 case TYPE_MISC:
9200 case TYPE_MVI:
0b196b18
RH
9201 case TYPE_LD_L:
9202 case TYPE_ST_C:
9203 case TYPE_MB:
4ead2a39
RH
9204 case TYPE_FTOI: /* fake */
9205 case TYPE_ITOF: /* fake */
68aed21b
RH
9206 return EV5_E0;
9207
9208 case TYPE_IBR:
9209 case TYPE_JSR:
d5909a79 9210 case TYPE_CALLPAL:
68aed21b
RH
9211 return EV5_E1;
9212
9213 case TYPE_FCPYS:
9214 return EV5_FAM;
9215
9216 case TYPE_FBR:
9217 case TYPE_FCMOV:
9218 case TYPE_FADD:
9219 case TYPE_FDIV:
4ead2a39 9220 case TYPE_FSQRT: /* fake */
68aed21b
RH
9221 return EV5_FA;
9222
9223 case TYPE_FMUL:
9224 return EV5_FM;
2c01018f
RH
9225
9226 default:
56daab84 9227 gcc_unreachable ();
68aed21b 9228 }
68aed21b
RH
9229}
9230
f676971a 9231/* IN_USE is a mask of the slots currently filled within the insn group.
3873d24b 9232 The mask bits come from alphaev4_pipe above. If EV4_IBX is set, then
f676971a 9233 the insn in EV4_IB0 can be swapped by the hardware into EV4_IB1.
3873d24b
RH
9234
9235 LEN is, of course, the length of the group in bytes. */
9236
9237static rtx
a5c24926 9238alphaev4_next_group (rtx insn, int *pin_use, int *plen)
3873d24b
RH
9239{
9240 int len, in_use;
9241
9242 len = in_use = 0;
9243
2c3c49de 9244 if (! INSN_P (insn)
3873d24b
RH
9245 || GET_CODE (PATTERN (insn)) == CLOBBER
9246 || GET_CODE (PATTERN (insn)) == USE)
9247 goto next_and_done;
9248
9249 while (1)
9250 {
9251 enum alphaev4_pipe pipe;
9252
9253 pipe = alphaev4_insn_pipe (insn);
9254 switch (pipe)
9255 {
9256 case EV4_STOP:
9257 /* Force complex instructions to start new groups. */
9258 if (in_use)
9259 goto done;
9260
f3b569ca 9261 /* If this is a completely unrecognized insn, it's an asm.
3873d24b
RH
9262 We don't know how long it is, so record length as -1 to
9263 signal a needed realignment. */
9264 if (recog_memoized (insn) < 0)
9265 len = -1;
9266 else
9267 len = get_attr_length (insn);
9268 goto next_and_done;
9269
9270 case EV4_IBX:
9271 if (in_use & EV4_IB0)
9272 {
9273 if (in_use & EV4_IB1)
9274 goto done;
9275 in_use |= EV4_IB1;
9276 }
9277 else
9278 in_use |= EV4_IB0 | EV4_IBX;
9279 break;
9280
9281 case EV4_IB0:
9282 if (in_use & EV4_IB0)
9283 {
9284 if (!(in_use & EV4_IBX) || (in_use & EV4_IB1))
9285 goto done;
9286 in_use |= EV4_IB1;
9287 }
9288 in_use |= EV4_IB0;
9289 break;
9290
9291 case EV4_IB1:
9292 if (in_use & EV4_IB1)
9293 goto done;
9294 in_use |= EV4_IB1;
9295 break;
9296
9297 default:
56daab84 9298 gcc_unreachable ();
3873d24b
RH
9299 }
9300 len += 4;
f676971a 9301
3873d24b 9302 /* Haifa doesn't do well scheduling branches. */
7d83f4f5 9303 if (JUMP_P (insn))
3873d24b
RH
9304 goto next_and_done;
9305
9306 next:
9307 insn = next_nonnote_insn (insn);
9308
2c3c49de 9309 if (!insn || ! INSN_P (insn))
3873d24b
RH
9310 goto done;
9311
9312 /* Let Haifa tell us where it thinks insn group boundaries are. */
9313 if (GET_MODE (insn) == TImode)
9314 goto done;
9315
9316 if (GET_CODE (insn) == CLOBBER || GET_CODE (insn) == USE)
9317 goto next;
9318 }
9319
9320 next_and_done:
9321 insn = next_nonnote_insn (insn);
9322
9323 done:
9324 *plen = len;
9325 *pin_use = in_use;
9326 return insn;
9327}
9328
f676971a 9329/* IN_USE is a mask of the slots currently filled within the insn group.
3873d24b 9330 The mask bits come from alphaev5_pipe above. If EV5_E01 is set, then
f676971a 9331 the insn in EV5_E0 can be swapped by the hardware into EV5_E1.
68aed21b
RH
9332
9333 LEN is, of course, the length of the group in bytes. */
9334
9335static rtx
a5c24926 9336alphaev5_next_group (rtx insn, int *pin_use, int *plen)
68aed21b
RH
9337{
9338 int len, in_use;
9339
9340 len = in_use = 0;
9341
2c3c49de 9342 if (! INSN_P (insn)
2c01018f
RH
9343 || GET_CODE (PATTERN (insn)) == CLOBBER
9344 || GET_CODE (PATTERN (insn)) == USE)
9345 goto next_and_done;
68aed21b 9346
2c01018f 9347 while (1)
68aed21b
RH
9348 {
9349 enum alphaev5_pipe pipe;
68aed21b
RH
9350
9351 pipe = alphaev5_insn_pipe (insn);
9352 switch (pipe)
9353 {
9354 case EV5_STOP:
9355 /* Force complex instructions to start new groups. */
9356 if (in_use)
9357 goto done;
9358
f3b569ca 9359 /* If this is a completely unrecognized insn, it's an asm.
68aed21b
RH
9360 We don't know how long it is, so record length as -1 to
9361 signal a needed realignment. */
9362 if (recog_memoized (insn) < 0)
9363 len = -1;
9364 else
9365 len = get_attr_length (insn);
2c01018f 9366 goto next_and_done;
68aed21b 9367
56daab84
NS
9368 /* ??? Most of the places below, we would like to assert never
9369 happen, as it would indicate an error either in Haifa, or
9370 in the scheduling description. Unfortunately, Haifa never
9371 schedules the last instruction of the BB, so we don't have
9372 an accurate TI bit to go off. */
68aed21b
RH
9373 case EV5_E01:
9374 if (in_use & EV5_E0)
9375 {
9376 if (in_use & EV5_E1)
9377 goto done;
9378 in_use |= EV5_E1;
9379 }
9380 else
9381 in_use |= EV5_E0 | EV5_E01;
9382 break;
9383
9384 case EV5_E0:
9385 if (in_use & EV5_E0)
9386 {
3873d24b 9387 if (!(in_use & EV5_E01) || (in_use & EV5_E1))
68aed21b
RH
9388 goto done;
9389 in_use |= EV5_E1;
9390 }
9391 in_use |= EV5_E0;
9392 break;
9393
9394 case EV5_E1:
9395 if (in_use & EV5_E1)
9396 goto done;
9397 in_use |= EV5_E1;
9398 break;
9399
9400 case EV5_FAM:
9401 if (in_use & EV5_FA)
9402 {
9403 if (in_use & EV5_FM)
9404 goto done;
9405 in_use |= EV5_FM;
9406 }
9407 else
9408 in_use |= EV5_FA | EV5_FAM;
9409 break;
9410
9411 case EV5_FA:
9412 if (in_use & EV5_FA)
9413 goto done;
9414 in_use |= EV5_FA;
9415 break;
9416
9417 case EV5_FM:
9418 if (in_use & EV5_FM)
9419 goto done;
9420 in_use |= EV5_FM;
9421 break;
9422
9423 case EV5_NONE:
9424 break;
9425
9426 default:
56daab84 9427 gcc_unreachable ();
68aed21b
RH
9428 }
9429 len += 4;
f676971a 9430
68aed21b
RH
9431 /* Haifa doesn't do well scheduling branches. */
9432 /* ??? If this is predicted not-taken, slotting continues, except
9433 that no more IBR, FBR, or JSR insns may be slotted. */
7d83f4f5 9434 if (JUMP_P (insn))
2c01018f 9435 goto next_and_done;
68aed21b 9436
2c01018f 9437 next:
68aed21b
RH
9438 insn = next_nonnote_insn (insn);
9439
2c3c49de 9440 if (!insn || ! INSN_P (insn))
68aed21b 9441 goto done;
a874dd18 9442
68aed21b
RH
9443 /* Let Haifa tell us where it thinks insn group boundaries are. */
9444 if (GET_MODE (insn) == TImode)
9445 goto done;
9446
2c01018f
RH
9447 if (GET_CODE (insn) == CLOBBER || GET_CODE (insn) == USE)
9448 goto next;
68aed21b 9449 }
2c01018f
RH
9450
9451 next_and_done:
9452 insn = next_nonnote_insn (insn);
68aed21b
RH
9453
9454 done:
9455 *plen = len;
9456 *pin_use = in_use;
9457 return insn;
68aed21b
RH
9458}
9459
3873d24b 9460static rtx
a5c24926 9461alphaev4_next_nop (int *pin_use)
3873d24b
RH
9462{
9463 int in_use = *pin_use;
9464 rtx nop;
9465
9466 if (!(in_use & EV4_IB0))
9467 {
9468 in_use |= EV4_IB0;
9469 nop = gen_nop ();
9470 }
9471 else if ((in_use & (EV4_IBX|EV4_IB1)) == EV4_IBX)
9472 {
9473 in_use |= EV4_IB1;
9474 nop = gen_nop ();
9475 }
9476 else if (TARGET_FP && !(in_use & EV4_IB1))
9477 {
9478 in_use |= EV4_IB1;
9479 nop = gen_fnop ();
9480 }
9481 else
9482 nop = gen_unop ();
9483
9484 *pin_use = in_use;
9485 return nop;
9486}
9487
9488static rtx
a5c24926 9489alphaev5_next_nop (int *pin_use)
3873d24b
RH
9490{
9491 int in_use = *pin_use;
9492 rtx nop;
9493
9494 if (!(in_use & EV5_E1))
9495 {
9496 in_use |= EV5_E1;
9497 nop = gen_nop ();
9498 }
9499 else if (TARGET_FP && !(in_use & EV5_FA))
9500 {
9501 in_use |= EV5_FA;
9502 nop = gen_fnop ();
9503 }
9504 else if (TARGET_FP && !(in_use & EV5_FM))
9505 {
9506 in_use |= EV5_FM;
9507 nop = gen_fnop ();
9508 }
9509 else
9510 nop = gen_unop ();
9511
9512 *pin_use = in_use;
9513 return nop;
9514}
9515
9516/* The instruction group alignment main loop. */
9517
68aed21b 9518static void
a5c24926
RH
9519alpha_align_insns (unsigned int max_align,
9520 rtx (*next_group) (rtx, int *, int *),
9521 rtx (*next_nop) (int *))
68aed21b
RH
9522{
9523 /* ALIGN is the known alignment for the insn group. */
b81f53a1 9524 unsigned int align;
68aed21b
RH
9525 /* OFS is the offset of the current insn in the insn group. */
9526 int ofs;
0f1341c7 9527 int prev_in_use, in_use, len, ldgp;
68aed21b
RH
9528 rtx i, next;
9529
9530 /* Let shorten branches care for assigning alignments to code labels. */
18dbd950 9531 shorten_branches (get_insns ());
68aed21b 9532
30864e14
RH
9533 if (align_functions < 4)
9534 align = 4;
21cb9e60 9535 else if ((unsigned int) align_functions < max_align)
30864e14
RH
9536 align = align_functions;
9537 else
9538 align = max_align;
80db34d8 9539
68aed21b 9540 ofs = prev_in_use = 0;
18dbd950 9541 i = get_insns ();
7d83f4f5 9542 if (NOTE_P (i))
68aed21b
RH
9543 i = next_nonnote_insn (i);
9544
0f1341c7
RH
9545 ldgp = alpha_function_needs_gp ? 8 : 0;
9546
68aed21b
RH
9547 while (i)
9548 {
b81f53a1 9549 next = (*next_group) (i, &in_use, &len);
68aed21b
RH
9550
9551 /* When we see a label, resync alignment etc. */
7d83f4f5 9552 if (LABEL_P (i))
68aed21b 9553 {
b81f53a1
RK
9554 unsigned int new_align = 1 << label_to_alignment (i);
9555
68aed21b
RH
9556 if (new_align >= align)
9557 {
3873d24b 9558 align = new_align < max_align ? new_align : max_align;
68aed21b
RH
9559 ofs = 0;
9560 }
b81f53a1 9561
68aed21b
RH
9562 else if (ofs & (new_align-1))
9563 ofs = (ofs | (new_align-1)) + 1;
56daab84 9564 gcc_assert (!len);
68aed21b
RH
9565 }
9566
9567 /* Handle complex instructions special. */
9568 else if (in_use == 0)
9569 {
9570 /* Asms will have length < 0. This is a signal that we have
9571 lost alignment knowledge. Assume, however, that the asm
9572 will not mis-align instructions. */
9573 if (len < 0)
9574 {
9575 ofs = 0;
9576 align = 4;
9577 len = 0;
9578 }
9579 }
9580
9581 /* If the known alignment is smaller than the recognized insn group,
9582 realign the output. */
1eb356b9 9583 else if ((int) align < len)
68aed21b 9584 {
b81f53a1 9585 unsigned int new_log_align = len > 8 ? 4 : 3;
11cb1475 9586 rtx prev, where;
68aed21b 9587
11cb1475 9588 where = prev = prev_nonnote_insn (i);
7d83f4f5 9589 if (!where || !LABEL_P (where))
68aed21b
RH
9590 where = i;
9591
11cb1475
RH
9592 /* Can't realign between a call and its gp reload. */
9593 if (! (TARGET_EXPLICIT_RELOCS
7d83f4f5 9594 && prev && CALL_P (prev)))
11cb1475
RH
9595 {
9596 emit_insn_before (gen_realign (GEN_INT (new_log_align)), where);
9597 align = 1 << new_log_align;
9598 ofs = 0;
9599 }
68aed21b
RH
9600 }
9601
0f1341c7
RH
9602 /* We may not insert padding inside the initial ldgp sequence. */
9603 else if (ldgp > 0)
9604 ldgp -= len;
9605
68aed21b
RH
9606 /* If the group won't fit in the same INT16 as the previous,
9607 we need to add padding to keep the group together. Rather
9608 than simply leaving the insn filling to the assembler, we
9609 can make use of the knowledge of what sorts of instructions
9610 were issued in the previous group to make sure that all of
9611 the added nops are really free. */
1eb356b9 9612 else if (ofs + len > (int) align)
68aed21b
RH
9613 {
9614 int nop_count = (align - ofs) / 4;
9615 rtx where;
9616
839a4992 9617 /* Insert nops before labels, branches, and calls to truly merge
11cb1475 9618 the execution of the nops with the previous instruction group. */
68aed21b 9619 where = prev_nonnote_insn (i);
3873d24b 9620 if (where)
68aed21b 9621 {
7d83f4f5 9622 if (LABEL_P (where))
68aed21b 9623 {
3873d24b 9624 rtx where2 = prev_nonnote_insn (where);
7d83f4f5 9625 if (where2 && JUMP_P (where2))
3873d24b 9626 where = where2;
68aed21b 9627 }
7d83f4f5 9628 else if (NONJUMP_INSN_P (where))
3873d24b 9629 where = i;
68aed21b 9630 }
3873d24b
RH
9631 else
9632 where = i;
9633
f676971a 9634 do
3873d24b 9635 emit_insn_before ((*next_nop)(&prev_in_use), where);
68aed21b
RH
9636 while (--nop_count);
9637 ofs = 0;
9638 }
9639
9640 ofs = (ofs + len) & (align - 1);
9641 prev_in_use = in_use;
9642 i = next;
9643 }
9644}
76a4a1bd
UB
9645
9646/* Insert an unop between a noreturn function call and GP load. */
9647
9648static void
9649alpha_pad_noreturn (void)
9650{
9651 rtx insn, next;
9652
9653 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
9654 {
9655 if (!CALL_P (insn)
9656 || !find_reg_note (insn, REG_NORETURN, NULL_RTX))
9657 continue;
9658
9659 next = next_active_insn (insn);
9660
9661 if (next)
9662 {
9663 rtx pat = PATTERN (next);
9664
9665 if (GET_CODE (pat) == SET
9666 && GET_CODE (SET_SRC (pat)) == UNSPEC_VOLATILE
9667 && XINT (SET_SRC (pat), 1) == UNSPECV_LDGP1)
9668 emit_insn_after (gen_unop (), insn);
9669 }
9670 }
9671}
68aed21b 9672\f
f5143c46 9673/* Machine dependent reorg pass. */
2ea844d3 9674
18dbd950 9675static void
a5c24926 9676alpha_reorg (void)
2ea844d3 9677{
76a4a1bd
UB
9678 /* Workaround for a linker error that triggers when an
9679 exception handler immediatelly follows a noreturn function.
9680
9681 The instruction stream from an object file:
9682
9683 54: 00 40 5b 6b jsr ra,(t12),58 <__func+0x58>
9684 58: 00 00 ba 27 ldah gp,0(ra)
9685 5c: 00 00 bd 23 lda gp,0(gp)
9686 60: 00 00 7d a7 ldq t12,0(gp)
9687 64: 00 40 5b 6b jsr ra,(t12),68 <__func+0x68>
9688
9689 was converted in the final link pass to:
9690
9691 fdb24: a0 03 40 d3 bsr ra,fe9a8 <_called_func+0x8>
9692 fdb28: 00 00 fe 2f unop
9693 fdb2c: 00 00 fe 2f unop
9694 fdb30: 30 82 7d a7 ldq t12,-32208(gp)
9695 fdb34: 00 40 5b 6b jsr ra,(t12),fdb38 <__func+0x68>
9696
9697 GP load instructions were wrongly cleared by the linker relaxation
9698 pass. This workaround prevents removal of GP loads by inserting
9699 an unop instruction between a noreturn function call and
9700 exception handler prologue. */
9701
9702 if (current_function_has_exception_handlers ())
9703 alpha_pad_noreturn ();
9704
68aed21b 9705 if (alpha_tp != ALPHA_TP_PROG || flag_exceptions)
18dbd950 9706 alpha_handle_trap_shadows ();
68aed21b 9707
68aed21b
RH
9708 /* Due to the number of extra trapb insns, don't bother fixing up
9709 alignment when trap precision is instruction. Moreover, we can
b81f53a1 9710 only do our job when sched2 is run. */
68aed21b
RH
9711 if (optimize && !optimize_size
9712 && alpha_tp != ALPHA_TP_INSN
9713 && flag_schedule_insns_after_reload)
9714 {
8bea7f7c 9715 if (alpha_tune == PROCESSOR_EV4)
18dbd950 9716 alpha_align_insns (8, alphaev4_next_group, alphaev4_next_nop);
8bea7f7c 9717 else if (alpha_tune == PROCESSOR_EV5)
18dbd950 9718 alpha_align_insns (16, alphaev5_next_group, alphaev5_next_nop);
68aed21b 9719 }
2ea844d3 9720}
2ea844d3 9721\f
1bc7c5b6
ZW
9722#if !TARGET_ABI_UNICOSMK
9723
9724#ifdef HAVE_STAMP_H
9725#include <stamp.h>
9726#endif
9727
9728static void
9729alpha_file_start (void)
9730{
4739b00e
RH
9731#ifdef OBJECT_FORMAT_ELF
9732 /* If emitting dwarf2 debug information, we cannot generate a .file
9733 directive to start the file, as it will conflict with dwarf2out
9734 file numbers. So it's only useful when emitting mdebug output. */
38f8b050 9735 targetm.asm_file_start_file_directive = (write_symbols == DBX_DEBUG);
4739b00e
RH
9736#endif
9737
1bc7c5b6
ZW
9738 default_file_start ();
9739#ifdef MS_STAMP
cc550dce 9740 fprintf (asm_out_file, "\t.verstamp %d %d\n", MS_STAMP, LS_STAMP);
1bc7c5b6
ZW
9741#endif
9742
9743 fputs ("\t.set noreorder\n", asm_out_file);
9744 fputs ("\t.set volatile\n", asm_out_file);
9745 if (!TARGET_ABI_OPEN_VMS)
9746 fputs ("\t.set noat\n", asm_out_file);
9747 if (TARGET_EXPLICIT_RELOCS)
9748 fputs ("\t.set nomacro\n", asm_out_file);
9749 if (TARGET_SUPPORT_ARCH | TARGET_BWX | TARGET_MAX | TARGET_FIX | TARGET_CIX)
8bea7f7c
RH
9750 {
9751 const char *arch;
9752
9753 if (alpha_cpu == PROCESSOR_EV6 || TARGET_FIX || TARGET_CIX)
9754 arch = "ev6";
9755 else if (TARGET_MAX)
9756 arch = "pca56";
9757 else if (TARGET_BWX)
9758 arch = "ev56";
9759 else if (alpha_cpu == PROCESSOR_EV5)
9760 arch = "ev5";
9761 else
9762 arch = "ev4";
9763
9764 fprintf (asm_out_file, "\t.arch %s\n", arch);
9765 }
1bc7c5b6
ZW
9766}
9767#endif
9768
b64a1b53 9769#ifdef OBJECT_FORMAT_ELF
9b580a0b
RH
9770/* Since we don't have a .dynbss section, we should not allow global
9771 relocations in the .rodata section. */
9772
9773static int
9774alpha_elf_reloc_rw_mask (void)
9775{
9776 return flag_pic ? 3 : 2;
9777}
b64a1b53 9778
d6b5193b
RS
9779/* Return a section for X. The only special thing we do here is to
9780 honor small data. */
b64a1b53 9781
d6b5193b 9782static section *
a5c24926
RH
9783alpha_elf_select_rtx_section (enum machine_mode mode, rtx x,
9784 unsigned HOST_WIDE_INT align)
b64a1b53
RH
9785{
9786 if (TARGET_SMALL_DATA && GET_MODE_SIZE (mode) <= g_switch_value)
093354e0 9787 /* ??? Consider using mergeable sdata sections. */
d6b5193b 9788 return sdata_section;
b64a1b53 9789 else
d6b5193b 9790 return default_elf_select_rtx_section (mode, x, align);
b64a1b53
RH
9791}
9792
ae069803
RH
9793static unsigned int
9794alpha_elf_section_type_flags (tree decl, const char *name, int reloc)
9795{
9796 unsigned int flags = 0;
9797
9798 if (strcmp (name, ".sdata") == 0
9799 || strncmp (name, ".sdata.", 7) == 0
9800 || strncmp (name, ".gnu.linkonce.s.", 16) == 0
9801 || strcmp (name, ".sbss") == 0
9802 || strncmp (name, ".sbss.", 6) == 0
9803 || strncmp (name, ".gnu.linkonce.sb.", 17) == 0)
9804 flags = SECTION_SMALL;
9805
9806 flags |= default_section_type_flags (decl, name, reloc);
9807 return flags;
9808}
b64a1b53
RH
9809#endif /* OBJECT_FORMAT_ELF */
9810\f
f030826a
RH
9811/* Structure to collect function names for final output in link section. */
9812/* Note that items marked with GTY can't be ifdef'ed out. */
17211ab5
GK
9813
9814enum links_kind {KIND_UNUSED, KIND_LOCAL, KIND_EXTERN};
f030826a 9815enum reloc_kind {KIND_LINKAGE, KIND_CODEADDR};
17211ab5 9816
d1b38208 9817struct GTY(()) alpha_links
17211ab5 9818{
f030826a 9819 int num;
b714133e 9820 const char *target;
17211ab5 9821 rtx linkage;
f030826a
RH
9822 enum links_kind lkind;
9823 enum reloc_kind rkind;
9824};
9825
d1b38208 9826struct GTY(()) alpha_funcs
f030826a
RH
9827{
9828 int num;
9829 splay_tree GTY ((param1_is (char *), param2_is (struct alpha_links *)))
9830 links;
17211ab5
GK
9831};
9832
9833static GTY ((param1_is (char *), param2_is (struct alpha_links *)))
f030826a
RH
9834 splay_tree alpha_links_tree;
9835static GTY ((param1_is (tree), param2_is (struct alpha_funcs *)))
9836 splay_tree alpha_funcs_tree;
9837
9838static GTY(()) int alpha_funcs_num;
17211ab5 9839
be7b80f4 9840#if TARGET_ABI_OPEN_VMS
89cfc2c6 9841
e9a25f70 9842/* Return the VMS argument type corresponding to MODE. */
89cfc2c6 9843
e9a25f70 9844enum avms_arg_type
a5c24926 9845alpha_arg_type (enum machine_mode mode)
e9a25f70
JL
9846{
9847 switch (mode)
89cfc2c6 9848 {
e9a25f70
JL
9849 case SFmode:
9850 return TARGET_FLOAT_VAX ? FF : FS;
9851 case DFmode:
9852 return TARGET_FLOAT_VAX ? FD : FT;
9853 default:
9854 return I64;
89cfc2c6 9855 }
e9a25f70 9856}
89cfc2c6 9857
e9a25f70
JL
9858/* Return an rtx for an integer representing the VMS Argument Information
9859 register value. */
89cfc2c6 9860
aa388f29 9861rtx
a5c24926 9862alpha_arg_info_reg_val (CUMULATIVE_ARGS cum)
e9a25f70
JL
9863{
9864 unsigned HOST_WIDE_INT regval = cum.num_args;
9865 int i;
89cfc2c6 9866
e9a25f70
JL
9867 for (i = 0; i < 6; i++)
9868 regval |= ((int) cum.atypes[i]) << (i * 3 + 8);
89cfc2c6 9869
e9a25f70
JL
9870 return GEN_INT (regval);
9871}
9872\f
b714133e
EB
9873/* Register the need for a (fake) .linkage entry for calls to function NAME.
9874 IS_LOCAL is 1 if this is for a definition, 0 if this is for a real call.
9875 Return a SYMBOL_REF suited to the call instruction. */
a82c7f05
RH
9876
9877rtx
a5c24926 9878alpha_need_linkage (const char *name, int is_local)
89cfc2c6 9879{
a82c7f05
RH
9880 splay_tree_node node;
9881 struct alpha_links *al;
b714133e
EB
9882 const char *target;
9883 tree id;
89cfc2c6
RK
9884
9885 if (name[0] == '*')
9886 name++;
9887
1330f7d5
DR
9888 if (is_local)
9889 {
f030826a
RH
9890 struct alpha_funcs *cfaf;
9891
9892 if (!alpha_funcs_tree)
df453731
DR
9893 alpha_funcs_tree = splay_tree_new_ggc
9894 (splay_tree_compare_pointers,
9895 ggc_alloc_splay_tree_tree_node_tree_node_splay_tree_s,
9896 ggc_alloc_splay_tree_tree_node_tree_node_splay_tree_node_s);
9897
f676971a 9898
a9429e29 9899 cfaf = ggc_alloc_alpha_funcs ();
1330f7d5
DR
9900
9901 cfaf->links = 0;
9902 cfaf->num = ++alpha_funcs_num;
9903
9904 splay_tree_insert (alpha_funcs_tree,
9905 (splay_tree_key) current_function_decl,
9906 (splay_tree_value) cfaf);
1330f7d5
DR
9907 }
9908
9909 if (alpha_links_tree)
a82c7f05
RH
9910 {
9911 /* Is this name already defined? */
89cfc2c6 9912
1330f7d5 9913 node = splay_tree_lookup (alpha_links_tree, (splay_tree_key) name);
a82c7f05
RH
9914 if (node)
9915 {
9916 al = (struct alpha_links *) node->value;
9917 if (is_local)
9918 {
9919 /* Defined here but external assumed. */
1330f7d5
DR
9920 if (al->lkind == KIND_EXTERN)
9921 al->lkind = KIND_LOCAL;
a82c7f05
RH
9922 }
9923 else
9924 {
9925 /* Used here but unused assumed. */
1330f7d5
DR
9926 if (al->lkind == KIND_UNUSED)
9927 al->lkind = KIND_LOCAL;
a82c7f05
RH
9928 }
9929 return al->linkage;
9930 }
9931 }
9932 else
df453731
DR
9933 alpha_links_tree = splay_tree_new_ggc
9934 ((splay_tree_compare_fn) strcmp,
9935 ggc_alloc_splay_tree_str_alpha_links_splay_tree_s,
9936 ggc_alloc_splay_tree_str_alpha_links_splay_tree_node_s);
89cfc2c6 9937
a9429e29 9938 al = ggc_alloc_alpha_links ();
17211ab5 9939 name = ggc_strdup (name);
89cfc2c6
RK
9940
9941 /* Assume external if no definition. */
1330f7d5 9942 al->lkind = (is_local ? KIND_UNUSED : KIND_EXTERN);
89cfc2c6 9943
b714133e
EB
9944 /* Ensure we have an IDENTIFIER so assemble_name can mark it used
9945 and find the ultimate alias target like assemble_name. */
9946 id = get_identifier (name);
9947 target = NULL;
9948 while (IDENTIFIER_TRANSPARENT_ALIAS (id))
9949 {
9950 id = TREE_CHAIN (id);
9951 target = IDENTIFIER_POINTER (id);
9952 }
9398dc27 9953
b714133e
EB
9954 al->target = target ? target : name;
9955 al->linkage = gen_rtx_SYMBOL_REF (Pmode, name);
a82c7f05 9956
1330f7d5 9957 splay_tree_insert (alpha_links_tree, (splay_tree_key) name,
a82c7f05 9958 (splay_tree_value) al);
89cfc2c6 9959
a82c7f05 9960 return al->linkage;
89cfc2c6
RK
9961}
9962
b714133e
EB
9963/* Return a SYMBOL_REF representing the reference to the .linkage entry
9964 of function FUNC built for calls made from CFUNDECL. LFLAG is 1 if
9965 this is the reference to the linkage pointer value, 0 if this is the
9966 reference to the function entry value. RFLAG is 1 if this a reduced
9967 reference (code address only), 0 if this is a full reference. */
9968
1330f7d5 9969rtx
b714133e 9970alpha_use_linkage (rtx func, tree cfundecl, int lflag, int rflag)
1330f7d5
DR
9971{
9972 splay_tree_node cfunnode;
9973 struct alpha_funcs *cfaf;
9974 struct alpha_links *al;
b714133e 9975 const char *name = XSTR (func, 0);
1330f7d5
DR
9976
9977 cfaf = (struct alpha_funcs *) 0;
9978 al = (struct alpha_links *) 0;
9979
9980 cfunnode = splay_tree_lookup (alpha_funcs_tree, (splay_tree_key) cfundecl);
9981 cfaf = (struct alpha_funcs *) cfunnode->value;
9982
9983 if (cfaf->links)
9984 {
9985 splay_tree_node lnode;
9986
9987 /* Is this name already defined? */
9988
9989 lnode = splay_tree_lookup (cfaf->links, (splay_tree_key) name);
9990 if (lnode)
9991 al = (struct alpha_links *) lnode->value;
9992 }
9993 else
df453731
DR
9994 cfaf->links = splay_tree_new_ggc
9995 ((splay_tree_compare_fn) strcmp,
9996 ggc_alloc_splay_tree_str_alpha_links_splay_tree_s,
9997 ggc_alloc_splay_tree_str_alpha_links_splay_tree_node_s);
1330f7d5
DR
9998
9999 if (!al)
10000 {
10001 size_t name_len;
10002 size_t buflen;
1330f7d5
DR
10003 char *linksym;
10004 splay_tree_node node = 0;
10005 struct alpha_links *anl;
10006
10007 if (name[0] == '*')
10008 name++;
10009
10010 name_len = strlen (name);
b714133e 10011 linksym = (char *) alloca (name_len + 50);
1330f7d5 10012
a9429e29 10013 al = ggc_alloc_alpha_links ();
1330f7d5
DR
10014 al->num = cfaf->num;
10015
10016 node = splay_tree_lookup (alpha_links_tree, (splay_tree_key) name);
10017 if (node)
10018 {
10019 anl = (struct alpha_links *) node->value;
10020 al->lkind = anl->lkind;
b714133e 10021 name = anl->target;
1330f7d5
DR
10022 }
10023
b714133e
EB
10024 sprintf (linksym, "$%d..%s..lk", cfaf->num, name);
10025 buflen = strlen (linksym);
1330f7d5
DR
10026
10027 al->linkage = gen_rtx_SYMBOL_REF
10028 (Pmode, ggc_alloc_string (linksym, buflen + 1));
10029
10030 splay_tree_insert (cfaf->links, (splay_tree_key) name,
10031 (splay_tree_value) al);
10032 }
10033
10034 if (rflag)
10035 al->rkind = KIND_CODEADDR;
10036 else
10037 al->rkind = KIND_LINKAGE;
f676971a 10038
1330f7d5
DR
10039 if (lflag)
10040 return gen_rtx_MEM (Pmode, plus_constant (al->linkage, 8));
10041 else
10042 return al->linkage;
10043}
10044
a82c7f05 10045static int
a5c24926 10046alpha_write_one_linkage (splay_tree_node node, void *data)
a82c7f05 10047{
83182544 10048 const char *const name = (const char *) node->key;
1330f7d5 10049 struct alpha_links *link = (struct alpha_links *) node->value;
a82c7f05
RH
10050 FILE *stream = (FILE *) data;
10051
1330f7d5
DR
10052 fprintf (stream, "$%d..%s..lk:\n", link->num, name);
10053 if (link->rkind == KIND_CODEADDR)
a82c7f05 10054 {
1330f7d5
DR
10055 if (link->lkind == KIND_LOCAL)
10056 {
10057 /* Local and used */
10058 fprintf (stream, "\t.quad %s..en\n", name);
10059 }
10060 else
10061 {
10062 /* External and used, request code address. */
10063 fprintf (stream, "\t.code_address %s\n", name);
10064 }
a82c7f05
RH
10065 }
10066 else
10067 {
1330f7d5
DR
10068 if (link->lkind == KIND_LOCAL)
10069 {
10070 /* Local and used, build linkage pair. */
10071 fprintf (stream, "\t.quad %s..en\n", name);
10072 fprintf (stream, "\t.quad %s\n", name);
10073 }
10074 else
10075 {
10076 /* External and used, request linkage pair. */
10077 fprintf (stream, "\t.linkage %s\n", name);
10078 }
a82c7f05
RH
10079 }
10080
10081 return 0;
10082}
89cfc2c6 10083
1330f7d5 10084static void
a5c24926 10085alpha_write_linkage (FILE *stream, const char *funname, tree fundecl)
89cfc2c6 10086{
1330f7d5
DR
10087 splay_tree_node node;
10088 struct alpha_funcs *func;
10089
d6b5193b 10090 fprintf (stream, "\t.link\n");
1330f7d5 10091 fprintf (stream, "\t.align 3\n");
d6b5193b
RS
10092 in_section = NULL;
10093
1330f7d5
DR
10094 node = splay_tree_lookup (alpha_funcs_tree, (splay_tree_key) fundecl);
10095 func = (struct alpha_funcs *) node->value;
10096
10097 fputs ("\t.name ", stream);
10098 assemble_name (stream, funname);
10099 fputs ("..na\n", stream);
10100 ASM_OUTPUT_LABEL (stream, funname);
10101 fprintf (stream, "\t.pdesc ");
10102 assemble_name (stream, funname);
10103 fprintf (stream, "..en,%s\n",
10104 alpha_procedure_type == PT_STACK ? "stack"
10105 : alpha_procedure_type == PT_REGISTER ? "reg" : "null");
10106
10107 if (func->links)
c1bd46a8 10108 {
1330f7d5
DR
10109 splay_tree_foreach (func->links, alpha_write_one_linkage, stream);
10110 /* splay_tree_delete (func->links); */
c1bd46a8 10111 }
89cfc2c6
RK
10112}
10113
7c262518
RH
10114/* Switch to an arbitrary section NAME with attributes as specified
10115 by FLAGS. ALIGN specifies any known alignment requirements for
10116 the section; 0 if the default should be used. */
10117
10118static void
c18a5b6c
MM
10119vms_asm_named_section (const char *name, unsigned int flags,
10120 tree decl ATTRIBUTE_UNUSED)
7c262518 10121{
c1bd46a8
DR
10122 fputc ('\n', asm_out_file);
10123 fprintf (asm_out_file, ".section\t%s", name);
7c262518 10124
c1bd46a8
DR
10125 if (flags & SECTION_DEBUG)
10126 fprintf (asm_out_file, ",NOWRT");
10127
10128 fputc ('\n', asm_out_file);
7c262518
RH
10129}
10130
2cc07db4
RH
10131/* Record an element in the table of global constructors. SYMBOL is
10132 a SYMBOL_REF of the function to be called; PRIORITY is a number
f676971a 10133 between 0 and MAX_INIT_PRIORITY.
2cc07db4
RH
10134
10135 Differs from default_ctors_section_asm_out_constructor in that the
10136 width of the .ctors entry is always 64 bits, rather than the 32 bits
10137 used by a normal pointer. */
10138
10139static void
a5c24926 10140vms_asm_out_constructor (rtx symbol, int priority ATTRIBUTE_UNUSED)
2cc07db4 10141{
d6b5193b 10142 switch_to_section (ctors_section);
c8af3574
RH
10143 assemble_align (BITS_PER_WORD);
10144 assemble_integer (symbol, UNITS_PER_WORD, BITS_PER_WORD, 1);
2cc07db4
RH
10145}
10146
10147static void
a5c24926 10148vms_asm_out_destructor (rtx symbol, int priority ATTRIBUTE_UNUSED)
2cc07db4 10149{
d6b5193b 10150 switch_to_section (dtors_section);
c8af3574
RH
10151 assemble_align (BITS_PER_WORD);
10152 assemble_integer (symbol, UNITS_PER_WORD, BITS_PER_WORD, 1);
2cc07db4 10153}
89cfc2c6
RK
10154#else
10155
a82c7f05 10156rtx
a5c24926
RH
10157alpha_need_linkage (const char *name ATTRIBUTE_UNUSED,
10158 int is_local ATTRIBUTE_UNUSED)
89cfc2c6 10159{
a82c7f05 10160 return NULL_RTX;
89cfc2c6
RK
10161}
10162
1330f7d5 10163rtx
b714133e 10164alpha_use_linkage (rtx func ATTRIBUTE_UNUSED,
a5c24926
RH
10165 tree cfundecl ATTRIBUTE_UNUSED,
10166 int lflag ATTRIBUTE_UNUSED,
10167 int rflag ATTRIBUTE_UNUSED)
1330f7d5
DR
10168{
10169 return NULL_RTX;
10170}
10171
be7b80f4 10172#endif /* TARGET_ABI_OPEN_VMS */
30102605
RH
10173\f
10174#if TARGET_ABI_UNICOSMK
10175
fe984136
RH
10176/* This evaluates to true if we do not know how to pass TYPE solely in
10177 registers. This is the case for all arguments that do not fit in two
10178 registers. */
10179
10180static bool
586de218 10181unicosmk_must_pass_in_stack (enum machine_mode mode, const_tree type)
fe984136
RH
10182{
10183 if (type == NULL)
10184 return false;
10185
10186 if (TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
10187 return true;
10188 if (TREE_ADDRESSABLE (type))
10189 return true;
10190
10191 return ALPHA_ARG_SIZE (mode, type, 0) > 2;
10192}
10193
30102605
RH
10194/* Define the offset between two registers, one to be eliminated, and the
10195 other its replacement, at the start of a routine. */
10196
10197int
a5c24926 10198unicosmk_initial_elimination_offset (int from, int to)
30102605
RH
10199{
10200 int fixed_size;
f676971a 10201
30102605
RH
10202 fixed_size = alpha_sa_size();
10203 if (fixed_size != 0)
10204 fixed_size += 48;
10205
10206 if (from == FRAME_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM)
f676971a 10207 return -fixed_size;
30102605
RH
10208 else if (from == ARG_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM)
10209 return 0;
10210 else if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
38173d38 10211 return (ALPHA_ROUND (crtl->outgoing_args_size)
30102605
RH
10212 + ALPHA_ROUND (get_frame_size()));
10213 else if (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
10214 return (ALPHA_ROUND (fixed_size)
f676971a 10215 + ALPHA_ROUND (get_frame_size()
38173d38 10216 + crtl->outgoing_args_size));
30102605 10217 else
56daab84 10218 gcc_unreachable ();
30102605
RH
10219}
10220
10221/* Output the module name for .ident and .end directives. We have to strip
10222 directories and add make sure that the module name starts with a letter
10223 or '$'. */
10224
10225static void
a5c24926 10226unicosmk_output_module_name (FILE *file)
30102605 10227{
f5924ac1
NS
10228 const char *name = lbasename (main_input_filename);
10229 unsigned len = strlen (name);
10230 char *clean_name = alloca (len + 2);
10231 char *ptr = clean_name;
f676971a 10232
30102605
RH
10233 /* CAM only accepts module names that start with a letter or '$'. We
10234 prefix the module name with a '$' if necessary. */
10235
10236 if (!ISALPHA (*name))
f5924ac1
NS
10237 *ptr++ = '$';
10238 memcpy (ptr, name, len + 1);
10239 clean_symbol_name (clean_name);
10240 fputs (clean_name, file);
30102605
RH
10241}
10242
a5c24926 10243/* Output the definition of a common variable. */
30102605 10244
a5c24926
RH
10245void
10246unicosmk_output_common (FILE *file, const char *name, int size, int align)
30102605 10247{
a5c24926
RH
10248 tree name_tree;
10249 printf ("T3E__: common %s\n", name);
30102605 10250
d6b5193b 10251 in_section = NULL;
30102605
RH
10252 fputs("\t.endp\n\n\t.psect ", file);
10253 assemble_name(file, name);
10254 fprintf(file, ",%d,common\n", floor_log2 (align / BITS_PER_UNIT));
10255 fprintf(file, "\t.byte\t0:%d\n", size);
10256
10257 /* Mark the symbol as defined in this module. */
10258 name_tree = get_identifier (name);
10259 TREE_ASM_WRITTEN (name_tree) = 1;
10260}
10261
10262#define SECTION_PUBLIC SECTION_MACH_DEP
10263#define SECTION_MAIN (SECTION_PUBLIC << 1)
10264static int current_section_align;
10265
d6b5193b
RS
10266/* A get_unnamed_section callback for switching to the text section. */
10267
10268static void
10269unicosmk_output_text_section_asm_op (const void *data ATTRIBUTE_UNUSED)
10270{
10271 static int count = 0;
10272 fprintf (asm_out_file, "\t.endp\n\n\t.psect\tgcc@text___%d,code\n", count++);
10273}
10274
10275/* A get_unnamed_section callback for switching to the data section. */
10276
10277static void
10278unicosmk_output_data_section_asm_op (const void *data ATTRIBUTE_UNUSED)
10279{
10280 static int count = 1;
10281 fprintf (asm_out_file, "\t.endp\n\n\t.psect\tgcc@data___%d,data\n", count++);
10282}
10283
10284/* Implement TARGET_ASM_INIT_SECTIONS.
10285
10286 The Cray assembler is really weird with respect to sections. It has only
10287 named sections and you can't reopen a section once it has been closed.
10288 This means that we have to generate unique names whenever we want to
10289 reenter the text or the data section. */
10290
10291static void
10292unicosmk_init_sections (void)
10293{
10294 text_section = get_unnamed_section (SECTION_CODE,
10295 unicosmk_output_text_section_asm_op,
10296 NULL);
10297 data_section = get_unnamed_section (SECTION_WRITE,
10298 unicosmk_output_data_section_asm_op,
10299 NULL);
10300 readonly_data_section = data_section;
10301}
10302
30102605 10303static unsigned int
a5c24926
RH
10304unicosmk_section_type_flags (tree decl, const char *name,
10305 int reloc ATTRIBUTE_UNUSED)
30102605
RH
10306{
10307 unsigned int flags = default_section_type_flags (decl, name, reloc);
10308
10309 if (!decl)
10310 return flags;
10311
10312 if (TREE_CODE (decl) == FUNCTION_DECL)
10313 {
10314 current_section_align = floor_log2 (FUNCTION_BOUNDARY / BITS_PER_UNIT);
10315 if (align_functions_log > current_section_align)
10316 current_section_align = align_functions_log;
10317
10318 if (! strcmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)), "main"))
10319 flags |= SECTION_MAIN;
10320 }
10321 else
10322 current_section_align = floor_log2 (DECL_ALIGN (decl) / BITS_PER_UNIT);
10323
10324 if (TREE_PUBLIC (decl))
10325 flags |= SECTION_PUBLIC;
10326
10327 return flags;
10328}
10329
10330/* Generate a section name for decl and associate it with the
10331 declaration. */
10332
ae46c4e0 10333static void
a5c24926 10334unicosmk_unique_section (tree decl, int reloc ATTRIBUTE_UNUSED)
30102605
RH
10335{
10336 const char *name;
10337 int len;
10338
56daab84 10339 gcc_assert (decl);
30102605
RH
10340
10341 name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
d055668e 10342 name = default_strip_name_encoding (name);
30102605
RH
10343 len = strlen (name);
10344
10345 if (TREE_CODE (decl) == FUNCTION_DECL)
10346 {
10347 char *string;
10348
f676971a
EC
10349 /* It is essential that we prefix the section name here because
10350 otherwise the section names generated for constructors and
30102605
RH
10351 destructors confuse collect2. */
10352
10353 string = alloca (len + 6);
10354 sprintf (string, "code@%s", name);
10355 DECL_SECTION_NAME (decl) = build_string (len + 5, string);
10356 }
10357 else if (TREE_PUBLIC (decl))
10358 DECL_SECTION_NAME (decl) = build_string (len, name);
10359 else
10360 {
10361 char *string;
10362
10363 string = alloca (len + 6);
10364 sprintf (string, "data@%s", name);
10365 DECL_SECTION_NAME (decl) = build_string (len + 5, string);
10366 }
10367}
10368
10369/* Switch to an arbitrary section NAME with attributes as specified
10370 by FLAGS. ALIGN specifies any known alignment requirements for
10371 the section; 0 if the default should be used. */
10372
10373static void
c18a5b6c
MM
10374unicosmk_asm_named_section (const char *name, unsigned int flags,
10375 tree decl ATTRIBUTE_UNUSED)
30102605
RH
10376{
10377 const char *kind;
10378
10379 /* Close the previous section. */
10380
10381 fputs ("\t.endp\n\n", asm_out_file);
10382
10383 /* Find out what kind of section we are opening. */
10384
10385 if (flags & SECTION_MAIN)
10386 fputs ("\t.start\tmain\n", asm_out_file);
10387
10388 if (flags & SECTION_CODE)
10389 kind = "code";
10390 else if (flags & SECTION_PUBLIC)
10391 kind = "common";
10392 else
10393 kind = "data";
10394
10395 if (current_section_align != 0)
10396 fprintf (asm_out_file, "\t.psect\t%s,%d,%s\n", name,
10397 current_section_align, kind);
10398 else
10399 fprintf (asm_out_file, "\t.psect\t%s,%s\n", name, kind);
10400}
10401
10402static void
a5c24926 10403unicosmk_insert_attributes (tree decl, tree *attr_ptr ATTRIBUTE_UNUSED)
30102605
RH
10404{
10405 if (DECL_P (decl)
10406 && (TREE_PUBLIC (decl) || TREE_CODE (decl) == FUNCTION_DECL))
ae46c4e0 10407 unicosmk_unique_section (decl, 0);
30102605
RH
10408}
10409
10410/* Output an alignment directive. We have to use the macro 'gcc@code@align'
10411 in code sections because .align fill unused space with zeroes. */
f676971a 10412
30102605 10413void
a5c24926 10414unicosmk_output_align (FILE *file, int align)
30102605
RH
10415{
10416 if (inside_function)
10417 fprintf (file, "\tgcc@code@align\t%d\n", align);
10418 else
10419 fprintf (file, "\t.align\t%d\n", align);
10420}
10421
10422/* Add a case vector to the current function's list of deferred case
10423 vectors. Case vectors have to be put into a separate section because CAM
10424 does not allow data definitions in code sections. */
10425
10426void
a5c24926 10427unicosmk_defer_case_vector (rtx lab, rtx vec)
30102605
RH
10428{
10429 struct machine_function *machine = cfun->machine;
f676971a 10430
30102605
RH
10431 vec = gen_rtx_EXPR_LIST (VOIDmode, lab, vec);
10432 machine->addr_list = gen_rtx_EXPR_LIST (VOIDmode, vec,
f676971a 10433 machine->addr_list);
30102605
RH
10434}
10435
10436/* Output a case vector. */
10437
10438static void
a5c24926 10439unicosmk_output_addr_vec (FILE *file, rtx vec)
30102605
RH
10440{
10441 rtx lab = XEXP (vec, 0);
10442 rtx body = XEXP (vec, 1);
10443 int vlen = XVECLEN (body, 0);
10444 int idx;
10445
4977bab6 10446 (*targetm.asm_out.internal_label) (file, "L", CODE_LABEL_NUMBER (lab));
30102605
RH
10447
10448 for (idx = 0; idx < vlen; idx++)
10449 {
10450 ASM_OUTPUT_ADDR_VEC_ELT
10451 (file, CODE_LABEL_NUMBER (XEXP (XVECEXP (body, 0, idx), 0)));
10452 }
10453}
10454
10455/* Output current function's deferred case vectors. */
10456
10457static void
a5c24926 10458unicosmk_output_deferred_case_vectors (FILE *file)
30102605
RH
10459{
10460 struct machine_function *machine = cfun->machine;
10461 rtx t;
10462
10463 if (machine->addr_list == NULL_RTX)
10464 return;
10465
d6b5193b 10466 switch_to_section (data_section);
30102605
RH
10467 for (t = machine->addr_list; t; t = XEXP (t, 1))
10468 unicosmk_output_addr_vec (file, XEXP (t, 0));
10469}
10470
a5c24926
RH
10471/* Generate the name of the SSIB section for the current function. */
10472
10473#define SSIB_PREFIX "__SSIB_"
10474#define SSIB_PREFIX_LEN 7
10475
10476static const char *
10477unicosmk_ssib_name (void)
10478{
f676971a 10479 /* This is ok since CAM won't be able to deal with names longer than that
a5c24926
RH
10480 anyway. */
10481
10482 static char name[256];
10483
10484 rtx x;
10485 const char *fnname;
10486 int len;
10487
10488 x = DECL_RTL (cfun->decl);
7d83f4f5 10489 gcc_assert (MEM_P (x));
a5c24926 10490 x = XEXP (x, 0);
56daab84 10491 gcc_assert (GET_CODE (x) == SYMBOL_REF);
a5c24926
RH
10492 fnname = XSTR (x, 0);
10493
10494 len = strlen (fnname);
10495 if (len + SSIB_PREFIX_LEN > 255)
10496 len = 255 - SSIB_PREFIX_LEN;
10497
10498 strcpy (name, SSIB_PREFIX);
10499 strncpy (name + SSIB_PREFIX_LEN, fnname, len);
10500 name[len + SSIB_PREFIX_LEN] = 0;
10501
10502 return name;
10503}
10504
f676971a
EC
10505/* Set up the dynamic subprogram information block (DSIB) and update the
10506 frame pointer register ($15) for subroutines which have a frame. If the
30102605
RH
10507 subroutine doesn't have a frame, simply increment $15. */
10508
10509static void
a5c24926 10510unicosmk_gen_dsib (unsigned long *imaskP)
30102605 10511{
c2ea1ac6 10512 if (alpha_procedure_type == PT_STACK)
30102605
RH
10513 {
10514 const char *ssib_name;
10515 rtx mem;
10516
10517 /* Allocate 64 bytes for the DSIB. */
10518
10519 FRP (emit_insn (gen_adddi3 (stack_pointer_rtx, stack_pointer_rtx,
10520 GEN_INT (-64))));
10521 emit_insn (gen_blockage ());
10522
10523 /* Save the return address. */
10524
10525 mem = gen_rtx_MEM (DImode, plus_constant (stack_pointer_rtx, 56));
10526 set_mem_alias_set (mem, alpha_sr_alias_set);
10527 FRP (emit_move_insn (mem, gen_rtx_REG (DImode, REG_RA)));
409f52d3 10528 (*imaskP) &= ~(1UL << REG_RA);
30102605
RH
10529
10530 /* Save the old frame pointer. */
10531
10532 mem = gen_rtx_MEM (DImode, plus_constant (stack_pointer_rtx, 48));
10533 set_mem_alias_set (mem, alpha_sr_alias_set);
10534 FRP (emit_move_insn (mem, hard_frame_pointer_rtx));
409f52d3 10535 (*imaskP) &= ~(1UL << HARD_FRAME_POINTER_REGNUM);
30102605
RH
10536
10537 emit_insn (gen_blockage ());
10538
10539 /* Store the SSIB pointer. */
10540
10541 ssib_name = ggc_strdup (unicosmk_ssib_name ());
10542 mem = gen_rtx_MEM (DImode, plus_constant (stack_pointer_rtx, 32));
10543 set_mem_alias_set (mem, alpha_sr_alias_set);
10544
10545 FRP (emit_move_insn (gen_rtx_REG (DImode, 5),
10546 gen_rtx_SYMBOL_REF (Pmode, ssib_name)));
10547 FRP (emit_move_insn (mem, gen_rtx_REG (DImode, 5)));
10548
10549 /* Save the CIW index. */
10550
10551 mem = gen_rtx_MEM (DImode, plus_constant (stack_pointer_rtx, 24));
10552 set_mem_alias_set (mem, alpha_sr_alias_set);
10553 FRP (emit_move_insn (mem, gen_rtx_REG (DImode, 25)));
10554
10555 emit_insn (gen_blockage ());
10556
10557 /* Set the new frame pointer. */
30102605
RH
10558 FRP (emit_insn (gen_adddi3 (hard_frame_pointer_rtx,
10559 stack_pointer_rtx, GEN_INT (64))));
30102605
RH
10560 }
10561 else
10562 {
10563 /* Increment the frame pointer register to indicate that we do not
10564 have a frame. */
15cb981a
RH
10565 emit_insn (gen_adddi3 (hard_frame_pointer_rtx,
10566 hard_frame_pointer_rtx, const1_rtx));
30102605
RH
10567 }
10568}
10569
30102605
RH
10570/* Output the static subroutine information block for the current
10571 function. */
10572
10573static void
a5c24926 10574unicosmk_output_ssib (FILE *file, const char *fnname)
30102605
RH
10575{
10576 int len;
10577 int i;
10578 rtx x;
10579 rtx ciw;
10580 struct machine_function *machine = cfun->machine;
10581
d6b5193b 10582 in_section = NULL;
30102605
RH
10583 fprintf (file, "\t.endp\n\n\t.psect\t%s%s,data\n", user_label_prefix,
10584 unicosmk_ssib_name ());
10585
10586 /* Some required stuff and the function name length. */
10587
10588 len = strlen (fnname);
10589 fprintf (file, "\t.quad\t^X20008%2.2X28\n", len);
10590
10591 /* Saved registers
10592 ??? We don't do that yet. */
10593
10594 fputs ("\t.quad\t0\n", file);
10595
10596 /* Function address. */
10597
10598 fputs ("\t.quad\t", file);
10599 assemble_name (file, fnname);
10600 putc ('\n', file);
10601
10602 fputs ("\t.quad\t0\n", file);
10603 fputs ("\t.quad\t0\n", file);
10604
10605 /* Function name.
10606 ??? We do it the same way Cray CC does it but this could be
10607 simplified. */
10608
10609 for( i = 0; i < len; i++ )
10610 fprintf (file, "\t.byte\t%d\n", (int)(fnname[i]));
10611 if( (len % 8) == 0 )
10612 fputs ("\t.quad\t0\n", file);
10613 else
10614 fprintf (file, "\t.bits\t%d : 0\n", (8 - (len % 8))*8);
10615
10616 /* All call information words used in the function. */
10617
10618 for (x = machine->first_ciw; x; x = XEXP (x, 1))
10619 {
10620 ciw = XEXP (x, 0);
30102605 10621#if HOST_BITS_PER_WIDE_INT == 32
4a0a75dd 10622 fprintf (file, "\t.quad\t" HOST_WIDE_INT_PRINT_DOUBLE_HEX "\n",
30102605
RH
10623 CONST_DOUBLE_HIGH (ciw), CONST_DOUBLE_LOW (ciw));
10624#else
4a0a75dd 10625 fprintf (file, "\t.quad\t" HOST_WIDE_INT_PRINT_HEX "\n", INTVAL (ciw));
30102605 10626#endif
30102605
RH
10627 }
10628}
10629
10630/* Add a call information word (CIW) to the list of the current function's
10631 CIWs and return its index.
10632
10633 X is a CONST_INT or CONST_DOUBLE representing the CIW. */
10634
10635rtx
a5c24926 10636unicosmk_add_call_info_word (rtx x)
30102605
RH
10637{
10638 rtx node;
10639 struct machine_function *machine = cfun->machine;
10640
10641 node = gen_rtx_EXPR_LIST (VOIDmode, x, NULL_RTX);
10642 if (machine->first_ciw == NULL_RTX)
10643 machine->first_ciw = node;
10644 else
10645 XEXP (machine->last_ciw, 1) = node;
10646
10647 machine->last_ciw = node;
10648 ++machine->ciw_count;
10649
10650 return GEN_INT (machine->ciw_count
faed5cc3 10651 + strlen (current_function_name ())/8 + 5);
30102605
RH
10652}
10653
30102605
RH
10654/* The Cray assembler doesn't accept extern declarations for symbols which
10655 are defined in the same file. We have to keep track of all global
10656 symbols which are referenced and/or defined in a source file and output
10657 extern declarations for those which are referenced but not defined at
10658 the end of file. */
10659
10660/* List of identifiers for which an extern declaration might have to be
10661 emitted. */
f030826a 10662/* FIXME: needs to use GC, so it can be saved and restored for PCH. */
30102605
RH
10663
10664struct unicosmk_extern_list
10665{
10666 struct unicosmk_extern_list *next;
10667 const char *name;
10668};
10669
10670static struct unicosmk_extern_list *unicosmk_extern_head = 0;
10671
10672/* Output extern declarations which are required for every asm file. */
10673
10674static void
a5c24926 10675unicosmk_output_default_externs (FILE *file)
30102605 10676{
83182544 10677 static const char *const externs[] =
30102605
RH
10678 { "__T3E_MISMATCH" };
10679
10680 int i;
10681 int n;
10682
10683 n = ARRAY_SIZE (externs);
10684
10685 for (i = 0; i < n; i++)
10686 fprintf (file, "\t.extern\t%s\n", externs[i]);
10687}
10688
10689/* Output extern declarations for global symbols which are have been
10690 referenced but not defined. */
10691
10692static void
a5c24926 10693unicosmk_output_externs (FILE *file)
30102605
RH
10694{
10695 struct unicosmk_extern_list *p;
10696 const char *real_name;
10697 int len;
10698 tree name_tree;
10699
10700 len = strlen (user_label_prefix);
10701 for (p = unicosmk_extern_head; p != 0; p = p->next)
10702 {
f676971a 10703 /* We have to strip the encoding and possibly remove user_label_prefix
30102605
RH
10704 from the identifier in order to handle -fleading-underscore and
10705 explicit asm names correctly (cf. gcc.dg/asm-names-1.c). */
d055668e 10706 real_name = default_strip_name_encoding (p->name);
30102605
RH
10707 if (len && p->name[0] == '*'
10708 && !memcmp (real_name, user_label_prefix, len))
10709 real_name += len;
f676971a 10710
30102605
RH
10711 name_tree = get_identifier (real_name);
10712 if (! TREE_ASM_WRITTEN (name_tree))
10713 {
10714 TREE_ASM_WRITTEN (name_tree) = 1;
10715 fputs ("\t.extern\t", file);
10716 assemble_name (file, p->name);
10717 putc ('\n', file);
10718 }
10719 }
10720}
f676971a 10721
30102605
RH
10722/* Record an extern. */
10723
10724void
a5c24926 10725unicosmk_add_extern (const char *name)
30102605
RH
10726{
10727 struct unicosmk_extern_list *p;
10728
10729 p = (struct unicosmk_extern_list *)
6d9f628e 10730 xmalloc (sizeof (struct unicosmk_extern_list));
30102605
RH
10731 p->next = unicosmk_extern_head;
10732 p->name = name;
10733 unicosmk_extern_head = p;
10734}
10735
10736/* The Cray assembler generates incorrect code if identifiers which
10737 conflict with register names are used as instruction operands. We have
10738 to replace such identifiers with DEX expressions. */
10739
10740/* Structure to collect identifiers which have been replaced by DEX
10741 expressions. */
f030826a 10742/* FIXME: needs to use GC, so it can be saved and restored for PCH. */
30102605
RH
10743
10744struct unicosmk_dex {
10745 struct unicosmk_dex *next;
10746 const char *name;
10747};
10748
f676971a 10749/* List of identifiers which have been replaced by DEX expressions. The DEX
30102605
RH
10750 number is determined by the position in the list. */
10751
f676971a 10752static struct unicosmk_dex *unicosmk_dex_list = NULL;
30102605
RH
10753
10754/* The number of elements in the DEX list. */
10755
10756static int unicosmk_dex_count = 0;
10757
10758/* Check if NAME must be replaced by a DEX expression. */
10759
10760static int
a5c24926 10761unicosmk_special_name (const char *name)
30102605
RH
10762{
10763 if (name[0] == '*')
10764 ++name;
10765
10766 if (name[0] == '$')
10767 ++name;
10768
10769 if (name[0] != 'r' && name[0] != 'f' && name[0] != 'R' && name[0] != 'F')
10770 return 0;
10771
10772 switch (name[1])
10773 {
10774 case '1': case '2':
10775 return (name[2] == '\0' || (ISDIGIT (name[2]) && name[3] == '\0'));
10776
10777 case '3':
10778 return (name[2] == '\0'
10779 || ((name[2] == '0' || name[2] == '1') && name[3] == '\0'));
10780
10781 default:
10782 return (ISDIGIT (name[1]) && name[2] == '\0');
10783 }
10784}
10785
10786/* Return the DEX number if X must be replaced by a DEX expression and 0
10787 otherwise. */
10788
10789static int
a5c24926 10790unicosmk_need_dex (rtx x)
30102605
RH
10791{
10792 struct unicosmk_dex *dex;
10793 const char *name;
10794 int i;
f676971a 10795
30102605
RH
10796 if (GET_CODE (x) != SYMBOL_REF)
10797 return 0;
10798
10799 name = XSTR (x,0);
10800 if (! unicosmk_special_name (name))
10801 return 0;
10802
10803 i = unicosmk_dex_count;
10804 for (dex = unicosmk_dex_list; dex; dex = dex->next)
10805 {
10806 if (! strcmp (name, dex->name))
10807 return i;
10808 --i;
10809 }
f676971a 10810
6d9f628e 10811 dex = (struct unicosmk_dex *) xmalloc (sizeof (struct unicosmk_dex));
30102605
RH
10812 dex->name = name;
10813 dex->next = unicosmk_dex_list;
10814 unicosmk_dex_list = dex;
10815
10816 ++unicosmk_dex_count;
10817 return unicosmk_dex_count;
10818}
10819
10820/* Output the DEX definitions for this file. */
10821
10822static void
a5c24926 10823unicosmk_output_dex (FILE *file)
30102605
RH
10824{
10825 struct unicosmk_dex *dex;
10826 int i;
10827
10828 if (unicosmk_dex_list == NULL)
10829 return;
10830
10831 fprintf (file, "\t.dexstart\n");
10832
10833 i = unicosmk_dex_count;
10834 for (dex = unicosmk_dex_list; dex; dex = dex->next)
10835 {
10836 fprintf (file, "\tDEX (%d) = ", i);
10837 assemble_name (file, dex->name);
10838 putc ('\n', file);
10839 --i;
10840 }
f676971a 10841
30102605
RH
10842 fprintf (file, "\t.dexend\n");
10843}
10844
a5c24926
RH
10845/* Output text that to appear at the beginning of an assembler file. */
10846
f676971a 10847static void
1bc7c5b6 10848unicosmk_file_start (void)
a5c24926
RH
10849{
10850 int i;
10851
1bc7c5b6
ZW
10852 fputs ("\t.ident\t", asm_out_file);
10853 unicosmk_output_module_name (asm_out_file);
10854 fputs ("\n\n", asm_out_file);
a5c24926
RH
10855
10856 /* The Unicos/Mk assembler uses different register names. Instead of trying
10857 to support them, we simply use micro definitions. */
10858
10859 /* CAM has different register names: rN for the integer register N and fN
10860 for the floating-point register N. Instead of trying to use these in
10861 alpha.md, we define the symbols $N and $fN to refer to the appropriate
10862 register. */
10863
10864 for (i = 0; i < 32; ++i)
1bc7c5b6 10865 fprintf (asm_out_file, "$%d <- r%d\n", i, i);
a5c24926
RH
10866
10867 for (i = 0; i < 32; ++i)
1bc7c5b6 10868 fprintf (asm_out_file, "$f%d <- f%d\n", i, i);
a5c24926 10869
1bc7c5b6 10870 putc ('\n', asm_out_file);
a5c24926
RH
10871
10872 /* The .align directive fill unused space with zeroes which does not work
10873 in code sections. We define the macro 'gcc@code@align' which uses nops
10874 instead. Note that it assumes that code sections always have the
10875 biggest possible alignment since . refers to the current offset from
10876 the beginning of the section. */
10877
1bc7c5b6
ZW
10878 fputs ("\t.macro gcc@code@align n\n", asm_out_file);
10879 fputs ("gcc@n@bytes = 1 << n\n", asm_out_file);
10880 fputs ("gcc@here = . % gcc@n@bytes\n", asm_out_file);
10881 fputs ("\t.if ne, gcc@here, 0\n", asm_out_file);
10882 fputs ("\t.repeat (gcc@n@bytes - gcc@here) / 4\n", asm_out_file);
10883 fputs ("\tbis r31,r31,r31\n", asm_out_file);
10884 fputs ("\t.endr\n", asm_out_file);
10885 fputs ("\t.endif\n", asm_out_file);
10886 fputs ("\t.endm gcc@code@align\n\n", asm_out_file);
a5c24926
RH
10887
10888 /* Output extern declarations which should always be visible. */
1bc7c5b6 10889 unicosmk_output_default_externs (asm_out_file);
a5c24926
RH
10890
10891 /* Open a dummy section. We always need to be inside a section for the
10892 section-switching code to work correctly.
10893 ??? This should be a module id or something like that. I still have to
10894 figure out what the rules for those are. */
1bc7c5b6 10895 fputs ("\n\t.psect\t$SG00000,data\n", asm_out_file);
a5c24926
RH
10896}
10897
10898/* Output text to appear at the end of an assembler file. This includes all
10899 pending extern declarations and DEX expressions. */
10900
10901static void
10902unicosmk_file_end (void)
10903{
10904 fputs ("\t.endp\n\n", asm_out_file);
10905
10906 /* Output all pending externs. */
10907
10908 unicosmk_output_externs (asm_out_file);
10909
f676971a 10910 /* Output dex definitions used for functions whose names conflict with
a5c24926
RH
10911 register names. */
10912
10913 unicosmk_output_dex (asm_out_file);
10914
10915 fputs ("\t.end\t", asm_out_file);
10916 unicosmk_output_module_name (asm_out_file);
10917 putc ('\n', asm_out_file);
10918}
10919
30102605
RH
10920#else
10921
10922static void
a5c24926 10923unicosmk_output_deferred_case_vectors (FILE *file ATTRIBUTE_UNUSED)
30102605
RH
10924{}
10925
10926static void
a5c24926 10927unicosmk_gen_dsib (unsigned long *imaskP ATTRIBUTE_UNUSED)
30102605
RH
10928{}
10929
10930static void
a5c24926
RH
10931unicosmk_output_ssib (FILE * file ATTRIBUTE_UNUSED,
10932 const char * fnname ATTRIBUTE_UNUSED)
30102605
RH
10933{}
10934
10935rtx
a5c24926 10936unicosmk_add_call_info_word (rtx x ATTRIBUTE_UNUSED)
30102605
RH
10937{
10938 return NULL_RTX;
10939}
10940
10941static int
a5c24926 10942unicosmk_need_dex (rtx x ATTRIBUTE_UNUSED)
30102605
RH
10943{
10944 return 0;
10945}
10946
10947#endif /* TARGET_ABI_UNICOSMK */
e2500fed 10948
c15c90bb
ZW
10949static void
10950alpha_init_libfuncs (void)
10951{
10952 if (TARGET_ABI_UNICOSMK)
10953 {
10954 /* Prevent gcc from generating calls to __divsi3. */
10955 set_optab_libfunc (sdiv_optab, SImode, 0);
10956 set_optab_libfunc (udiv_optab, SImode, 0);
10957
10958 /* Use the functions provided by the system library
10959 for DImode integer division. */
10960 set_optab_libfunc (sdiv_optab, DImode, "$sldiv");
10961 set_optab_libfunc (udiv_optab, DImode, "$uldiv");
10962 }
10963 else if (TARGET_ABI_OPEN_VMS)
10964 {
10965 /* Use the VMS runtime library functions for division and
10966 remainder. */
10967 set_optab_libfunc (sdiv_optab, SImode, "OTS$DIV_I");
10968 set_optab_libfunc (sdiv_optab, DImode, "OTS$DIV_L");
10969 set_optab_libfunc (udiv_optab, SImode, "OTS$DIV_UI");
10970 set_optab_libfunc (udiv_optab, DImode, "OTS$DIV_UL");
10971 set_optab_libfunc (smod_optab, SImode, "OTS$REM_I");
10972 set_optab_libfunc (smod_optab, DImode, "OTS$REM_L");
10973 set_optab_libfunc (umod_optab, SImode, "OTS$REM_UI");
10974 set_optab_libfunc (umod_optab, DImode, "OTS$REM_UL");
5e3fef6c
DR
10975 abort_libfunc = init_one_libfunc ("decc$abort");
10976 memcmp_libfunc = init_one_libfunc ("decc$memcmp");
10977#ifdef MEM_LIBFUNCS_INIT
10978 MEM_LIBFUNCS_INIT;
10979#endif
c15c90bb
ZW
10980 }
10981}
10982
a5c24926
RH
10983\f
10984/* Initialize the GCC target structure. */
10985#if TARGET_ABI_OPEN_VMS
10986# undef TARGET_ATTRIBUTE_TABLE
10987# define TARGET_ATTRIBUTE_TABLE vms_attribute_table
7b5cbb57
AS
10988# undef TARGET_CAN_ELIMINATE
10989# define TARGET_CAN_ELIMINATE alpha_vms_can_eliminate
a5c24926
RH
10990#endif
10991
10992#undef TARGET_IN_SMALL_DATA_P
10993#define TARGET_IN_SMALL_DATA_P alpha_in_small_data_p
10994
10995#if TARGET_ABI_UNICOSMK
10996# undef TARGET_INSERT_ATTRIBUTES
10997# define TARGET_INSERT_ATTRIBUTES unicosmk_insert_attributes
10998# undef TARGET_SECTION_TYPE_FLAGS
10999# define TARGET_SECTION_TYPE_FLAGS unicosmk_section_type_flags
11000# undef TARGET_ASM_UNIQUE_SECTION
11001# define TARGET_ASM_UNIQUE_SECTION unicosmk_unique_section
ab5c8549
JJ
11002#undef TARGET_ASM_FUNCTION_RODATA_SECTION
11003#define TARGET_ASM_FUNCTION_RODATA_SECTION default_no_function_rodata_section
a5c24926
RH
11004# undef TARGET_ASM_GLOBALIZE_LABEL
11005# define TARGET_ASM_GLOBALIZE_LABEL hook_void_FILEptr_constcharptr
fe984136
RH
11006# undef TARGET_MUST_PASS_IN_STACK
11007# define TARGET_MUST_PASS_IN_STACK unicosmk_must_pass_in_stack
a5c24926
RH
11008#endif
11009
11010#undef TARGET_ASM_ALIGNED_HI_OP
11011#define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
11012#undef TARGET_ASM_ALIGNED_DI_OP
11013#define TARGET_ASM_ALIGNED_DI_OP "\t.quad\t"
11014
11015/* Default unaligned ops are provided for ELF systems. To get unaligned
11016 data for non-ELF systems, we have to turn off auto alignment. */
3bd1b109 11017#if !defined (OBJECT_FORMAT_ELF) || TARGET_ABI_OPEN_VMS
a5c24926
RH
11018#undef TARGET_ASM_UNALIGNED_HI_OP
11019#define TARGET_ASM_UNALIGNED_HI_OP "\t.align 0\n\t.word\t"
11020#undef TARGET_ASM_UNALIGNED_SI_OP
11021#define TARGET_ASM_UNALIGNED_SI_OP "\t.align 0\n\t.long\t"
11022#undef TARGET_ASM_UNALIGNED_DI_OP
11023#define TARGET_ASM_UNALIGNED_DI_OP "\t.align 0\n\t.quad\t"
11024#endif
11025
11026#ifdef OBJECT_FORMAT_ELF
9b580a0b
RH
11027#undef TARGET_ASM_RELOC_RW_MASK
11028#define TARGET_ASM_RELOC_RW_MASK alpha_elf_reloc_rw_mask
a5c24926
RH
11029#undef TARGET_ASM_SELECT_RTX_SECTION
11030#define TARGET_ASM_SELECT_RTX_SECTION alpha_elf_select_rtx_section
ae069803
RH
11031#undef TARGET_SECTION_TYPE_FLAGS
11032#define TARGET_SECTION_TYPE_FLAGS alpha_elf_section_type_flags
a5c24926
RH
11033#endif
11034
11035#undef TARGET_ASM_FUNCTION_END_PROLOGUE
11036#define TARGET_ASM_FUNCTION_END_PROLOGUE alpha_output_function_end_prologue
11037
c15c90bb
ZW
11038#undef TARGET_INIT_LIBFUNCS
11039#define TARGET_INIT_LIBFUNCS alpha_init_libfuncs
11040
506d7b68
PB
11041#undef TARGET_LEGITIMIZE_ADDRESS
11042#define TARGET_LEGITIMIZE_ADDRESS alpha_legitimize_address
11043
1bc7c5b6
ZW
11044#if TARGET_ABI_UNICOSMK
11045#undef TARGET_ASM_FILE_START
11046#define TARGET_ASM_FILE_START unicosmk_file_start
11047#undef TARGET_ASM_FILE_END
11048#define TARGET_ASM_FILE_END unicosmk_file_end
11049#else
11050#undef TARGET_ASM_FILE_START
11051#define TARGET_ASM_FILE_START alpha_file_start
11052#undef TARGET_ASM_FILE_START_FILE_DIRECTIVE
11053#define TARGET_ASM_FILE_START_FILE_DIRECTIVE true
11054#endif
11055
a5c24926
RH
11056#undef TARGET_SCHED_ADJUST_COST
11057#define TARGET_SCHED_ADJUST_COST alpha_adjust_cost
11058#undef TARGET_SCHED_ISSUE_RATE
11059#define TARGET_SCHED_ISSUE_RATE alpha_issue_rate
a5c24926
RH
11060#undef TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD
11061#define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD \
11062 alpha_multipass_dfa_lookahead
11063
11064#undef TARGET_HAVE_TLS
11065#define TARGET_HAVE_TLS HAVE_AS_TLS
11066
11067#undef TARGET_INIT_BUILTINS
11068#define TARGET_INIT_BUILTINS alpha_init_builtins
11069#undef TARGET_EXPAND_BUILTIN
11070#define TARGET_EXPAND_BUILTIN alpha_expand_builtin
36013987
RH
11071#undef TARGET_FOLD_BUILTIN
11072#define TARGET_FOLD_BUILTIN alpha_fold_builtin
a5c24926
RH
11073
11074#undef TARGET_FUNCTION_OK_FOR_SIBCALL
11075#define TARGET_FUNCTION_OK_FOR_SIBCALL alpha_function_ok_for_sibcall
11076#undef TARGET_CANNOT_COPY_INSN_P
11077#define TARGET_CANNOT_COPY_INSN_P alpha_cannot_copy_insn_p
04886dc0
RH
11078#undef TARGET_CANNOT_FORCE_CONST_MEM
11079#define TARGET_CANNOT_FORCE_CONST_MEM alpha_cannot_force_const_mem
a5c24926
RH
11080
11081#if TARGET_ABI_OSF
11082#undef TARGET_ASM_OUTPUT_MI_THUNK
11083#define TARGET_ASM_OUTPUT_MI_THUNK alpha_output_mi_thunk_osf
11084#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
3101faab 11085#define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_const_tree_hwi_hwi_const_tree_true
3f620b5f
RH
11086#undef TARGET_STDARG_OPTIMIZE_HOOK
11087#define TARGET_STDARG_OPTIMIZE_HOOK alpha_stdarg_optimize_hook
a5c24926
RH
11088#endif
11089
11090#undef TARGET_RTX_COSTS
11091#define TARGET_RTX_COSTS alpha_rtx_costs
11092#undef TARGET_ADDRESS_COST
f40751dd 11093#define TARGET_ADDRESS_COST hook_int_rtx_bool_0
a5c24926
RH
11094
11095#undef TARGET_MACHINE_DEPENDENT_REORG
11096#define TARGET_MACHINE_DEPENDENT_REORG alpha_reorg
11097
cde0f3fd
PB
11098#undef TARGET_PROMOTE_FUNCTION_MODE
11099#define TARGET_PROMOTE_FUNCTION_MODE default_promote_function_mode_always_promote
f93c2180 11100#undef TARGET_PROMOTE_PROTOTYPES
586de218 11101#define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_false
f93c2180
RH
11102#undef TARGET_RETURN_IN_MEMORY
11103#define TARGET_RETURN_IN_MEMORY alpha_return_in_memory
8cd5a4e0
RH
11104#undef TARGET_PASS_BY_REFERENCE
11105#define TARGET_PASS_BY_REFERENCE alpha_pass_by_reference
f93c2180
RH
11106#undef TARGET_SETUP_INCOMING_VARARGS
11107#define TARGET_SETUP_INCOMING_VARARGS alpha_setup_incoming_varargs
11108#undef TARGET_STRICT_ARGUMENT_NAMING
11109#define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true
11110#undef TARGET_PRETEND_OUTGOING_VARARGS_NAMED
11111#define TARGET_PRETEND_OUTGOING_VARARGS_NAMED hook_bool_CUMULATIVE_ARGS_true
42ba5130
RH
11112#undef TARGET_SPLIT_COMPLEX_ARG
11113#define TARGET_SPLIT_COMPLEX_ARG alpha_split_complex_arg
28245018
RH
11114#undef TARGET_GIMPLIFY_VA_ARG_EXPR
11115#define TARGET_GIMPLIFY_VA_ARG_EXPR alpha_gimplify_va_arg
78a52f11
RH
11116#undef TARGET_ARG_PARTIAL_BYTES
11117#define TARGET_ARG_PARTIAL_BYTES alpha_arg_partial_bytes
2d7b663a
RH
11118#undef TARGET_TRAMPOLINE_INIT
11119#define TARGET_TRAMPOLINE_INIT alpha_trampoline_init
6dd53648 11120
48f46219
RH
11121#undef TARGET_SECONDARY_RELOAD
11122#define TARGET_SECONDARY_RELOAD alpha_secondary_reload
11123
6dd53648
RH
11124#undef TARGET_SCALAR_MODE_SUPPORTED_P
11125#define TARGET_SCALAR_MODE_SUPPORTED_P alpha_scalar_mode_supported_p
f676971a
EC
11126#undef TARGET_VECTOR_MODE_SUPPORTED_P
11127#define TARGET_VECTOR_MODE_SUPPORTED_P alpha_vector_mode_supported_p
f93c2180 11128
c35d187f
RH
11129#undef TARGET_BUILD_BUILTIN_VA_LIST
11130#define TARGET_BUILD_BUILTIN_VA_LIST alpha_build_builtin_va_list
11131
d7bd8aeb
JJ
11132#undef TARGET_EXPAND_BUILTIN_VA_START
11133#define TARGET_EXPAND_BUILTIN_VA_START alpha_va_start
11134
445cf5eb
JM
11135/* The Alpha architecture does not require sequential consistency. See
11136 http://www.cs.umd.edu/~pugh/java/memoryModel/AlphaReordering.html
11137 for an example of how it can be violated in practice. */
11138#undef TARGET_RELAXED_ORDERING
11139#define TARGET_RELAXED_ORDERING true
11140
8bea7f7c
RH
11141#undef TARGET_DEFAULT_TARGET_FLAGS
11142#define TARGET_DEFAULT_TARGET_FLAGS \
11143 (TARGET_DEFAULT | TARGET_CPU_DEFAULT | TARGET_DEFAULT_EXPLICIT_RELOCS)
11144#undef TARGET_HANDLE_OPTION
11145#define TARGET_HANDLE_OPTION alpha_handle_option
11146
7269aee7 11147#ifdef TARGET_ALTERNATE_LONG_DOUBLE_MANGLING
608063c3
JB
11148#undef TARGET_MANGLE_TYPE
11149#define TARGET_MANGLE_TYPE alpha_mangle_type
7269aee7
AH
11150#endif
11151
c6c3dba9
PB
11152#undef TARGET_LEGITIMATE_ADDRESS_P
11153#define TARGET_LEGITIMATE_ADDRESS_P alpha_legitimate_address_p
11154
a5c24926
RH
11155struct gcc_target targetm = TARGET_INITIALIZER;
11156
11157\f
e2500fed 11158#include "gt-alpha.h"