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