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