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