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