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