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