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