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