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