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