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