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