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