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