OSDN Git Service

6e0001b0a05a6c0a39215f20728b3f67b2d3e659
[pf3gnuchains/gcc-fork.git] / gcc / config / spu / spu.c
1 /* Copyright (C) 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
2
3    This file is free software; you can redistribute it and/or modify it under
4    the terms of the GNU General Public License as published by the Free
5    Software Foundation; either version 3 of the License, or (at your option) 
6    any later version.
7
8    This file is distributed in the hope that it will be useful, but WITHOUT
9    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
11    for more details.
12
13    You should have received a copy of the GNU General Public License
14    along with GCC; see the file COPYING3.  If not see
15    <http://www.gnu.org/licenses/>.  */
16
17 #include "config.h"
18 #include "system.h"
19 #include "coretypes.h"
20 #include "tm.h"
21 #include "rtl.h"
22 #include "regs.h"
23 #include "hard-reg-set.h"
24 #include "real.h"
25 #include "insn-config.h"
26 #include "conditions.h"
27 #include "insn-attr.h"
28 #include "flags.h"
29 #include "recog.h"
30 #include "obstack.h"
31 #include "tree.h"
32 #include "expr.h"
33 #include "optabs.h"
34 #include "except.h"
35 #include "function.h"
36 #include "output.h"
37 #include "basic-block.h"
38 #include "integrate.h"
39 #include "toplev.h"
40 #include "ggc.h"
41 #include "hashtab.h"
42 #include "tm_p.h"
43 #include "target.h"
44 #include "target-def.h"
45 #include "langhooks.h"
46 #include "reload.h"
47 #include "cfglayout.h"
48 #include "sched-int.h"
49 #include "params.h"
50 #include "assert.h"
51 #include "c-common.h"
52 #include "machmode.h"
53 #include "gimple.h"
54 #include "tm-constrs.h"
55 #include "spu-builtins.h"
56 #include "ddg.h"
57 #include "sbitmap.h"
58 #include "timevar.h"
59 #include "df.h"
60
61 /* Builtin types, data and prototypes. */
62 struct spu_builtin_range
63 {
64   int low, high;
65 };
66
67 static struct spu_builtin_range spu_builtin_range[] = {
68   {-0x40ll, 0x7fll},            /* SPU_BTI_7     */
69   {-0x40ll, 0x3fll},            /* SPU_BTI_S7    */
70   {0ll, 0x7fll},                /* SPU_BTI_U7    */
71   {-0x200ll, 0x1ffll},          /* SPU_BTI_S10   */
72   {-0x2000ll, 0x1fffll},        /* SPU_BTI_S10_4 */
73   {0ll, 0x3fffll},              /* SPU_BTI_U14   */
74   {-0x8000ll, 0xffffll},        /* SPU_BTI_16    */
75   {-0x8000ll, 0x7fffll},        /* SPU_BTI_S16   */
76   {-0x20000ll, 0x1ffffll},      /* SPU_BTI_S16_2 */
77   {0ll, 0xffffll},              /* SPU_BTI_U16   */
78   {0ll, 0x3ffffll},             /* SPU_BTI_U16_2 */
79   {0ll, 0x3ffffll},             /* SPU_BTI_U18   */
80 };
81
82 \f
83 /*  Target specific attribute specifications.  */
84 char regs_ever_allocated[FIRST_PSEUDO_REGISTER];
85
86 /*  Prototypes and external defs.  */
87 static void spu_init_builtins (void);
88 static unsigned char spu_scalar_mode_supported_p (enum machine_mode mode);
89 static unsigned char spu_vector_mode_supported_p (enum machine_mode mode);
90 static rtx adjust_operand (rtx op, HOST_WIDE_INT * start);
91 static rtx get_pic_reg (void);
92 static int need_to_save_reg (int regno, int saving);
93 static rtx frame_emit_store (int regno, rtx addr, HOST_WIDE_INT offset);
94 static rtx frame_emit_load (int regno, rtx addr, HOST_WIDE_INT offset);
95 static rtx frame_emit_add_imm (rtx dst, rtx src, HOST_WIDE_INT imm,
96                                rtx scratch);
97 static void emit_nop_for_insn (rtx insn);
98 static bool insn_clobbers_hbr (rtx insn);
99 static void spu_emit_branch_hint (rtx before, rtx branch, rtx target,
100                                   int distance, sbitmap blocks);
101 static rtx spu_emit_vector_compare (enum rtx_code rcode, rtx op0, rtx op1,
102                                     enum machine_mode dmode);
103 static rtx get_branch_target (rtx branch);
104 static void spu_machine_dependent_reorg (void);
105 static int spu_sched_issue_rate (void);
106 static int spu_sched_variable_issue (FILE * dump, int verbose, rtx insn,
107                                      int can_issue_more);
108 static int get_pipe (rtx insn);
109 static int spu_sched_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost);
110 static void spu_sched_init_global (FILE *, int, int);
111 static void spu_sched_init (FILE *, int, int);
112 static int spu_sched_reorder (FILE *, int, rtx *, int *, int);
113 static tree spu_handle_fndecl_attribute (tree * node, tree name, tree args,
114                                          int flags,
115                                          unsigned char *no_add_attrs);
116 static tree spu_handle_vector_attribute (tree * node, tree name, tree args,
117                                          int flags,
118                                          unsigned char *no_add_attrs);
119 static int spu_naked_function_p (tree func);
120 static unsigned char spu_pass_by_reference (CUMULATIVE_ARGS *cum, enum machine_mode mode,
121                                             const_tree type, unsigned char named);
122 static tree spu_build_builtin_va_list (void);
123 static void spu_va_start (tree, rtx);
124 static tree spu_gimplify_va_arg_expr (tree valist, tree type,
125                                       gimple_seq * pre_p, gimple_seq * post_p);
126 static int regno_aligned_for_load (int regno);
127 static int store_with_one_insn_p (rtx mem);
128 static int mem_is_padded_component_ref (rtx x);
129 static bool spu_assemble_integer (rtx x, unsigned int size, int aligned_p);
130 static void spu_asm_globalize_label (FILE * file, const char *name);
131 static unsigned char spu_rtx_costs (rtx x, int code, int outer_code,
132                                     int *total, bool speed);
133 static unsigned char spu_function_ok_for_sibcall (tree decl, tree exp);
134 static void spu_init_libfuncs (void);
135 static bool spu_return_in_memory (const_tree type, const_tree fntype);
136 static void fix_range (const char *);
137 static void spu_encode_section_info (tree, rtx, int);
138 static tree spu_builtin_mul_widen_even (tree);
139 static tree spu_builtin_mul_widen_odd (tree);
140 static tree spu_builtin_mask_for_load (void);
141 static int spu_builtin_vectorization_cost (bool);
142 static bool spu_vector_alignment_reachable (const_tree, bool);
143 static tree spu_builtin_vec_perm (tree, tree *);
144 static int spu_sms_res_mii (struct ddg *g);
145 static void asm_file_start (void);
146 static unsigned int spu_section_type_flags (tree, const char *, int);
147
148 extern const char *reg_names[];
149 rtx spu_compare_op0, spu_compare_op1;
150
151 /* Which instruction set architecture to use.  */
152 int spu_arch;
153 /* Which cpu are we tuning for.  */
154 int spu_tune;
155
156 /* The hardware requires 8 insns between a hint and the branch it
157    effects.  This variable describes how many rtl instructions the
158    compiler needs to see before inserting a hint, and then the compiler
159    will insert enough nops to make it at least 8 insns.  The default is
160    for the compiler to allow up to 2 nops be emitted.  The nops are
161    inserted in pairs, so we round down. */
162 int spu_hint_dist = (8*4) - (2*4);
163
164 /* Determines whether we run variable tracking in machine dependent
165    reorganization.  */
166 static int spu_flag_var_tracking;
167
168 enum spu_immediate {
169   SPU_NONE,
170   SPU_IL,
171   SPU_ILA,
172   SPU_ILH,
173   SPU_ILHU,
174   SPU_ORI,
175   SPU_ORHI,
176   SPU_ORBI,
177   SPU_IOHL
178 };
179 enum immediate_class
180 {
181   IC_POOL,                      /* constant pool */
182   IC_IL1,                       /* one il* instruction */
183   IC_IL2,                       /* both ilhu and iohl instructions */
184   IC_IL1s,                      /* one il* instruction */
185   IC_IL2s,                      /* both ilhu and iohl instructions */
186   IC_FSMBI,                     /* the fsmbi instruction */
187   IC_CPAT,                      /* one of the c*d instructions */
188   IC_FSMBI2                     /* fsmbi plus 1 other instruction */
189 };
190
191 static enum spu_immediate which_immediate_load (HOST_WIDE_INT val);
192 static enum spu_immediate which_logical_immediate (HOST_WIDE_INT val);
193 static int cpat_info(unsigned char *arr, int size, int *prun, int *pstart);
194 static enum immediate_class classify_immediate (rtx op,
195                                                 enum machine_mode mode);
196
197 static enum machine_mode spu_unwind_word_mode (void);
198
199 static enum machine_mode
200 spu_libgcc_cmp_return_mode (void);
201
202 static enum machine_mode
203 spu_libgcc_shift_count_mode (void);
204
205 /* Built in types.  */
206 tree spu_builtin_types[SPU_BTI_MAX];
207 \f
208 /*  TARGET overrides.  */
209
210 #undef TARGET_INIT_BUILTINS
211 #define TARGET_INIT_BUILTINS spu_init_builtins
212
213 #undef TARGET_EXPAND_BUILTIN
214 #define TARGET_EXPAND_BUILTIN spu_expand_builtin
215
216 #undef TARGET_UNWIND_WORD_MODE
217 #define TARGET_UNWIND_WORD_MODE spu_unwind_word_mode
218
219 /* The .8byte directive doesn't seem to work well for a 32 bit
220    architecture. */
221 #undef TARGET_ASM_UNALIGNED_DI_OP
222 #define TARGET_ASM_UNALIGNED_DI_OP NULL
223
224 #undef TARGET_RTX_COSTS
225 #define TARGET_RTX_COSTS spu_rtx_costs
226
227 #undef TARGET_ADDRESS_COST
228 #define TARGET_ADDRESS_COST hook_int_rtx_bool_0
229
230 #undef TARGET_SCHED_ISSUE_RATE
231 #define TARGET_SCHED_ISSUE_RATE spu_sched_issue_rate
232
233 #undef TARGET_SCHED_INIT_GLOBAL
234 #define TARGET_SCHED_INIT_GLOBAL spu_sched_init_global
235
236 #undef TARGET_SCHED_INIT
237 #define TARGET_SCHED_INIT spu_sched_init
238
239 #undef TARGET_SCHED_VARIABLE_ISSUE
240 #define TARGET_SCHED_VARIABLE_ISSUE spu_sched_variable_issue
241
242 #undef TARGET_SCHED_REORDER
243 #define TARGET_SCHED_REORDER spu_sched_reorder
244
245 #undef TARGET_SCHED_REORDER2
246 #define TARGET_SCHED_REORDER2 spu_sched_reorder
247
248 #undef TARGET_SCHED_ADJUST_COST
249 #define TARGET_SCHED_ADJUST_COST spu_sched_adjust_cost
250
251 const struct attribute_spec spu_attribute_table[];
252 #undef  TARGET_ATTRIBUTE_TABLE
253 #define TARGET_ATTRIBUTE_TABLE spu_attribute_table
254
255 #undef TARGET_ASM_INTEGER
256 #define TARGET_ASM_INTEGER spu_assemble_integer
257
258 #undef TARGET_SCALAR_MODE_SUPPORTED_P
259 #define TARGET_SCALAR_MODE_SUPPORTED_P  spu_scalar_mode_supported_p
260
261 #undef TARGET_VECTOR_MODE_SUPPORTED_P
262 #define TARGET_VECTOR_MODE_SUPPORTED_P  spu_vector_mode_supported_p
263
264 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
265 #define TARGET_FUNCTION_OK_FOR_SIBCALL spu_function_ok_for_sibcall
266
267 #undef TARGET_ASM_GLOBALIZE_LABEL
268 #define TARGET_ASM_GLOBALIZE_LABEL spu_asm_globalize_label
269
270 #undef TARGET_PASS_BY_REFERENCE
271 #define TARGET_PASS_BY_REFERENCE spu_pass_by_reference
272
273 #undef TARGET_MUST_PASS_IN_STACK
274 #define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size
275
276 #undef TARGET_BUILD_BUILTIN_VA_LIST
277 #define TARGET_BUILD_BUILTIN_VA_LIST spu_build_builtin_va_list
278
279 #undef TARGET_EXPAND_BUILTIN_VA_START
280 #define TARGET_EXPAND_BUILTIN_VA_START spu_va_start
281
282 #undef TARGET_SETUP_INCOMING_VARARGS
283 #define TARGET_SETUP_INCOMING_VARARGS spu_setup_incoming_varargs
284
285 #undef TARGET_MACHINE_DEPENDENT_REORG
286 #define TARGET_MACHINE_DEPENDENT_REORG spu_machine_dependent_reorg
287
288 #undef TARGET_GIMPLIFY_VA_ARG_EXPR
289 #define TARGET_GIMPLIFY_VA_ARG_EXPR spu_gimplify_va_arg_expr
290
291 #undef TARGET_DEFAULT_TARGET_FLAGS
292 #define TARGET_DEFAULT_TARGET_FLAGS (TARGET_DEFAULT)
293
294 #undef TARGET_INIT_LIBFUNCS
295 #define TARGET_INIT_LIBFUNCS spu_init_libfuncs
296
297 #undef TARGET_RETURN_IN_MEMORY
298 #define TARGET_RETURN_IN_MEMORY spu_return_in_memory
299
300 #undef  TARGET_ENCODE_SECTION_INFO
301 #define TARGET_ENCODE_SECTION_INFO spu_encode_section_info
302
303 #undef TARGET_VECTORIZE_BUILTIN_MUL_WIDEN_EVEN
304 #define TARGET_VECTORIZE_BUILTIN_MUL_WIDEN_EVEN spu_builtin_mul_widen_even
305
306 #undef TARGET_VECTORIZE_BUILTIN_MUL_WIDEN_ODD
307 #define TARGET_VECTORIZE_BUILTIN_MUL_WIDEN_ODD spu_builtin_mul_widen_odd
308
309 #undef TARGET_VECTORIZE_BUILTIN_MASK_FOR_LOAD
310 #define TARGET_VECTORIZE_BUILTIN_MASK_FOR_LOAD spu_builtin_mask_for_load
311
312 #undef TARGET_VECTORIZE_BUILTIN_VECTORIZATION_COST
313 #define TARGET_VECTORIZE_BUILTIN_VECTORIZATION_COST spu_builtin_vectorization_cost
314
315 #undef TARGET_VECTOR_ALIGNMENT_REACHABLE
316 #define TARGET_VECTOR_ALIGNMENT_REACHABLE spu_vector_alignment_reachable
317
318 #undef TARGET_VECTORIZE_BUILTIN_VEC_PERM
319 #define TARGET_VECTORIZE_BUILTIN_VEC_PERM spu_builtin_vec_perm
320
321 #undef TARGET_LIBGCC_CMP_RETURN_MODE
322 #define TARGET_LIBGCC_CMP_RETURN_MODE spu_libgcc_cmp_return_mode
323
324 #undef TARGET_LIBGCC_SHIFT_COUNT_MODE
325 #define TARGET_LIBGCC_SHIFT_COUNT_MODE spu_libgcc_shift_count_mode
326
327 #undef TARGET_SCHED_SMS_RES_MII
328 #define TARGET_SCHED_SMS_RES_MII spu_sms_res_mii
329
330 #undef TARGET_ASM_FILE_START
331 #define TARGET_ASM_FILE_START asm_file_start
332
333 #undef TARGET_SECTION_TYPE_FLAGS
334 #define TARGET_SECTION_TYPE_FLAGS spu_section_type_flags
335
336 struct gcc_target targetm = TARGET_INITIALIZER;
337
338 void
339 spu_optimization_options (int level ATTRIBUTE_UNUSED, int size ATTRIBUTE_UNUSED)
340 {
341   /* Override some of the default param values.  With so many registers
342      larger values are better for these params.  */
343   MAX_PENDING_LIST_LENGTH = 128;
344
345   /* With so many registers this is better on by default. */
346   flag_rename_registers = 1;
347 }
348
349 /* Sometimes certain combinations of command options do not make sense
350    on a particular target machine.  You can define a macro
351    OVERRIDE_OPTIONS to take account of this. This macro, if defined, is
352    executed once just after all the command options have been parsed.  */
353 void
354 spu_override_options (void)
355 {
356   /* Small loops will be unpeeled at -O3.  For SPU it is more important
357      to keep code small by default.  */
358   if (!flag_unroll_loops && !flag_peel_loops
359       && !PARAM_SET_P (PARAM_MAX_COMPLETELY_PEEL_TIMES))
360     PARAM_VALUE (PARAM_MAX_COMPLETELY_PEEL_TIMES) = 1;
361
362   flag_omit_frame_pointer = 1;
363
364   /* Functions must be 8 byte aligned so we correctly handle dual issue */
365   if (align_functions < 8)
366     align_functions = 8;
367
368   spu_hint_dist = 8*4 - spu_max_nops*4;
369   if (spu_hint_dist < 0) 
370     spu_hint_dist = 0;
371
372   if (spu_fixed_range_string)
373     fix_range (spu_fixed_range_string);
374
375   /* Determine processor architectural level.  */
376   if (spu_arch_string)
377     {
378       if (strcmp (&spu_arch_string[0], "cell") == 0)
379         spu_arch = PROCESSOR_CELL;
380       else if (strcmp (&spu_arch_string[0], "celledp") == 0)
381         spu_arch = PROCESSOR_CELLEDP;
382       else
383         error ("Unknown architecture '%s'", &spu_arch_string[0]);
384     }
385
386   /* Determine processor to tune for.  */
387   if (spu_tune_string)
388     {
389       if (strcmp (&spu_tune_string[0], "cell") == 0)
390         spu_tune = PROCESSOR_CELL;
391       else if (strcmp (&spu_tune_string[0], "celledp") == 0)
392         spu_tune = PROCESSOR_CELLEDP;
393       else
394         error ("Unknown architecture '%s'", &spu_tune_string[0]);
395     }
396
397   /* Change defaults according to the processor architecture.  */
398   if (spu_arch == PROCESSOR_CELLEDP)
399     {
400       /* If no command line option has been otherwise specified, change
401          the default to -mno-safe-hints on celledp -- only the original
402          Cell/B.E. processors require this workaround.  */
403       if (!(target_flags_explicit & MASK_SAFE_HINTS))
404         target_flags &= ~MASK_SAFE_HINTS;
405     }
406
407   REAL_MODE_FORMAT (SFmode) = &spu_single_format;
408 }
409 \f
410 /* Handle an attribute requiring a FUNCTION_DECL; arguments as in
411    struct attribute_spec.handler.  */
412
413 /*  Table of machine attributes.  */
414 const struct attribute_spec spu_attribute_table[] =
415 {
416   /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
417   { "naked",          0, 0, true,  false, false, spu_handle_fndecl_attribute },
418   { "spu_vector",     0, 0, false, true,  false, spu_handle_vector_attribute },
419   { NULL,             0, 0, false, false, false, NULL }
420 };
421
422 /* True if MODE is valid for the target.  By "valid", we mean able to
423    be manipulated in non-trivial ways.  In particular, this means all
424    the arithmetic is supported.  */
425 static bool
426 spu_scalar_mode_supported_p (enum machine_mode mode)
427 {
428   switch (mode)
429     {
430     case QImode:
431     case HImode:
432     case SImode:
433     case SFmode:
434     case DImode:
435     case TImode:
436     case DFmode:
437       return true;
438
439     default:
440       return false;
441     }
442 }
443
444 /* Similarly for vector modes.  "Supported" here is less strict.  At
445    least some operations are supported; need to check optabs or builtins
446    for further details.  */
447 static bool
448 spu_vector_mode_supported_p (enum machine_mode mode)
449 {
450   switch (mode)
451     {
452     case V16QImode:
453     case V8HImode:
454     case V4SImode:
455     case V2DImode:
456     case V4SFmode:
457     case V2DFmode:
458       return true;
459
460     default:
461       return false;
462     }
463 }
464
465 /* GCC assumes that in a paradoxical SUBREG the inner mode occupies the
466    least significant bytes of the outer mode.  This function returns
467    TRUE for the SUBREG's where this is correct.  */
468 int
469 valid_subreg (rtx op)
470 {
471   enum machine_mode om = GET_MODE (op);
472   enum machine_mode im = GET_MODE (SUBREG_REG (op));
473   return om != VOIDmode && im != VOIDmode
474     && (GET_MODE_SIZE (im) == GET_MODE_SIZE (om)
475         || (GET_MODE_SIZE (im) <= 4 && GET_MODE_SIZE (om) <= 4)
476         || (GET_MODE_SIZE (im) >= 16 && GET_MODE_SIZE (om) >= 16));
477 }
478
479 /* When insv and ext[sz]v ar passed a TI SUBREG, we want to strip it off
480    and adjust the start offset.  */
481 static rtx
482 adjust_operand (rtx op, HOST_WIDE_INT * start)
483 {
484   enum machine_mode mode;
485   int op_size;
486   /* Strip any paradoxical SUBREG.  */
487   if (GET_CODE (op) == SUBREG
488       && (GET_MODE_BITSIZE (GET_MODE (op))
489           > GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (op)))))
490     {
491       if (start)
492         *start -=
493           GET_MODE_BITSIZE (GET_MODE (op)) -
494           GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (op)));
495       op = SUBREG_REG (op);
496     }
497   /* If it is smaller than SI, assure a SUBREG */
498   op_size = GET_MODE_BITSIZE (GET_MODE (op));
499   if (op_size < 32)
500     {
501       if (start)
502         *start += 32 - op_size;
503       op_size = 32;
504     }
505   /* If it is not a MODE_INT (and/or it is smaller than SI) add a SUBREG. */
506   mode = mode_for_size (op_size, MODE_INT, 0);
507   if (mode != GET_MODE (op))
508     op = gen_rtx_SUBREG (mode, op, 0);
509   return op;
510 }
511
512 void
513 spu_expand_extv (rtx ops[], int unsignedp)
514 {
515   HOST_WIDE_INT width = INTVAL (ops[2]);
516   HOST_WIDE_INT start = INTVAL (ops[3]);
517   HOST_WIDE_INT src_size, dst_size;
518   enum machine_mode src_mode, dst_mode;
519   rtx dst = ops[0], src = ops[1];
520   rtx s;
521
522   dst = adjust_operand (ops[0], 0);
523   dst_mode = GET_MODE (dst);
524   dst_size = GET_MODE_BITSIZE (GET_MODE (dst));
525
526   src = adjust_operand (src, &start);
527   src_mode = GET_MODE (src);
528   src_size = GET_MODE_BITSIZE (GET_MODE (src));
529
530   if (start > 0)
531     {
532       s = gen_reg_rtx (src_mode);
533       switch (src_mode)
534         {
535         case SImode:
536           emit_insn (gen_ashlsi3 (s, src, GEN_INT (start)));
537           break;
538         case DImode:
539           emit_insn (gen_ashldi3 (s, src, GEN_INT (start)));
540           break;
541         case TImode:
542           emit_insn (gen_ashlti3 (s, src, GEN_INT (start)));
543           break;
544         default:
545           abort ();
546         }
547       src = s;
548     }
549
550   if (width < src_size)
551     {
552       rtx pat;
553       int icode;
554       switch (src_mode)
555         {
556         case SImode:
557           icode = unsignedp ? CODE_FOR_lshrsi3 : CODE_FOR_ashrsi3;
558           break;
559         case DImode:
560           icode = unsignedp ? CODE_FOR_lshrdi3 : CODE_FOR_ashrdi3;
561           break;
562         case TImode:
563           icode = unsignedp ? CODE_FOR_lshrti3 : CODE_FOR_ashrti3;
564           break;
565         default:
566           abort ();
567         }
568       s = gen_reg_rtx (src_mode);
569       pat = GEN_FCN (icode) (s, src, GEN_INT (src_size - width));
570       emit_insn (pat);
571       src = s;
572     }
573
574   convert_move (dst, src, unsignedp);
575 }
576
577 void
578 spu_expand_insv (rtx ops[])
579 {
580   HOST_WIDE_INT width = INTVAL (ops[1]);
581   HOST_WIDE_INT start = INTVAL (ops[2]);
582   HOST_WIDE_INT maskbits;
583   enum machine_mode dst_mode, src_mode;
584   rtx dst = ops[0], src = ops[3];
585   int dst_size, src_size;
586   rtx mask;
587   rtx shift_reg;
588   int shift;
589
590
591   if (GET_CODE (ops[0]) == MEM)
592     dst = gen_reg_rtx (TImode);
593   else
594     dst = adjust_operand (dst, &start);
595   dst_mode = GET_MODE (dst);
596   dst_size = GET_MODE_BITSIZE (GET_MODE (dst));
597
598   if (CONSTANT_P (src))
599     {
600       enum machine_mode m =
601         (width <= 32 ? SImode : width <= 64 ? DImode : TImode);
602       src = force_reg (m, convert_to_mode (m, src, 0));
603     }
604   src = adjust_operand (src, 0);
605   src_mode = GET_MODE (src);
606   src_size = GET_MODE_BITSIZE (GET_MODE (src));
607
608   mask = gen_reg_rtx (dst_mode);
609   shift_reg = gen_reg_rtx (dst_mode);
610   shift = dst_size - start - width;
611
612   /* It's not safe to use subreg here because the compiler assumes
613      that the SUBREG_REG is right justified in the SUBREG. */
614   convert_move (shift_reg, src, 1);
615
616   if (shift > 0)
617     {
618       switch (dst_mode)
619         {
620         case SImode:
621           emit_insn (gen_ashlsi3 (shift_reg, shift_reg, GEN_INT (shift)));
622           break;
623         case DImode:
624           emit_insn (gen_ashldi3 (shift_reg, shift_reg, GEN_INT (shift)));
625           break;
626         case TImode:
627           emit_insn (gen_ashlti3 (shift_reg, shift_reg, GEN_INT (shift)));
628           break;
629         default:
630           abort ();
631         }
632     }
633   else if (shift < 0)
634     abort ();
635
636   switch (dst_size)
637     {
638     case 32:
639       maskbits = (-1ll << (32 - width - start));
640       if (start)
641         maskbits += (1ll << (32 - start));
642       emit_move_insn (mask, GEN_INT (maskbits));
643       break;
644     case 64:
645       maskbits = (-1ll << (64 - width - start));
646       if (start)
647         maskbits += (1ll << (64 - start));
648       emit_move_insn (mask, GEN_INT (maskbits));
649       break;
650     case 128:
651       {
652         unsigned char arr[16];
653         int i = start / 8;
654         memset (arr, 0, sizeof (arr));
655         arr[i] = 0xff >> (start & 7);
656         for (i++; i <= (start + width - 1) / 8; i++)
657           arr[i] = 0xff;
658         arr[i - 1] &= 0xff << (7 - ((start + width - 1) & 7));
659         emit_move_insn (mask, array_to_constant (TImode, arr));
660       }
661       break;
662     default:
663       abort ();
664     }
665   if (GET_CODE (ops[0]) == MEM)
666     {
667       rtx aligned = gen_reg_rtx (SImode);
668       rtx low = gen_reg_rtx (SImode);
669       rtx addr = gen_reg_rtx (SImode);
670       rtx rotl = gen_reg_rtx (SImode);
671       rtx mask0 = gen_reg_rtx (TImode);
672       rtx mem;
673
674       emit_move_insn (addr, XEXP (ops[0], 0));
675       emit_insn (gen_andsi3 (aligned, addr, GEN_INT (-16)));
676       emit_insn (gen_andsi3 (low, addr, GEN_INT (15)));
677       emit_insn (gen_negsi2 (rotl, low));
678       emit_insn (gen_rotqby_ti (shift_reg, shift_reg, rotl));
679       emit_insn (gen_rotqmby_ti (mask0, mask, rotl));
680       mem = change_address (ops[0], TImode, aligned);
681       set_mem_alias_set (mem, 0);
682       emit_move_insn (dst, mem);
683       emit_insn (gen_selb (dst, dst, shift_reg, mask0));
684       emit_move_insn (mem, dst);
685       if (start + width > MEM_ALIGN (ops[0]))
686         {
687           rtx shl = gen_reg_rtx (SImode);
688           rtx mask1 = gen_reg_rtx (TImode);
689           rtx dst1 = gen_reg_rtx (TImode);
690           rtx mem1;
691           emit_insn (gen_subsi3 (shl, GEN_INT (16), low));
692           emit_insn (gen_shlqby_ti (mask1, mask, shl));
693           mem1 = adjust_address (mem, TImode, 16);
694           set_mem_alias_set (mem1, 0);
695           emit_move_insn (dst1, mem1);
696           emit_insn (gen_selb (dst1, dst1, shift_reg, mask1));
697           emit_move_insn (mem1, dst1);
698         }
699     }
700   else
701     emit_insn (gen_selb (dst, copy_rtx (dst), shift_reg, mask));
702 }
703
704
705 int
706 spu_expand_block_move (rtx ops[])
707 {
708   HOST_WIDE_INT bytes, align, offset;
709   rtx src, dst, sreg, dreg, target;
710   int i;
711   if (GET_CODE (ops[2]) != CONST_INT
712       || GET_CODE (ops[3]) != CONST_INT
713       || INTVAL (ops[2]) > (HOST_WIDE_INT) (MOVE_RATIO (optimize_insn_for_speed_p ()) * 8))
714     return 0;
715
716   bytes = INTVAL (ops[2]);
717   align = INTVAL (ops[3]);
718
719   if (bytes <= 0)
720     return 1;
721
722   dst = ops[0];
723   src = ops[1];
724
725   if (align == 16)
726     {
727       for (offset = 0; offset + 16 <= bytes; offset += 16)
728         {
729           dst = adjust_address (ops[0], V16QImode, offset);
730           src = adjust_address (ops[1], V16QImode, offset);
731           emit_move_insn (dst, src);
732         }
733       if (offset < bytes)
734         {
735           rtx mask;
736           unsigned char arr[16] = { 0 };
737           for (i = 0; i < bytes - offset; i++)
738             arr[i] = 0xff;
739           dst = adjust_address (ops[0], V16QImode, offset);
740           src = adjust_address (ops[1], V16QImode, offset);
741           mask = gen_reg_rtx (V16QImode);
742           sreg = gen_reg_rtx (V16QImode);
743           dreg = gen_reg_rtx (V16QImode);
744           target = gen_reg_rtx (V16QImode);
745           emit_move_insn (mask, array_to_constant (V16QImode, arr));
746           emit_move_insn (dreg, dst);
747           emit_move_insn (sreg, src);
748           emit_insn (gen_selb (target, dreg, sreg, mask));
749           emit_move_insn (dst, target);
750         }
751       return 1;
752     }
753   return 0;
754 }
755
756 enum spu_comp_code
757 { SPU_EQ, SPU_GT, SPU_GTU };
758
759 int spu_comp_icode[12][3] = {
760  {CODE_FOR_ceq_qi, CODE_FOR_cgt_qi, CODE_FOR_clgt_qi},
761  {CODE_FOR_ceq_hi, CODE_FOR_cgt_hi, CODE_FOR_clgt_hi},
762  {CODE_FOR_ceq_si, CODE_FOR_cgt_si, CODE_FOR_clgt_si},
763  {CODE_FOR_ceq_di, CODE_FOR_cgt_di, CODE_FOR_clgt_di},
764  {CODE_FOR_ceq_ti, CODE_FOR_cgt_ti, CODE_FOR_clgt_ti},
765  {CODE_FOR_ceq_sf, CODE_FOR_cgt_sf, 0},
766  {CODE_FOR_ceq_df, CODE_FOR_cgt_df, 0},
767  {CODE_FOR_ceq_v16qi, CODE_FOR_cgt_v16qi, CODE_FOR_clgt_v16qi},
768  {CODE_FOR_ceq_v8hi,  CODE_FOR_cgt_v8hi,  CODE_FOR_clgt_v8hi},
769  {CODE_FOR_ceq_v4si,  CODE_FOR_cgt_v4si,  CODE_FOR_clgt_v4si},
770  {CODE_FOR_ceq_v4sf,  CODE_FOR_cgt_v4sf, 0},
771  {CODE_FOR_ceq_v2df,  CODE_FOR_cgt_v2df, 0},
772 };
773
774 /* Generate a compare for CODE.  Return a brand-new rtx that represents
775    the result of the compare.   GCC can figure this out too if we don't
776    provide all variations of compares, but GCC always wants to use
777    WORD_MODE, we can generate better code in most cases if we do it
778    ourselves.  */
779 void
780 spu_emit_branch_or_set (int is_set, enum rtx_code code, rtx operands[])
781 {
782   int reverse_compare = 0;
783   int reverse_test = 0;
784   rtx compare_result, eq_result;
785   rtx comp_rtx, eq_rtx;
786   rtx target = operands[0];
787   enum machine_mode comp_mode;
788   enum machine_mode op_mode;
789   enum spu_comp_code scode, eq_code, ior_code;
790   int index;
791   int eq_test = 0;
792
793   /* When spu_compare_op1 is a CONST_INT change (X >= C) to (X > C-1),
794      and so on, to keep the constant in operand 1. */
795   if (GET_CODE (spu_compare_op1) == CONST_INT)
796     {
797       HOST_WIDE_INT val = INTVAL (spu_compare_op1) - 1;
798       if (trunc_int_for_mode (val, GET_MODE (spu_compare_op0)) == val)
799         switch (code)
800           {
801           case GE:
802             spu_compare_op1 = GEN_INT (val);
803             code = GT;
804             break;
805           case LT:
806             spu_compare_op1 = GEN_INT (val);
807             code = LE;
808             break;
809           case GEU:
810             spu_compare_op1 = GEN_INT (val);
811             code = GTU;
812             break;
813           case LTU:
814             spu_compare_op1 = GEN_INT (val);
815             code = LEU;
816             break;
817           default:
818             break;
819           }
820     }
821
822   comp_mode = SImode;
823   op_mode = GET_MODE (spu_compare_op0);
824
825   switch (code)
826     {
827     case GE:
828       scode = SPU_GT;
829       if (HONOR_NANS (op_mode))
830         {
831           reverse_compare = 0;
832           reverse_test = 0;
833           eq_test = 1;
834           eq_code = SPU_EQ;
835         }
836       else
837         {
838           reverse_compare = 1;
839           reverse_test = 1;
840         }
841       break;
842     case LE:
843       scode = SPU_GT;
844       if (HONOR_NANS (op_mode))
845         {
846           reverse_compare = 1;
847           reverse_test = 0;
848           eq_test = 1;
849           eq_code = SPU_EQ;
850         }
851       else
852         {
853           reverse_compare = 0;
854           reverse_test = 1;
855         }
856       break;
857     case LT:
858       reverse_compare = 1;
859       reverse_test = 0;
860       scode = SPU_GT;
861       break;
862     case GEU:
863       reverse_compare = 1;
864       reverse_test = 1;
865       scode = SPU_GTU;
866       break;
867     case LEU:
868       reverse_compare = 0;
869       reverse_test = 1;
870       scode = SPU_GTU;
871       break;
872     case LTU:
873       reverse_compare = 1;
874       reverse_test = 0;
875       scode = SPU_GTU;
876       break;
877     case NE:
878       reverse_compare = 0;
879       reverse_test = 1;
880       scode = SPU_EQ;
881       break;
882
883     case EQ:
884       scode = SPU_EQ;
885       break;
886     case GT:
887       scode = SPU_GT;
888       break;
889     case GTU:
890       scode = SPU_GTU;
891       break;
892     default:
893       scode = SPU_EQ;
894       break;
895     }
896
897   switch (op_mode)
898     {
899     case QImode:
900       index = 0;
901       comp_mode = QImode;
902       break;
903     case HImode:
904       index = 1;
905       comp_mode = HImode;
906       break;
907     case SImode:
908       index = 2;
909       break;
910     case DImode:
911       index = 3;
912       break;
913     case TImode:
914       index = 4;
915       break;
916     case SFmode:
917       index = 5;
918       break;
919     case DFmode:
920       index = 6;
921       break;
922     case V16QImode:
923       index = 7;
924       comp_mode = op_mode;
925       break;
926     case V8HImode:
927       index = 8;
928       comp_mode = op_mode;
929       break;
930     case V4SImode:
931       index = 9;
932       comp_mode = op_mode;
933       break;
934     case V4SFmode:
935       index = 10;
936       comp_mode = V4SImode;
937       break;
938     case V2DFmode:
939       index = 11;
940       comp_mode = V2DImode;
941       break;
942     case V2DImode:
943     default:
944       abort ();
945     }
946
947   if (GET_MODE (spu_compare_op1) == DFmode
948       && (scode != SPU_GT && scode != SPU_EQ))
949     abort ();
950
951   if (is_set == 0 && spu_compare_op1 == const0_rtx
952       && (GET_MODE (spu_compare_op0) == SImode
953           || GET_MODE (spu_compare_op0) == HImode) && scode == SPU_EQ)
954     {
955       /* Don't need to set a register with the result when we are 
956          comparing against zero and branching. */
957       reverse_test = !reverse_test;
958       compare_result = spu_compare_op0;
959     }
960   else
961     {
962       compare_result = gen_reg_rtx (comp_mode);
963
964       if (reverse_compare)
965         {
966           rtx t = spu_compare_op1;
967           spu_compare_op1 = spu_compare_op0;
968           spu_compare_op0 = t;
969         }
970
971       if (spu_comp_icode[index][scode] == 0)
972         abort ();
973
974       if (!(*insn_data[spu_comp_icode[index][scode]].operand[1].predicate)
975           (spu_compare_op0, op_mode))
976         spu_compare_op0 = force_reg (op_mode, spu_compare_op0);
977       if (!(*insn_data[spu_comp_icode[index][scode]].operand[2].predicate)
978           (spu_compare_op1, op_mode))
979         spu_compare_op1 = force_reg (op_mode, spu_compare_op1);
980       comp_rtx = GEN_FCN (spu_comp_icode[index][scode]) (compare_result,
981                                                          spu_compare_op0,
982                                                          spu_compare_op1);
983       if (comp_rtx == 0)
984         abort ();
985       emit_insn (comp_rtx);
986
987       if (eq_test)
988         {
989           eq_result = gen_reg_rtx (comp_mode);
990           eq_rtx = GEN_FCN (spu_comp_icode[index][eq_code]) (eq_result,
991                                                              spu_compare_op0,
992                                                              spu_compare_op1);
993           if (eq_rtx == 0)
994             abort ();
995           emit_insn (eq_rtx);
996           ior_code = ior_optab->handlers[(int)comp_mode].insn_code;
997           gcc_assert (ior_code != CODE_FOR_nothing);
998           emit_insn (GEN_FCN (ior_code)
999                      (compare_result, compare_result, eq_result));
1000         }
1001     }
1002
1003   if (is_set == 0)
1004     {
1005       rtx bcomp;
1006       rtx loc_ref;
1007
1008       /* We don't have branch on QI compare insns, so we convert the
1009          QI compare result to a HI result. */
1010       if (comp_mode == QImode)
1011         {
1012           rtx old_res = compare_result;
1013           compare_result = gen_reg_rtx (HImode);
1014           comp_mode = HImode;
1015           emit_insn (gen_extendqihi2 (compare_result, old_res));
1016         }
1017
1018       if (reverse_test)
1019         bcomp = gen_rtx_EQ (comp_mode, compare_result, const0_rtx);
1020       else
1021         bcomp = gen_rtx_NE (comp_mode, compare_result, const0_rtx);
1022
1023       loc_ref = gen_rtx_LABEL_REF (VOIDmode, target);
1024       emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx,
1025                                    gen_rtx_IF_THEN_ELSE (VOIDmode, bcomp,
1026                                                          loc_ref, pc_rtx)));
1027     }
1028   else if (is_set == 2)
1029     {
1030       int compare_size = GET_MODE_BITSIZE (comp_mode);
1031       int target_size = GET_MODE_BITSIZE (GET_MODE (target));
1032       enum machine_mode mode = mode_for_size (target_size, MODE_INT, 0);
1033       rtx select_mask;
1034       rtx op_t = operands[2];
1035       rtx op_f = operands[3];
1036
1037       /* The result of the comparison can be SI, HI or QI mode.  Create a
1038          mask based on that result. */
1039       if (target_size > compare_size)
1040         {
1041           select_mask = gen_reg_rtx (mode);
1042           emit_insn (gen_extend_compare (select_mask, compare_result));
1043         }
1044       else if (target_size < compare_size)
1045         select_mask =
1046           gen_rtx_SUBREG (mode, compare_result,
1047                           (compare_size - target_size) / BITS_PER_UNIT);
1048       else if (comp_mode != mode)
1049         select_mask = gen_rtx_SUBREG (mode, compare_result, 0);
1050       else
1051         select_mask = compare_result;
1052
1053       if (GET_MODE (target) != GET_MODE (op_t)
1054           || GET_MODE (target) != GET_MODE (op_f))
1055         abort ();
1056
1057       if (reverse_test)
1058         emit_insn (gen_selb (target, op_t, op_f, select_mask));
1059       else
1060         emit_insn (gen_selb (target, op_f, op_t, select_mask));
1061     }
1062   else
1063     {
1064       if (reverse_test)
1065         emit_insn (gen_rtx_SET (VOIDmode, compare_result,
1066                                 gen_rtx_NOT (comp_mode, compare_result)));
1067       if (GET_MODE (target) == SImode && GET_MODE (compare_result) == HImode)
1068         emit_insn (gen_extendhisi2 (target, compare_result));
1069       else if (GET_MODE (target) == SImode
1070                && GET_MODE (compare_result) == QImode)
1071         emit_insn (gen_extend_compare (target, compare_result));
1072       else
1073         emit_move_insn (target, compare_result);
1074     }
1075 }
1076
1077 HOST_WIDE_INT
1078 const_double_to_hwint (rtx x)
1079 {
1080   HOST_WIDE_INT val;
1081   REAL_VALUE_TYPE rv;
1082   if (GET_MODE (x) == SFmode)
1083     {
1084       REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
1085       REAL_VALUE_TO_TARGET_SINGLE (rv, val);
1086     }
1087   else if (GET_MODE (x) == DFmode)
1088     {
1089       long l[2];
1090       REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
1091       REAL_VALUE_TO_TARGET_DOUBLE (rv, l);
1092       val = l[0];
1093       val = (val << 32) | (l[1] & 0xffffffff);
1094     }
1095   else
1096     abort ();
1097   return val;
1098 }
1099
1100 rtx
1101 hwint_to_const_double (enum machine_mode mode, HOST_WIDE_INT v)
1102 {
1103   long tv[2];
1104   REAL_VALUE_TYPE rv;
1105   gcc_assert (mode == SFmode || mode == DFmode);
1106
1107   if (mode == SFmode)
1108     tv[0] = (v << 32) >> 32;
1109   else if (mode == DFmode)
1110     {
1111       tv[1] = (v << 32) >> 32;
1112       tv[0] = v >> 32;
1113     }
1114   real_from_target (&rv, tv, mode);
1115   return CONST_DOUBLE_FROM_REAL_VALUE (rv, mode);
1116 }
1117
1118 void
1119 print_operand_address (FILE * file, register rtx addr)
1120 {
1121   rtx reg;
1122   rtx offset;
1123
1124   if (GET_CODE (addr) == AND
1125       && GET_CODE (XEXP (addr, 1)) == CONST_INT
1126       && INTVAL (XEXP (addr, 1)) == -16)
1127     addr = XEXP (addr, 0);
1128
1129   switch (GET_CODE (addr))
1130     {
1131     case REG:
1132       fprintf (file, "0(%s)", reg_names[REGNO (addr)]);
1133       break;
1134
1135     case PLUS:
1136       reg = XEXP (addr, 0);
1137       offset = XEXP (addr, 1);
1138       if (GET_CODE (offset) == REG)
1139         {
1140           fprintf (file, "%s,%s", reg_names[REGNO (reg)],
1141                    reg_names[REGNO (offset)]);
1142         }
1143       else if (GET_CODE (offset) == CONST_INT)
1144         {
1145           fprintf (file, HOST_WIDE_INT_PRINT_DEC "(%s)",
1146                    INTVAL (offset), reg_names[REGNO (reg)]);
1147         }
1148       else
1149         abort ();
1150       break;
1151
1152     case CONST:
1153     case LABEL_REF:
1154     case SYMBOL_REF:
1155     case CONST_INT:
1156       output_addr_const (file, addr);
1157       break;
1158
1159     default:
1160       debug_rtx (addr);
1161       abort ();
1162     }
1163 }
1164
1165 void
1166 print_operand (FILE * file, rtx x, int code)
1167 {
1168   enum machine_mode mode = GET_MODE (x);
1169   HOST_WIDE_INT val;
1170   unsigned char arr[16];
1171   int xcode = GET_CODE (x);
1172   int i, info;
1173   if (GET_MODE (x) == VOIDmode)
1174     switch (code)
1175       {
1176       case 'L':                 /* 128 bits, signed */
1177       case 'm':                 /* 128 bits, signed */
1178       case 'T':                 /* 128 bits, signed */
1179       case 't':                 /* 128 bits, signed */
1180         mode = TImode;
1181         break;
1182       case 'K':                 /* 64 bits, signed */
1183       case 'k':                 /* 64 bits, signed */
1184       case 'D':                 /* 64 bits, signed */
1185       case 'd':                 /* 64 bits, signed */
1186         mode = DImode;
1187         break;
1188       case 'J':                 /* 32 bits, signed */
1189       case 'j':                 /* 32 bits, signed */
1190       case 's':                 /* 32 bits, signed */
1191       case 'S':                 /* 32 bits, signed */
1192         mode = SImode;
1193         break;
1194       }
1195   switch (code)
1196     {
1197
1198     case 'j':                   /* 32 bits, signed */
1199     case 'k':                   /* 64 bits, signed */
1200     case 'm':                   /* 128 bits, signed */
1201       if (xcode == CONST_INT
1202           || xcode == CONST_DOUBLE || xcode == CONST_VECTOR)
1203         {
1204           gcc_assert (logical_immediate_p (x, mode));
1205           constant_to_array (mode, x, arr);
1206           val = (arr[0] << 24) | (arr[1] << 16) | (arr[2] << 8) | arr[3];
1207           val = trunc_int_for_mode (val, SImode);
1208           switch (which_logical_immediate (val))
1209           {
1210           case SPU_ORI:
1211             break;
1212           case SPU_ORHI:
1213             fprintf (file, "h");
1214             break;
1215           case SPU_ORBI:
1216             fprintf (file, "b");
1217             break;
1218           default:
1219             gcc_unreachable();
1220           }
1221         }
1222       else
1223         gcc_unreachable();
1224       return;
1225
1226     case 'J':                   /* 32 bits, signed */
1227     case 'K':                   /* 64 bits, signed */
1228     case 'L':                   /* 128 bits, signed */
1229       if (xcode == CONST_INT
1230           || xcode == CONST_DOUBLE || xcode == CONST_VECTOR)
1231         {
1232           gcc_assert (logical_immediate_p (x, mode)
1233                       || iohl_immediate_p (x, mode));
1234           constant_to_array (mode, x, arr);
1235           val = (arr[0] << 24) | (arr[1] << 16) | (arr[2] << 8) | arr[3];
1236           val = trunc_int_for_mode (val, SImode);
1237           switch (which_logical_immediate (val))
1238           {
1239           case SPU_ORI:
1240           case SPU_IOHL:
1241             break;
1242           case SPU_ORHI:
1243             val = trunc_int_for_mode (val, HImode);
1244             break;
1245           case SPU_ORBI:
1246             val = trunc_int_for_mode (val, QImode);
1247             break;
1248           default:
1249             gcc_unreachable();
1250           }
1251           fprintf (file, HOST_WIDE_INT_PRINT_DEC, val);
1252         }
1253       else
1254         gcc_unreachable();
1255       return;
1256
1257     case 't':                   /* 128 bits, signed */
1258     case 'd':                   /* 64 bits, signed */
1259     case 's':                   /* 32 bits, signed */
1260       if (CONSTANT_P (x))
1261         {
1262           enum immediate_class c = classify_immediate (x, mode);
1263           switch (c)
1264             {
1265             case IC_IL1:
1266               constant_to_array (mode, x, arr);
1267               val = (arr[0] << 24) | (arr[1] << 16) | (arr[2] << 8) | arr[3];
1268               val = trunc_int_for_mode (val, SImode);
1269               switch (which_immediate_load (val))
1270                 {
1271                 case SPU_IL:
1272                   break;
1273                 case SPU_ILA:
1274                   fprintf (file, "a");
1275                   break;
1276                 case SPU_ILH:
1277                   fprintf (file, "h");
1278                   break;
1279                 case SPU_ILHU:
1280                   fprintf (file, "hu");
1281                   break;
1282                 default:
1283                   gcc_unreachable ();
1284                 }
1285               break;
1286             case IC_CPAT:
1287               constant_to_array (mode, x, arr);
1288               cpat_info (arr, GET_MODE_SIZE (mode), &info, 0);
1289               if (info == 1)
1290                 fprintf (file, "b");
1291               else if (info == 2)
1292                 fprintf (file, "h");
1293               else if (info == 4)
1294                 fprintf (file, "w");
1295               else if (info == 8)
1296                 fprintf (file, "d");
1297               break;
1298             case IC_IL1s:
1299               if (xcode == CONST_VECTOR)
1300                 {
1301                   x = CONST_VECTOR_ELT (x, 0);
1302                   xcode = GET_CODE (x);
1303                 }
1304               if (xcode == SYMBOL_REF || xcode == LABEL_REF || xcode == CONST)
1305                 fprintf (file, "a");
1306               else if (xcode == HIGH)
1307                 fprintf (file, "hu");
1308               break;
1309             case IC_FSMBI:
1310             case IC_FSMBI2:
1311             case IC_IL2:
1312             case IC_IL2s:
1313             case IC_POOL:
1314               abort ();
1315             }
1316         }
1317       else
1318         gcc_unreachable ();
1319       return;
1320
1321     case 'T':                   /* 128 bits, signed */
1322     case 'D':                   /* 64 bits, signed */
1323     case 'S':                   /* 32 bits, signed */
1324       if (CONSTANT_P (x))
1325         {
1326           enum immediate_class c = classify_immediate (x, mode);
1327           switch (c)
1328             {
1329             case IC_IL1:
1330               constant_to_array (mode, x, arr);
1331               val = (arr[0] << 24) | (arr[1] << 16) | (arr[2] << 8) | arr[3];
1332               val = trunc_int_for_mode (val, SImode);
1333               switch (which_immediate_load (val))
1334                 {
1335                 case SPU_IL:
1336                 case SPU_ILA:
1337                   break;
1338                 case SPU_ILH:
1339                 case SPU_ILHU:
1340                   val = trunc_int_for_mode (((arr[0] << 8) | arr[1]), HImode);
1341                   break;
1342                 default:
1343                   gcc_unreachable ();
1344                 }
1345               fprintf (file, HOST_WIDE_INT_PRINT_DEC, val);
1346               break;
1347             case IC_FSMBI:
1348               constant_to_array (mode, x, arr);
1349               val = 0;
1350               for (i = 0; i < 16; i++)
1351                 {
1352                   val <<= 1;
1353                   val |= arr[i] & 1;
1354                 }
1355               print_operand (file, GEN_INT (val), 0);
1356               break;
1357             case IC_CPAT:
1358               constant_to_array (mode, x, arr);
1359               cpat_info (arr, GET_MODE_SIZE (mode), 0, &info);
1360               fprintf (file, HOST_WIDE_INT_PRINT_DEC, (HOST_WIDE_INT)info);
1361               break;
1362             case IC_IL1s:
1363               if (xcode == HIGH)
1364                 x = XEXP (x, 0);
1365               if (GET_CODE (x) == CONST_VECTOR)
1366                 x = CONST_VECTOR_ELT (x, 0);
1367               output_addr_const (file, x);
1368               if (xcode == HIGH)
1369                 fprintf (file, "@h");
1370               break;
1371             case IC_IL2:
1372             case IC_IL2s:
1373             case IC_FSMBI2:
1374             case IC_POOL:
1375               abort ();
1376             }
1377         }
1378       else
1379         gcc_unreachable ();
1380       return;
1381
1382     case 'C':
1383       if (xcode == CONST_INT)
1384         {
1385           /* Only 4 least significant bits are relevant for generate
1386              control word instructions. */
1387           fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x) & 15);
1388           return;
1389         }
1390       break;
1391
1392     case 'M':                   /* print code for c*d */
1393       if (GET_CODE (x) == CONST_INT)
1394         switch (INTVAL (x))
1395           {
1396           case 1:
1397             fprintf (file, "b");
1398             break;
1399           case 2:
1400             fprintf (file, "h");
1401             break;
1402           case 4:
1403             fprintf (file, "w");
1404             break;
1405           case 8:
1406             fprintf (file, "d");
1407             break;
1408           default:
1409             gcc_unreachable();
1410           }
1411       else
1412         gcc_unreachable();
1413       return;
1414
1415     case 'N':                   /* Negate the operand */
1416       if (xcode == CONST_INT)
1417         fprintf (file, HOST_WIDE_INT_PRINT_DEC, -INTVAL (x));
1418       else if (xcode == CONST_VECTOR)
1419         fprintf (file, HOST_WIDE_INT_PRINT_DEC,
1420                  -INTVAL (CONST_VECTOR_ELT (x, 0)));
1421       return;
1422
1423     case 'I':                   /* enable/disable interrupts */
1424       if (xcode == CONST_INT)
1425         fprintf (file, "%s",  INTVAL (x) == 0 ? "d" : "e");
1426       return;
1427
1428     case 'b':                   /* branch modifiers */
1429       if (xcode == REG)
1430         fprintf (file, "%s", GET_MODE (x) == HImode ? "h" : "");
1431       else if (COMPARISON_P (x))
1432         fprintf (file, "%s", xcode == NE ? "n" : "");
1433       return;
1434
1435     case 'i':                   /* indirect call */
1436       if (xcode == MEM)
1437         {
1438           if (GET_CODE (XEXP (x, 0)) == REG)
1439             /* Used in indirect function calls. */
1440             fprintf (file, "%s", reg_names[REGNO (XEXP (x, 0))]);
1441           else
1442             output_address (XEXP (x, 0));
1443         }
1444       return;
1445
1446     case 'p':                   /* load/store */
1447       if (xcode == MEM)
1448         {
1449           x = XEXP (x, 0);
1450           xcode = GET_CODE (x);
1451         }
1452       if (xcode == AND)
1453         {
1454           x = XEXP (x, 0);
1455           xcode = GET_CODE (x);
1456         }
1457       if (xcode == REG)
1458         fprintf (file, "d");
1459       else if (xcode == CONST_INT)
1460         fprintf (file, "a");
1461       else if (xcode == CONST || xcode == SYMBOL_REF || xcode == LABEL_REF)
1462         fprintf (file, "r");
1463       else if (xcode == PLUS || xcode == LO_SUM)
1464         {
1465           if (GET_CODE (XEXP (x, 1)) == REG)
1466             fprintf (file, "x");
1467           else
1468             fprintf (file, "d");
1469         }
1470       return;
1471
1472     case 'e':
1473       val = xcode == CONST_INT ? INTVAL (x) : INTVAL (CONST_VECTOR_ELT (x, 0));
1474       val &= 0x7;
1475       output_addr_const (file, GEN_INT (val));
1476       return;
1477
1478     case 'f':
1479       val = xcode == CONST_INT ? INTVAL (x) : INTVAL (CONST_VECTOR_ELT (x, 0));
1480       val &= 0x1f;
1481       output_addr_const (file, GEN_INT (val));
1482       return;
1483
1484     case 'g':
1485       val = xcode == CONST_INT ? INTVAL (x) : INTVAL (CONST_VECTOR_ELT (x, 0));
1486       val &= 0x3f;
1487       output_addr_const (file, GEN_INT (val));
1488       return;
1489
1490     case 'h':
1491       val = xcode == CONST_INT ? INTVAL (x) : INTVAL (CONST_VECTOR_ELT (x, 0));
1492       val = (val >> 3) & 0x1f;
1493       output_addr_const (file, GEN_INT (val));
1494       return;
1495
1496     case 'E':
1497       val = xcode == CONST_INT ? INTVAL (x) : INTVAL (CONST_VECTOR_ELT (x, 0));
1498       val = -val;
1499       val &= 0x7;
1500       output_addr_const (file, GEN_INT (val));
1501       return;
1502
1503     case 'F':
1504       val = xcode == CONST_INT ? INTVAL (x) : INTVAL (CONST_VECTOR_ELT (x, 0));
1505       val = -val;
1506       val &= 0x1f;
1507       output_addr_const (file, GEN_INT (val));
1508       return;
1509
1510     case 'G':
1511       val = xcode == CONST_INT ? INTVAL (x) : INTVAL (CONST_VECTOR_ELT (x, 0));
1512       val = -val;
1513       val &= 0x3f;
1514       output_addr_const (file, GEN_INT (val));
1515       return;
1516
1517     case 'H':
1518       val = xcode == CONST_INT ? INTVAL (x) : INTVAL (CONST_VECTOR_ELT (x, 0));
1519       val = -(val & -8ll);
1520       val = (val >> 3) & 0x1f;
1521       output_addr_const (file, GEN_INT (val));
1522       return;
1523
1524     case 0:
1525       if (xcode == REG)
1526         fprintf (file, "%s", reg_names[REGNO (x)]);
1527       else if (xcode == MEM)
1528         output_address (XEXP (x, 0));
1529       else if (xcode == CONST_VECTOR)
1530         print_operand (file, CONST_VECTOR_ELT (x, 0), 0);
1531       else
1532         output_addr_const (file, x);
1533       return;
1534
1535       /* unused letters
1536                       o qr  uvw yz
1537         AB            OPQR  UVWXYZ */
1538     default:
1539       output_operand_lossage ("invalid %%xn code");
1540     }
1541   gcc_unreachable ();
1542 }
1543
1544 extern char call_used_regs[];
1545
1546 /* For PIC mode we've reserved PIC_OFFSET_TABLE_REGNUM, which is a
1547    caller saved register.  For leaf functions it is more efficient to
1548    use a volatile register because we won't need to save and restore the
1549    pic register.  This routine is only valid after register allocation
1550    is completed, so we can pick an unused register.  */
1551 static rtx
1552 get_pic_reg (void)
1553 {
1554   rtx pic_reg = pic_offset_table_rtx;
1555   if (!reload_completed && !reload_in_progress)
1556     abort ();
1557   return pic_reg;
1558 }
1559
1560 /* Split constant addresses to handle cases that are too large. 
1561    Add in the pic register when in PIC mode.
1562    Split immediates that require more than 1 instruction. */
1563 int
1564 spu_split_immediate (rtx * ops)
1565 {
1566   enum machine_mode mode = GET_MODE (ops[0]);
1567   enum immediate_class c = classify_immediate (ops[1], mode);
1568
1569   switch (c)
1570     {
1571     case IC_IL2:
1572       {
1573         unsigned char arrhi[16];
1574         unsigned char arrlo[16];
1575         rtx to, temp, hi, lo;
1576         int i;
1577         enum machine_mode imode = mode;
1578         /* We need to do reals as ints because the constant used in the
1579            IOR might not be a legitimate real constant. */
1580         imode = int_mode_for_mode (mode);
1581         constant_to_array (mode, ops[1], arrhi);
1582         if (imode != mode)
1583           to = simplify_gen_subreg (imode, ops[0], mode, 0);
1584         else
1585           to = ops[0];
1586         temp = !can_create_pseudo_p () ? to : gen_reg_rtx (imode);
1587         for (i = 0; i < 16; i += 4)
1588           {
1589             arrlo[i + 2] = arrhi[i + 2];
1590             arrlo[i + 3] = arrhi[i + 3];
1591             arrlo[i + 0] = arrlo[i + 1] = 0;
1592             arrhi[i + 2] = arrhi[i + 3] = 0;
1593           }
1594         hi = array_to_constant (imode, arrhi);
1595         lo = array_to_constant (imode, arrlo);
1596         emit_move_insn (temp, hi);
1597         emit_insn (gen_rtx_SET
1598                    (VOIDmode, to, gen_rtx_IOR (imode, temp, lo)));
1599         return 1;
1600       }
1601     case IC_FSMBI2:
1602       {
1603         unsigned char arr_fsmbi[16];
1604         unsigned char arr_andbi[16];
1605         rtx to, reg_fsmbi, reg_and;
1606         int i;
1607         enum machine_mode imode = mode;
1608         /* We need to do reals as ints because the constant used in the
1609          * AND might not be a legitimate real constant. */
1610         imode = int_mode_for_mode (mode);
1611         constant_to_array (mode, ops[1], arr_fsmbi);
1612         if (imode != mode)
1613           to = simplify_gen_subreg(imode, ops[0], GET_MODE (ops[0]), 0);
1614         else
1615           to = ops[0];
1616         for (i = 0; i < 16; i++)
1617           if (arr_fsmbi[i] != 0)
1618             {
1619               arr_andbi[0] = arr_fsmbi[i];
1620               arr_fsmbi[i] = 0xff;
1621             }
1622         for (i = 1; i < 16; i++)
1623           arr_andbi[i] = arr_andbi[0];
1624         reg_fsmbi = array_to_constant (imode, arr_fsmbi);
1625         reg_and = array_to_constant (imode, arr_andbi);
1626         emit_move_insn (to, reg_fsmbi);
1627         emit_insn (gen_rtx_SET
1628                    (VOIDmode, to, gen_rtx_AND (imode, to, reg_and)));
1629         return 1;
1630       }
1631     case IC_POOL:
1632       if (reload_in_progress || reload_completed)
1633         {
1634           rtx mem = force_const_mem (mode, ops[1]);
1635           if (TARGET_LARGE_MEM)
1636             {
1637               rtx addr = gen_rtx_REG (Pmode, REGNO (ops[0]));
1638               emit_move_insn (addr, XEXP (mem, 0));
1639               mem = replace_equiv_address (mem, addr);
1640             }
1641           emit_move_insn (ops[0], mem);
1642           return 1;
1643         }
1644       break;
1645     case IC_IL1s:
1646     case IC_IL2s:
1647       if (reload_completed && GET_CODE (ops[1]) != HIGH)
1648         {
1649           if (c == IC_IL2s)
1650             {
1651               emit_move_insn (ops[0], gen_rtx_HIGH (mode, ops[1]));
1652               emit_move_insn (ops[0], gen_rtx_LO_SUM (mode, ops[0], ops[1]));
1653             }
1654           else if (flag_pic)
1655             emit_insn (gen_pic (ops[0], ops[1]));
1656           if (flag_pic)
1657             {
1658               rtx pic_reg = get_pic_reg ();
1659               emit_insn (gen_addsi3 (ops[0], ops[0], pic_reg));
1660               crtl->uses_pic_offset_table = 1;
1661             }
1662           return flag_pic || c == IC_IL2s;
1663         }
1664       break;
1665     case IC_IL1:
1666     case IC_FSMBI:
1667     case IC_CPAT:
1668       break;
1669     }
1670   return 0;
1671 }
1672
1673 /* SAVING is TRUE when we are generating the actual load and store
1674    instructions for REGNO.  When determining the size of the stack
1675    needed for saving register we must allocate enough space for the
1676    worst case, because we don't always have the information early enough
1677    to not allocate it.  But we can at least eliminate the actual loads
1678    and stores during the prologue/epilogue.  */
1679 static int
1680 need_to_save_reg (int regno, int saving)
1681 {
1682   if (df_regs_ever_live_p (regno) && !call_used_regs[regno])
1683     return 1;
1684   if (flag_pic
1685       && regno == PIC_OFFSET_TABLE_REGNUM
1686       && (!saving || crtl->uses_pic_offset_table)
1687       && (!saving
1688           || !current_function_is_leaf || df_regs_ever_live_p (LAST_ARG_REGNUM)))
1689     return 1;
1690   return 0;
1691 }
1692
1693 /* This function is only correct starting with local register
1694    allocation */
1695 int
1696 spu_saved_regs_size (void)
1697 {
1698   int reg_save_size = 0;
1699   int regno;
1700
1701   for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; --regno)
1702     if (need_to_save_reg (regno, 0))
1703       reg_save_size += 0x10;
1704   return reg_save_size;
1705 }
1706
1707 static rtx
1708 frame_emit_store (int regno, rtx addr, HOST_WIDE_INT offset)
1709 {
1710   rtx reg = gen_rtx_REG (V4SImode, regno);
1711   rtx mem =
1712     gen_frame_mem (V4SImode, gen_rtx_PLUS (Pmode, addr, GEN_INT (offset)));
1713   return emit_insn (gen_movv4si (mem, reg));
1714 }
1715
1716 static rtx
1717 frame_emit_load (int regno, rtx addr, HOST_WIDE_INT offset)
1718 {
1719   rtx reg = gen_rtx_REG (V4SImode, regno);
1720   rtx mem =
1721     gen_frame_mem (V4SImode, gen_rtx_PLUS (Pmode, addr, GEN_INT (offset)));
1722   return emit_insn (gen_movv4si (reg, mem));
1723 }
1724
1725 /* This happens after reload, so we need to expand it.  */
1726 static rtx
1727 frame_emit_add_imm (rtx dst, rtx src, HOST_WIDE_INT imm, rtx scratch)
1728 {
1729   rtx insn;
1730   if (satisfies_constraint_K (GEN_INT (imm)))
1731     {
1732       insn = emit_insn (gen_addsi3 (dst, src, GEN_INT (imm)));
1733     }
1734   else
1735     {
1736       emit_insn (gen_movsi (scratch, gen_int_mode (imm, SImode)));
1737       insn = emit_insn (gen_addsi3 (dst, src, scratch));
1738       if (REGNO (src) == REGNO (scratch))
1739         abort ();
1740     }
1741   return insn;
1742 }
1743
1744 /* Return nonzero if this function is known to have a null epilogue.  */
1745
1746 int
1747 direct_return (void)
1748 {
1749   if (reload_completed)
1750     {
1751       if (cfun->static_chain_decl == 0
1752           && (spu_saved_regs_size ()
1753               + get_frame_size ()
1754               + crtl->outgoing_args_size
1755               + crtl->args.pretend_args_size == 0)
1756           && current_function_is_leaf)
1757         return 1;
1758     }
1759   return 0;
1760 }
1761
1762 /*
1763    The stack frame looks like this:
1764          +-------------+
1765          |  incoming   | 
1766          |    args     | 
1767    AP -> +-------------+
1768          | $lr save    |
1769          +-------------+
1770  prev SP | back chain  | 
1771          +-------------+
1772          |  var args   | 
1773          |  reg save   | crtl->args.pretend_args_size bytes
1774          +-------------+
1775          |    ...      | 
1776          | saved regs  | spu_saved_regs_size() bytes
1777    FP -> +-------------+
1778          |    ...      | 
1779          |   vars      | get_frame_size()  bytes
1780   HFP -> +-------------+
1781          |    ...      | 
1782          |  outgoing   | 
1783          |    args     | crtl->outgoing_args_size bytes
1784          +-------------+
1785          | $lr of next |
1786          |   frame     | 
1787          +-------------+
1788          | back chain  | 
1789    SP -> +-------------+
1790
1791 */
1792 void
1793 spu_expand_prologue (void)
1794 {
1795   HOST_WIDE_INT size = get_frame_size (), offset, regno;
1796   HOST_WIDE_INT total_size;
1797   HOST_WIDE_INT saved_regs_size;
1798   rtx sp_reg = gen_rtx_REG (Pmode, STACK_POINTER_REGNUM);
1799   rtx scratch_reg_0, scratch_reg_1;
1800   rtx insn, real;
1801
1802   /* A NOTE_INSN_DELETED is supposed to be at the start and end of
1803      the "toplevel" insn chain.  */
1804   emit_note (NOTE_INSN_DELETED);
1805
1806   if (flag_pic && optimize == 0)
1807     crtl->uses_pic_offset_table = 1;
1808
1809   if (spu_naked_function_p (current_function_decl))
1810     return;
1811
1812   scratch_reg_0 = gen_rtx_REG (SImode, LAST_ARG_REGNUM + 1);
1813   scratch_reg_1 = gen_rtx_REG (SImode, LAST_ARG_REGNUM + 2);
1814
1815   saved_regs_size = spu_saved_regs_size ();
1816   total_size = size + saved_regs_size
1817     + crtl->outgoing_args_size
1818     + crtl->args.pretend_args_size;
1819
1820   if (!current_function_is_leaf
1821       || cfun->calls_alloca || total_size > 0)
1822     total_size += STACK_POINTER_OFFSET;
1823
1824   /* Save this first because code after this might use the link
1825      register as a scratch register. */
1826   if (!current_function_is_leaf)
1827     {
1828       insn = frame_emit_store (LINK_REGISTER_REGNUM, sp_reg, 16);
1829       RTX_FRAME_RELATED_P (insn) = 1;
1830     }
1831
1832   if (total_size > 0)
1833     {
1834       offset = -crtl->args.pretend_args_size;
1835       for (regno = 0; regno < FIRST_PSEUDO_REGISTER; ++regno)
1836         if (need_to_save_reg (regno, 1))
1837           {
1838             offset -= 16;
1839             insn = frame_emit_store (regno, sp_reg, offset);
1840             RTX_FRAME_RELATED_P (insn) = 1;
1841           }
1842     }
1843
1844   if (flag_pic && crtl->uses_pic_offset_table)
1845     {
1846       rtx pic_reg = get_pic_reg ();
1847       insn = emit_insn (gen_load_pic_offset (pic_reg, scratch_reg_0));
1848       insn = emit_insn (gen_subsi3 (pic_reg, pic_reg, scratch_reg_0));
1849     }
1850
1851   if (total_size > 0)
1852     {
1853       if (flag_stack_check)
1854         {
1855           /* We compare against total_size-1 because
1856              ($sp >= total_size) <=> ($sp > total_size-1) */
1857           rtx scratch_v4si = gen_rtx_REG (V4SImode, REGNO (scratch_reg_0));
1858           rtx sp_v4si = gen_rtx_REG (V4SImode, STACK_POINTER_REGNUM);
1859           rtx size_v4si = spu_const (V4SImode, total_size - 1);
1860           if (!satisfies_constraint_K (GEN_INT (total_size - 1)))
1861             {
1862               emit_move_insn (scratch_v4si, size_v4si);
1863               size_v4si = scratch_v4si;
1864             }
1865           emit_insn (gen_cgt_v4si (scratch_v4si, sp_v4si, size_v4si));
1866           emit_insn (gen_vec_extractv4si
1867                      (scratch_reg_0, scratch_v4si, GEN_INT (1)));
1868           emit_insn (gen_spu_heq (scratch_reg_0, GEN_INT (0)));
1869         }
1870
1871       /* Adjust the stack pointer, and make sure scratch_reg_0 contains
1872          the value of the previous $sp because we save it as the back
1873          chain. */
1874       if (total_size <= 2000)
1875         {
1876           /* In this case we save the back chain first. */
1877           insn = frame_emit_store (STACK_POINTER_REGNUM, sp_reg, -total_size);
1878           insn =
1879             frame_emit_add_imm (sp_reg, sp_reg, -total_size, scratch_reg_0);
1880         }
1881       else if (satisfies_constraint_K (GEN_INT (-total_size)))
1882         {
1883           insn = emit_move_insn (scratch_reg_0, sp_reg);
1884           insn =
1885             emit_insn (gen_addsi3 (sp_reg, sp_reg, GEN_INT (-total_size)));
1886         }
1887       else
1888         {
1889           insn = emit_move_insn (scratch_reg_0, sp_reg);
1890           insn =
1891             frame_emit_add_imm (sp_reg, sp_reg, -total_size, scratch_reg_1);
1892         }
1893       RTX_FRAME_RELATED_P (insn) = 1;
1894       real = gen_addsi3 (sp_reg, sp_reg, GEN_INT (-total_size));
1895       REG_NOTES (insn) =
1896         gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, real, REG_NOTES (insn));
1897
1898       if (total_size > 2000)
1899         {
1900           /* Save the back chain ptr */
1901           insn = frame_emit_store (REGNO (scratch_reg_0), sp_reg, 0);
1902         }
1903
1904       if (frame_pointer_needed)
1905         {
1906           rtx fp_reg = gen_rtx_REG (Pmode, HARD_FRAME_POINTER_REGNUM);
1907           HOST_WIDE_INT fp_offset = STACK_POINTER_OFFSET
1908             + crtl->outgoing_args_size;
1909           /* Set the new frame_pointer */
1910           insn = frame_emit_add_imm (fp_reg, sp_reg, fp_offset, scratch_reg_0);
1911           RTX_FRAME_RELATED_P (insn) = 1;
1912           real = gen_addsi3 (fp_reg, sp_reg, GEN_INT (fp_offset));
1913           REG_NOTES (insn) = 
1914             gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
1915                                real, REG_NOTES (insn));
1916           REGNO_POINTER_ALIGN (HARD_FRAME_POINTER_REGNUM) = STACK_BOUNDARY;
1917         }
1918     }
1919
1920   emit_note (NOTE_INSN_DELETED);
1921 }
1922
1923 void
1924 spu_expand_epilogue (bool sibcall_p)
1925 {
1926   int size = get_frame_size (), offset, regno;
1927   HOST_WIDE_INT saved_regs_size, total_size;
1928   rtx sp_reg = gen_rtx_REG (Pmode, STACK_POINTER_REGNUM);
1929   rtx jump, scratch_reg_0;
1930
1931   /* A NOTE_INSN_DELETED is supposed to be at the start and end of
1932      the "toplevel" insn chain.  */
1933   emit_note (NOTE_INSN_DELETED);
1934
1935   if (spu_naked_function_p (current_function_decl))
1936     return;
1937
1938   scratch_reg_0 = gen_rtx_REG (SImode, LAST_ARG_REGNUM + 1);
1939
1940   saved_regs_size = spu_saved_regs_size ();
1941   total_size = size + saved_regs_size
1942     + crtl->outgoing_args_size
1943     + crtl->args.pretend_args_size;
1944
1945   if (!current_function_is_leaf
1946       || cfun->calls_alloca || total_size > 0)
1947     total_size += STACK_POINTER_OFFSET;
1948
1949   if (total_size > 0)
1950     {
1951       if (cfun->calls_alloca)
1952         frame_emit_load (STACK_POINTER_REGNUM, sp_reg, 0);
1953       else
1954         frame_emit_add_imm (sp_reg, sp_reg, total_size, scratch_reg_0);
1955
1956
1957       if (saved_regs_size > 0)
1958         {
1959           offset = -crtl->args.pretend_args_size;
1960           for (regno = 0; regno < FIRST_PSEUDO_REGISTER; ++regno)
1961             if (need_to_save_reg (regno, 1))
1962               {
1963                 offset -= 0x10;
1964                 frame_emit_load (regno, sp_reg, offset);
1965               }
1966         }
1967     }
1968
1969   if (!current_function_is_leaf)
1970     frame_emit_load (LINK_REGISTER_REGNUM, sp_reg, 16);
1971
1972   if (!sibcall_p)
1973     {
1974       emit_use (gen_rtx_REG (SImode, LINK_REGISTER_REGNUM));
1975       jump = emit_jump_insn (gen__return ());
1976       emit_barrier_after (jump);
1977     }
1978
1979   emit_note (NOTE_INSN_DELETED);
1980 }
1981
1982 rtx
1983 spu_return_addr (int count, rtx frame ATTRIBUTE_UNUSED)
1984 {
1985   if (count != 0)
1986     return 0;
1987   /* This is inefficient because it ends up copying to a save-register
1988      which then gets saved even though $lr has already been saved.  But
1989      it does generate better code for leaf functions and we don't need
1990      to use RETURN_ADDRESS_POINTER_REGNUM to get it working.  It's only
1991      used for __builtin_return_address anyway, so maybe we don't care if
1992      it's inefficient. */
1993   return get_hard_reg_initial_val (Pmode, LINK_REGISTER_REGNUM);
1994 }
1995 \f
1996
1997 /* Given VAL, generate a constant appropriate for MODE.
1998    If MODE is a vector mode, every element will be VAL.
1999    For TImode, VAL will be zero extended to 128 bits. */
2000 rtx
2001 spu_const (enum machine_mode mode, HOST_WIDE_INT val)
2002 {
2003   rtx inner;
2004   rtvec v;
2005   int units, i;
2006
2007   gcc_assert (GET_MODE_CLASS (mode) == MODE_INT
2008               || GET_MODE_CLASS (mode) == MODE_FLOAT
2009               || GET_MODE_CLASS (mode) == MODE_VECTOR_INT
2010               || GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT);
2011
2012   if (GET_MODE_CLASS (mode) == MODE_INT)
2013     return immed_double_const (val, 0, mode);
2014
2015   /* val is the bit representation of the float */
2016   if (GET_MODE_CLASS (mode) == MODE_FLOAT)
2017     return hwint_to_const_double (mode, val);
2018
2019   if (GET_MODE_CLASS (mode) == MODE_VECTOR_INT)
2020     inner = immed_double_const (val, 0, GET_MODE_INNER (mode));
2021   else 
2022     inner = hwint_to_const_double (GET_MODE_INNER (mode), val);
2023
2024   units = GET_MODE_NUNITS (mode);
2025
2026   v = rtvec_alloc (units);
2027
2028   for (i = 0; i < units; ++i)
2029     RTVEC_ELT (v, i) = inner;
2030
2031   return gen_rtx_CONST_VECTOR (mode, v);
2032 }
2033
2034 /* Create a MODE vector constant from 4 ints. */
2035 rtx
2036 spu_const_from_ints(enum machine_mode mode, int a, int b, int c, int d)
2037 {
2038   unsigned char arr[16];
2039   arr[0] = (a >> 24) & 0xff;
2040   arr[1] = (a >> 16) & 0xff;
2041   arr[2] = (a >> 8) & 0xff;
2042   arr[3] = (a >> 0) & 0xff;
2043   arr[4] = (b >> 24) & 0xff;
2044   arr[5] = (b >> 16) & 0xff;
2045   arr[6] = (b >> 8) & 0xff;
2046   arr[7] = (b >> 0) & 0xff;
2047   arr[8] = (c >> 24) & 0xff;
2048   arr[9] = (c >> 16) & 0xff;
2049   arr[10] = (c >> 8) & 0xff;
2050   arr[11] = (c >> 0) & 0xff;
2051   arr[12] = (d >> 24) & 0xff;
2052   arr[13] = (d >> 16) & 0xff;
2053   arr[14] = (d >> 8) & 0xff;
2054   arr[15] = (d >> 0) & 0xff;
2055   return array_to_constant(mode, arr);
2056 }
2057 \f
2058 /* branch hint stuff */
2059
2060 /* An array of these is used to propagate hints to predecessor blocks. */
2061 struct spu_bb_info
2062 {
2063   rtx prop_jump; /* propagated from another block */
2064   int bb_index;  /* the original block. */
2065 };
2066 static struct spu_bb_info *spu_bb_info;
2067
2068 #define STOP_HINT_P(INSN) \
2069                 (GET_CODE(INSN) == CALL_INSN \
2070                  || INSN_CODE(INSN) == CODE_FOR_divmodsi4 \
2071                  || INSN_CODE(INSN) == CODE_FOR_udivmodsi4)
2072
2073 /* 1 when RTX is a hinted branch or its target.  We keep track of
2074    what has been hinted so the safe-hint code can test it easily.  */
2075 #define HINTED_P(RTX)                                           \
2076   (RTL_FLAG_CHECK3("HINTED_P", (RTX), CODE_LABEL, JUMP_INSN, CALL_INSN)->unchanging)
2077
2078 /* 1 when RTX is an insn that must be scheduled on an even boundary. */
2079 #define SCHED_ON_EVEN_P(RTX)                                            \
2080   (RTL_FLAG_CHECK2("SCHED_ON_EVEN_P", (RTX), JUMP_INSN, CALL_INSN)->in_struct)
2081
2082 /* Emit a nop for INSN such that the two will dual issue.  This assumes
2083    INSN is 8-byte aligned.  When INSN is inline asm we emit an lnop.
2084    We check for TImode to handle a MULTI1 insn which has dual issued its
2085    first instruction.  get_pipe returns -1 for MULTI0, inline asm, or
2086    ADDR_VEC insns. */
2087 static void
2088 emit_nop_for_insn (rtx insn)
2089 {
2090   int p;
2091   rtx new_insn;
2092   p = get_pipe (insn);
2093   if ((CALL_P (insn) || JUMP_P (insn)) && SCHED_ON_EVEN_P (insn))
2094     new_insn = emit_insn_after (gen_lnop (), insn);
2095   else if (p == 1 && GET_MODE (insn) == TImode)
2096     {
2097       new_insn = emit_insn_before (gen_nopn (GEN_INT (127)), insn);
2098       PUT_MODE (new_insn, TImode);
2099       PUT_MODE (insn, VOIDmode);
2100     }
2101   else
2102     new_insn = emit_insn_after (gen_lnop (), insn);
2103   recog_memoized (new_insn);
2104 }
2105
2106 /* Insert nops in basic blocks to meet dual issue alignment
2107    requirements.  Also make sure hbrp and hint instructions are at least
2108    one cycle apart, possibly inserting a nop.  */
2109 static void
2110 pad_bb(void)
2111 {
2112   rtx insn, next_insn, prev_insn, hbr_insn = 0;
2113   int length;
2114   int addr;
2115
2116   /* This sets up INSN_ADDRESSES. */
2117   shorten_branches (get_insns ());
2118
2119   /* Keep track of length added by nops. */
2120   length = 0;
2121
2122   prev_insn = 0;
2123   insn = get_insns ();
2124   if (!active_insn_p (insn))
2125     insn = next_active_insn (insn);
2126   for (; insn; insn = next_insn)
2127     {
2128       next_insn = next_active_insn (insn);
2129       if (INSN_CODE (insn) == CODE_FOR_iprefetch
2130           || INSN_CODE (insn) == CODE_FOR_hbr)
2131         {
2132           if (hbr_insn)
2133             {
2134               int a0 = INSN_ADDRESSES (INSN_UID (hbr_insn));
2135               int a1 = INSN_ADDRESSES (INSN_UID (insn));
2136               if ((a1 - a0 == 8 && GET_MODE (insn) != TImode)
2137                   || (a1 - a0 == 4))
2138                 {
2139                   prev_insn = emit_insn_before (gen_lnop (), insn);
2140                   PUT_MODE (prev_insn, GET_MODE (insn));
2141                   PUT_MODE (insn, TImode);
2142                   length += 4;
2143                 }
2144             }
2145           hbr_insn = insn;
2146         }
2147       if (INSN_CODE (insn) == CODE_FOR_blockage)
2148         {
2149           if (GET_MODE (insn) == TImode)
2150             PUT_MODE (next_insn, TImode);
2151           insn = next_insn;
2152           next_insn = next_active_insn (insn);
2153         }
2154       addr = INSN_ADDRESSES (INSN_UID (insn));
2155       if ((CALL_P (insn) || JUMP_P (insn)) && SCHED_ON_EVEN_P (insn))
2156         {
2157           if (((addr + length) & 7) != 0)
2158             {
2159               emit_nop_for_insn (prev_insn);
2160               length += 4;
2161             }
2162         }
2163       else if (GET_MODE (insn) == TImode
2164                && ((next_insn && GET_MODE (next_insn) != TImode)
2165                    || get_attr_type (insn) == TYPE_MULTI0)
2166                && ((addr + length) & 7) != 0)
2167         {
2168           /* prev_insn will always be set because the first insn is
2169              always 8-byte aligned. */
2170           emit_nop_for_insn (prev_insn);
2171           length += 4;
2172         }
2173       prev_insn = insn;
2174     }
2175 }
2176
2177 \f
2178 /* Routines for branch hints. */
2179
2180 static void
2181 spu_emit_branch_hint (rtx before, rtx branch, rtx target,
2182                       int distance, sbitmap blocks)
2183 {
2184   rtx branch_label = 0;
2185   rtx hint;
2186   rtx insn;
2187   rtx table;
2188
2189   if (before == 0 || branch == 0 || target == 0)
2190     return;
2191
2192   /* While scheduling we require hints to be no further than 600, so
2193      we need to enforce that here too */
2194   if (distance > 600)
2195     return;
2196
2197   /* If we have a Basic block note, emit it after the basic block note.  */
2198   if (NOTE_KIND (before) == NOTE_INSN_BASIC_BLOCK)
2199     before = NEXT_INSN (before);
2200
2201   branch_label = gen_label_rtx ();
2202   LABEL_NUSES (branch_label)++;
2203   LABEL_PRESERVE_P (branch_label) = 1;
2204   insn = emit_label_before (branch_label, branch);
2205   branch_label = gen_rtx_LABEL_REF (VOIDmode, branch_label);
2206   SET_BIT (blocks, BLOCK_FOR_INSN (branch)->index);
2207
2208   hint = emit_insn_before (gen_hbr (branch_label, target), before);
2209   recog_memoized (hint);
2210   HINTED_P (branch) = 1;
2211
2212   if (GET_CODE (target) == LABEL_REF)
2213     HINTED_P (XEXP (target, 0)) = 1;
2214   else if (tablejump_p (branch, 0, &table))
2215     {
2216       rtvec vec;
2217       int j;
2218       if (GET_CODE (PATTERN (table)) == ADDR_VEC)
2219         vec = XVEC (PATTERN (table), 0);
2220       else
2221         vec = XVEC (PATTERN (table), 1);
2222       for (j = GET_NUM_ELEM (vec) - 1; j >= 0; --j)
2223         HINTED_P (XEXP (RTVEC_ELT (vec, j), 0)) = 1;
2224     }
2225
2226   if (distance >= 588)
2227     {
2228       /* Make sure the hint isn't scheduled any earlier than this point,
2229          which could make it too far for the branch offest to fit */
2230       recog_memoized (emit_insn_before (gen_blockage (), hint));
2231     }
2232   else if (distance <= 8 * 4)
2233     {
2234       /* To guarantee at least 8 insns between the hint and branch we
2235          insert nops. */
2236       int d;
2237       for (d = distance; d < 8 * 4; d += 4)
2238         {
2239           insn =
2240             emit_insn_after (gen_nopn_nv (gen_rtx_REG (SImode, 127)), hint);
2241           recog_memoized (insn);
2242         }
2243
2244       /* Make sure any nops inserted aren't scheduled before the hint. */
2245       recog_memoized (emit_insn_after (gen_blockage (), hint));
2246
2247       /* Make sure any nops inserted aren't scheduled after the call. */
2248       if (CALL_P (branch) && distance < 8 * 4)
2249         recog_memoized (emit_insn_before (gen_blockage (), branch));
2250     }
2251 }
2252
2253 /* Returns 0 if we don't want a hint for this branch.  Otherwise return
2254    the rtx for the branch target. */
2255 static rtx
2256 get_branch_target (rtx branch)
2257 {
2258   if (GET_CODE (branch) == JUMP_INSN)
2259     {
2260       rtx set, src;
2261
2262       /* Return statements */
2263       if (GET_CODE (PATTERN (branch)) == RETURN)
2264         return gen_rtx_REG (SImode, LINK_REGISTER_REGNUM);
2265
2266       /* jump table */
2267       if (GET_CODE (PATTERN (branch)) == ADDR_VEC
2268           || GET_CODE (PATTERN (branch)) == ADDR_DIFF_VEC)
2269         return 0;
2270
2271       set = single_set (branch);
2272       src = SET_SRC (set);
2273       if (GET_CODE (SET_DEST (set)) != PC)
2274         abort ();
2275
2276       if (GET_CODE (src) == IF_THEN_ELSE)
2277         {
2278           rtx lab = 0;
2279           rtx note = find_reg_note (branch, REG_BR_PROB, 0);
2280           if (note)
2281             {
2282               /* If the more probable case is not a fall through, then
2283                  try a branch hint.  */
2284               HOST_WIDE_INT prob = INTVAL (XEXP (note, 0));
2285               if (prob > (REG_BR_PROB_BASE * 6 / 10)
2286                   && GET_CODE (XEXP (src, 1)) != PC)
2287                 lab = XEXP (src, 1);
2288               else if (prob < (REG_BR_PROB_BASE * 4 / 10)
2289                        && GET_CODE (XEXP (src, 2)) != PC)
2290                 lab = XEXP (src, 2);
2291             }
2292           if (lab)
2293             {
2294               if (GET_CODE (lab) == RETURN)
2295                 return gen_rtx_REG (SImode, LINK_REGISTER_REGNUM);
2296               return lab;
2297             }
2298           return 0;
2299         }
2300
2301       return src;
2302     }
2303   else if (GET_CODE (branch) == CALL_INSN)
2304     {
2305       rtx call;
2306       /* All of our call patterns are in a PARALLEL and the CALL is
2307          the first pattern in the PARALLEL. */
2308       if (GET_CODE (PATTERN (branch)) != PARALLEL)
2309         abort ();
2310       call = XVECEXP (PATTERN (branch), 0, 0);
2311       if (GET_CODE (call) == SET)
2312         call = SET_SRC (call);
2313       if (GET_CODE (call) != CALL)
2314         abort ();
2315       return XEXP (XEXP (call, 0), 0);
2316     }
2317   return 0;
2318 }
2319
2320 /* The special $hbr register is used to prevent the insn scheduler from
2321    moving hbr insns across instructions which invalidate them.  It
2322    should only be used in a clobber, and this function searches for
2323    insns which clobber it.  */
2324 static bool
2325 insn_clobbers_hbr (rtx insn)
2326 {
2327   if (INSN_P (insn)
2328       && GET_CODE (PATTERN (insn)) == PARALLEL)
2329     {
2330       rtx parallel = PATTERN (insn);
2331       rtx clobber;
2332       int j;
2333       for (j = XVECLEN (parallel, 0) - 1; j >= 0; j--)
2334         {
2335           clobber = XVECEXP (parallel, 0, j);
2336           if (GET_CODE (clobber) == CLOBBER
2337               && GET_CODE (XEXP (clobber, 0)) == REG
2338               && REGNO (XEXP (clobber, 0)) == HBR_REGNUM)
2339             return 1;
2340         }
2341     }
2342   return 0;
2343 }
2344
2345 /* Search up to 32 insns starting at FIRST:
2346    - at any kind of hinted branch, just return
2347    - at any unconditional branch in the first 15 insns, just return
2348    - at a call or indirect branch, after the first 15 insns, force it to
2349      an even address and return
2350    - at any unconditional branch, after the first 15 insns, force it to
2351      an even address. 
2352    At then end of the search, insert an hbrp within 4 insns of FIRST,
2353    and an hbrp within 16 instructions of FIRST.
2354  */
2355 static void
2356 insert_hbrp_for_ilb_runout (rtx first)
2357 {
2358   rtx insn, before_4 = 0, before_16 = 0;
2359   int addr = 0, length, first_addr = -1;
2360   int hbrp_addr0 = 128 * 4, hbrp_addr1 = 128 * 4;
2361   int insert_lnop_after = 0;
2362   for (insn = first; insn; insn = NEXT_INSN (insn))
2363     if (INSN_P (insn))
2364       {
2365         if (first_addr == -1)
2366           first_addr = INSN_ADDRESSES (INSN_UID (insn));
2367         addr = INSN_ADDRESSES (INSN_UID (insn)) - first_addr;
2368         length = get_attr_length (insn);
2369
2370         if (before_4 == 0 && addr + length >= 4 * 4)
2371           before_4 = insn;
2372         /* We test for 14 instructions because the first hbrp will add
2373            up to 2 instructions. */
2374         if (before_16 == 0 && addr + length >= 14 * 4)
2375           before_16 = insn;
2376
2377         if (INSN_CODE (insn) == CODE_FOR_hbr)
2378           {
2379             /* Make sure an hbrp is at least 2 cycles away from a hint. 
2380                Insert an lnop after the hbrp when necessary. */
2381             if (before_4 == 0 && addr > 0)
2382               {
2383                 before_4 = insn;
2384                 insert_lnop_after |= 1;
2385               }
2386             else if (before_4 && addr <= 4 * 4)
2387               insert_lnop_after |= 1;
2388             if (before_16 == 0 && addr > 10 * 4)
2389               {
2390                 before_16 = insn;
2391                 insert_lnop_after |= 2;
2392               }
2393             else if (before_16 && addr <= 14 * 4)
2394               insert_lnop_after |= 2;
2395           }
2396
2397         if (INSN_CODE (insn) == CODE_FOR_iprefetch)
2398           {
2399             if (addr < hbrp_addr0)
2400               hbrp_addr0 = addr;
2401             else if (addr < hbrp_addr1)
2402               hbrp_addr1 = addr;
2403           }
2404
2405         if (CALL_P (insn) || JUMP_P (insn))
2406           {
2407             if (HINTED_P (insn))
2408               return;
2409
2410             /* Any branch after the first 15 insns should be on an even
2411                address to avoid a special case branch.  There might be
2412                some nops and/or hbrps inserted, so we test after 10
2413                insns. */
2414             if (addr > 10 * 4)
2415               SCHED_ON_EVEN_P (insn) = 1;
2416           }
2417
2418         if (CALL_P (insn) || tablejump_p (insn, 0, 0))
2419           return;
2420
2421
2422         if (addr + length >= 32 * 4)
2423           {
2424             gcc_assert (before_4 && before_16);
2425             if (hbrp_addr0 > 4 * 4)
2426               {
2427                 insn =
2428                   emit_insn_before (gen_iprefetch (GEN_INT (1)), before_4);
2429                 recog_memoized (insn);
2430                 INSN_ADDRESSES_NEW (insn,
2431                                     INSN_ADDRESSES (INSN_UID (before_4)));
2432                 PUT_MODE (insn, GET_MODE (before_4));
2433                 PUT_MODE (before_4, TImode);
2434                 if (insert_lnop_after & 1)
2435                   {
2436                     insn = emit_insn_before (gen_lnop (), before_4);
2437                     recog_memoized (insn);
2438                     INSN_ADDRESSES_NEW (insn,
2439                                         INSN_ADDRESSES (INSN_UID (before_4)));
2440                     PUT_MODE (insn, TImode);
2441                   }
2442               }
2443             if ((hbrp_addr0 <= 4 * 4 || hbrp_addr0 > 16 * 4)
2444                 && hbrp_addr1 > 16 * 4)
2445               {
2446                 insn =
2447                   emit_insn_before (gen_iprefetch (GEN_INT (2)), before_16);
2448                 recog_memoized (insn);
2449                 INSN_ADDRESSES_NEW (insn,
2450                                     INSN_ADDRESSES (INSN_UID (before_16)));
2451                 PUT_MODE (insn, GET_MODE (before_16));
2452                 PUT_MODE (before_16, TImode);
2453                 if (insert_lnop_after & 2)
2454                   {
2455                     insn = emit_insn_before (gen_lnop (), before_16);
2456                     recog_memoized (insn);
2457                     INSN_ADDRESSES_NEW (insn,
2458                                         INSN_ADDRESSES (INSN_UID
2459                                                         (before_16)));
2460                     PUT_MODE (insn, TImode);
2461                   }
2462               }
2463             return;
2464           }
2465       }
2466     else if (BARRIER_P (insn))
2467       return;
2468
2469 }
2470
2471 /* The SPU might hang when it executes 48 inline instructions after a
2472    hinted branch jumps to its hinted target.  The beginning of a
2473    function and the return from a call might have been hinted, and must
2474    be handled as well.  To prevent a hang we insert 2 hbrps.  The first
2475    should be within 6 insns of the branch target.  The second should be
2476    within 22 insns of the branch target.  When determining if hbrps are
2477    necessary, we look for only 32 inline instructions, because up to to
2478    12 nops and 4 hbrps could be inserted.  Similarily, when inserting
2479    new hbrps, we insert them within 4 and 16 insns of the target.  */
2480 static void
2481 insert_hbrp (void)
2482 {
2483   rtx insn;
2484   if (TARGET_SAFE_HINTS)
2485     {
2486       shorten_branches (get_insns ());
2487       /* Insert hbrp at beginning of function */
2488       insn = next_active_insn (get_insns ());
2489       if (insn)
2490         insert_hbrp_for_ilb_runout (insn);
2491       /* Insert hbrp after hinted targets. */
2492       for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
2493         if ((LABEL_P (insn) && HINTED_P (insn)) || CALL_P (insn))
2494           insert_hbrp_for_ilb_runout (next_active_insn (insn));
2495     }
2496 }
2497
2498 static int in_spu_reorg;
2499
2500 /* Insert branch hints.  There are no branch optimizations after this
2501    pass, so it's safe to set our branch hints now. */
2502 static void
2503 spu_machine_dependent_reorg (void)
2504 {
2505   sbitmap blocks;
2506   basic_block bb;
2507   rtx branch, insn;
2508   rtx branch_target = 0;
2509   int branch_addr = 0, insn_addr, required_dist = 0;
2510   int i;
2511   unsigned int j;
2512
2513   if (!TARGET_BRANCH_HINTS || optimize == 0)
2514     {
2515       /* We still do it for unoptimized code because an external
2516          function might have hinted a call or return. */
2517       insert_hbrp ();
2518       pad_bb ();
2519       return;
2520     }
2521
2522   blocks = sbitmap_alloc (last_basic_block);
2523   sbitmap_zero (blocks);
2524
2525   in_spu_reorg = 1;
2526   compute_bb_for_insn ();
2527
2528   compact_blocks ();
2529
2530   spu_bb_info =
2531     (struct spu_bb_info *) xcalloc (n_basic_blocks,
2532                                     sizeof (struct spu_bb_info));
2533
2534   /* We need exact insn addresses and lengths.  */
2535   shorten_branches (get_insns ());
2536
2537   for (i = n_basic_blocks - 1; i >= 0; i--)
2538     {
2539       bb = BASIC_BLOCK (i);
2540       branch = 0;
2541       if (spu_bb_info[i].prop_jump)
2542         {
2543           branch = spu_bb_info[i].prop_jump;
2544           branch_target = get_branch_target (branch);
2545           branch_addr = INSN_ADDRESSES (INSN_UID (branch));
2546           required_dist = spu_hint_dist;
2547         }
2548       /* Search from end of a block to beginning.   In this loop, find
2549          jumps which need a branch and emit them only when:
2550          - it's an indirect branch and we're at the insn which sets
2551          the register  
2552          - we're at an insn that will invalidate the hint. e.g., a
2553          call, another hint insn, inline asm that clobbers $hbr, and
2554          some inlined operations (divmodsi4).  Don't consider jumps
2555          because they are only at the end of a block and are
2556          considered when we are deciding whether to propagate
2557          - we're getting too far away from the branch.  The hbr insns
2558          only have a signed 10 bit offset
2559          We go back as far as possible so the branch will be considered
2560          for propagation when we get to the beginning of the block.  */
2561       for (insn = BB_END (bb); insn; insn = PREV_INSN (insn))
2562         {
2563           if (INSN_P (insn))
2564             {
2565               insn_addr = INSN_ADDRESSES (INSN_UID (insn));
2566               if (branch
2567                   && ((GET_CODE (branch_target) == REG
2568                        && set_of (branch_target, insn) != NULL_RTX)
2569                       || insn_clobbers_hbr (insn)
2570                       || branch_addr - insn_addr > 600))
2571                 {
2572                   rtx next = NEXT_INSN (insn);
2573                   int next_addr = INSN_ADDRESSES (INSN_UID (next));
2574                   if (insn != BB_END (bb)
2575                       && branch_addr - next_addr >= required_dist)
2576                     {
2577                       if (dump_file)
2578                         fprintf (dump_file,
2579                                  "hint for %i in block %i before %i\n",
2580                                  INSN_UID (branch), bb->index,
2581                                  INSN_UID (next));
2582                       spu_emit_branch_hint (next, branch, branch_target,
2583                                             branch_addr - next_addr, blocks);
2584                     }
2585                   branch = 0;
2586                 }
2587
2588               /* JUMP_P will only be true at the end of a block.  When
2589                  branch is already set it means we've previously decided
2590                  to propagate a hint for that branch into this block. */
2591               if (CALL_P (insn) || (JUMP_P (insn) && !branch))
2592                 {
2593                   branch = 0;
2594                   if ((branch_target = get_branch_target (insn)))
2595                     {
2596                       branch = insn;
2597                       branch_addr = insn_addr;
2598                       required_dist = spu_hint_dist;
2599                     }
2600                 }
2601             }
2602           if (insn == BB_HEAD (bb))
2603             break;
2604         }
2605
2606       if (branch)
2607         {
2608           /* If we haven't emitted a hint for this branch yet, it might
2609              be profitable to emit it in one of the predecessor blocks,
2610              especially for loops.  */
2611           rtx bbend;
2612           basic_block prev = 0, prop = 0, prev2 = 0;
2613           int loop_exit = 0, simple_loop = 0;
2614           int next_addr = INSN_ADDRESSES (INSN_UID (NEXT_INSN (insn)));
2615
2616           for (j = 0; j < EDGE_COUNT (bb->preds); j++)
2617             if (EDGE_PRED (bb, j)->flags & EDGE_FALLTHRU)
2618               prev = EDGE_PRED (bb, j)->src;
2619             else
2620               prev2 = EDGE_PRED (bb, j)->src;
2621
2622           for (j = 0; j < EDGE_COUNT (bb->succs); j++)
2623             if (EDGE_SUCC (bb, j)->flags & EDGE_LOOP_EXIT)
2624               loop_exit = 1;
2625             else if (EDGE_SUCC (bb, j)->dest == bb)
2626               simple_loop = 1;
2627
2628           /* If this branch is a loop exit then propagate to previous
2629              fallthru block. This catches the cases when it is a simple
2630              loop or when there is an initial branch into the loop. */
2631           if (prev && (loop_exit || simple_loop)
2632               && prev->loop_depth <= bb->loop_depth)
2633             prop = prev;
2634
2635           /* If there is only one adjacent predecessor.  Don't propagate
2636              outside this loop.  This loop_depth test isn't perfect, but
2637              I'm not sure the loop_father member is valid at this point.  */
2638           else if (prev && single_pred_p (bb)
2639                    && prev->loop_depth == bb->loop_depth)
2640             prop = prev;
2641
2642           /* If this is the JOIN block of a simple IF-THEN then
2643              propogate the hint to the HEADER block. */
2644           else if (prev && prev2
2645                    && EDGE_COUNT (bb->preds) == 2
2646                    && EDGE_COUNT (prev->preds) == 1
2647                    && EDGE_PRED (prev, 0)->src == prev2
2648                    && prev2->loop_depth == bb->loop_depth
2649                    && GET_CODE (branch_target) != REG)
2650             prop = prev;
2651
2652           /* Don't propagate when:
2653              - this is a simple loop and the hint would be too far
2654              - this is not a simple loop and there are 16 insns in
2655              this block already
2656              - the predecessor block ends in a branch that will be
2657              hinted
2658              - the predecessor block ends in an insn that invalidates
2659              the hint */
2660           if (prop
2661               && prop->index >= 0
2662               && (bbend = BB_END (prop))
2663               && branch_addr - INSN_ADDRESSES (INSN_UID (bbend)) <
2664               (simple_loop ? 600 : 16 * 4) && get_branch_target (bbend) == 0
2665               && (JUMP_P (bbend) || !insn_clobbers_hbr (bbend)))
2666             {
2667               if (dump_file)
2668                 fprintf (dump_file, "propagate from %i to %i (loop depth %i) "
2669                          "for %i (loop_exit %i simple_loop %i dist %i)\n",
2670                          bb->index, prop->index, bb->loop_depth,
2671                          INSN_UID (branch), loop_exit, simple_loop,
2672                          branch_addr - INSN_ADDRESSES (INSN_UID (bbend)));
2673
2674               spu_bb_info[prop->index].prop_jump = branch;
2675               spu_bb_info[prop->index].bb_index = i;
2676             }
2677           else if (branch_addr - next_addr >= required_dist)
2678             {
2679               if (dump_file)
2680                 fprintf (dump_file, "hint for %i in block %i before %i\n",
2681                          INSN_UID (branch), bb->index,
2682                          INSN_UID (NEXT_INSN (insn)));
2683               spu_emit_branch_hint (NEXT_INSN (insn), branch, branch_target,
2684                                     branch_addr - next_addr, blocks);
2685             }
2686           branch = 0;
2687         }
2688     }
2689   free (spu_bb_info);
2690
2691   if (!sbitmap_empty_p (blocks))
2692     find_many_sub_basic_blocks (blocks);
2693
2694   /* We have to schedule to make sure alignment is ok. */
2695   FOR_EACH_BB (bb) bb->flags &= ~BB_DISABLE_SCHEDULE;
2696
2697   /* The hints need to be scheduled, so call it again. */
2698   schedule_insns ();
2699
2700   insert_hbrp ();
2701
2702   pad_bb ();
2703
2704
2705   if (spu_flag_var_tracking)
2706     {
2707       df_analyze ();
2708       timevar_push (TV_VAR_TRACKING);
2709       variable_tracking_main ();
2710       timevar_pop (TV_VAR_TRACKING);
2711       df_finish_pass (false);
2712     }
2713
2714   free_bb_for_insn ();
2715
2716   in_spu_reorg = 0;
2717 }
2718 \f
2719
2720 /* Insn scheduling routines, primarily for dual issue. */
2721 static int
2722 spu_sched_issue_rate (void)
2723 {
2724   return 2;
2725 }
2726
2727 static int
2728 uses_ls_unit(rtx insn)
2729 {
2730   rtx set = single_set (insn);
2731   if (set != 0
2732       && (GET_CODE (SET_DEST (set)) == MEM
2733           || GET_CODE (SET_SRC (set)) == MEM))
2734     return 1;
2735   return 0;
2736 }
2737
2738 static int
2739 get_pipe (rtx insn)
2740 {
2741   enum attr_type t;
2742   /* Handle inline asm */
2743   if (INSN_CODE (insn) == -1)
2744     return -1;
2745   t = get_attr_type (insn);
2746   switch (t)
2747     {
2748     case TYPE_CONVERT:
2749       return -2;
2750     case TYPE_MULTI0:
2751       return -1;
2752
2753     case TYPE_FX2:
2754     case TYPE_FX3:
2755     case TYPE_SPR:
2756     case TYPE_NOP:
2757     case TYPE_FXB:
2758     case TYPE_FPD:
2759     case TYPE_FP6:
2760     case TYPE_FP7:
2761       return 0;
2762
2763     case TYPE_LNOP:
2764     case TYPE_SHUF:
2765     case TYPE_LOAD:
2766     case TYPE_STORE:
2767     case TYPE_BR:
2768     case TYPE_MULTI1:
2769     case TYPE_HBR:
2770     case TYPE_IPREFETCH:
2771       return 1;
2772     default:
2773       abort ();
2774     }
2775 }
2776
2777
2778 /* haifa-sched.c has a static variable that keeps track of the current
2779    cycle.  It is passed to spu_sched_reorder, and we record it here for
2780    use by spu_sched_variable_issue.  It won't be accurate if the
2781    scheduler updates it's clock_var between the two calls. */
2782 static int clock_var;
2783
2784 /* This is used to keep track of insn alignment.  Set to 0 at the
2785    beginning of each block and increased by the "length" attr of each
2786    insn scheduled. */
2787 static int spu_sched_length;
2788
2789 /* Record when we've issued pipe0 and pipe1 insns so we can reorder the
2790    ready list appropriately in spu_sched_reorder(). */
2791 static int pipe0_clock;
2792 static int pipe1_clock;
2793
2794 static int prev_clock_var;
2795
2796 static int prev_priority;
2797
2798 /* The SPU needs to load the next ilb sometime during the execution of
2799    the previous ilb.  There is a potential conflict if every cycle has a
2800    load or store.  To avoid the conflict we make sure the load/store
2801    unit is free for at least one cycle during the execution of insns in
2802    the previous ilb. */
2803 static int spu_ls_first;
2804 static int prev_ls_clock;
2805
2806 static void
2807 spu_sched_init_global (FILE *file ATTRIBUTE_UNUSED, int verbose ATTRIBUTE_UNUSED,
2808                        int max_ready ATTRIBUTE_UNUSED)
2809 {
2810   spu_sched_length = 0;
2811 }
2812
2813 static void
2814 spu_sched_init (FILE *file ATTRIBUTE_UNUSED, int verbose ATTRIBUTE_UNUSED,
2815                 int max_ready ATTRIBUTE_UNUSED)
2816 {
2817   if (align_labels > 4 || align_loops > 4 || align_jumps > 4)
2818     {
2819       /* When any block might be at least 8-byte aligned, assume they
2820          will all be at least 8-byte aligned to make sure dual issue
2821          works out correctly. */
2822       spu_sched_length = 0;
2823     }
2824   spu_ls_first = INT_MAX;
2825   clock_var = -1;
2826   prev_ls_clock = -1;
2827   pipe0_clock = -1;
2828   pipe1_clock = -1;
2829   prev_clock_var = -1;
2830   prev_priority = -1;
2831 }
2832
2833 static int
2834 spu_sched_variable_issue (FILE *file ATTRIBUTE_UNUSED,
2835                           int verbose ATTRIBUTE_UNUSED, rtx insn, int more)
2836 {
2837   int len;
2838   int p;
2839   if (GET_CODE (PATTERN (insn)) == USE
2840       || GET_CODE (PATTERN (insn)) == CLOBBER
2841       || (len = get_attr_length (insn)) == 0)
2842     return more;
2843
2844   spu_sched_length += len;
2845
2846   /* Reset on inline asm */
2847   if (INSN_CODE (insn) == -1)
2848     {
2849       spu_ls_first = INT_MAX;
2850       pipe0_clock = -1;
2851       pipe1_clock = -1;
2852       return 0;
2853     }
2854   p = get_pipe (insn);
2855   if (p == 0)
2856     pipe0_clock = clock_var;
2857   else
2858     pipe1_clock = clock_var;
2859
2860   if (in_spu_reorg)
2861     {
2862       if (clock_var - prev_ls_clock > 1
2863           || INSN_CODE (insn) == CODE_FOR_iprefetch)
2864         spu_ls_first = INT_MAX;
2865       if (uses_ls_unit (insn))
2866         {
2867           if (spu_ls_first == INT_MAX)
2868             spu_ls_first = spu_sched_length;
2869           prev_ls_clock = clock_var;
2870         }
2871
2872       /* The scheduler hasn't inserted the nop, but we will later on.
2873          Include those nops in spu_sched_length. */
2874       if (prev_clock_var == clock_var && (spu_sched_length & 7))
2875         spu_sched_length += 4;
2876       prev_clock_var = clock_var;
2877
2878       /* more is -1 when called from spu_sched_reorder for new insns
2879          that don't have INSN_PRIORITY */
2880       if (more >= 0)
2881         prev_priority = INSN_PRIORITY (insn);
2882     }
2883
2884   /* Always try issueing more insns.  spu_sched_reorder will decide 
2885      when the cycle should be advanced. */
2886   return 1;
2887 }
2888
2889 /* This function is called for both TARGET_SCHED_REORDER and
2890    TARGET_SCHED_REORDER2.  */
2891 static int
2892 spu_sched_reorder (FILE *file ATTRIBUTE_UNUSED, int verbose ATTRIBUTE_UNUSED,
2893                    rtx *ready, int *nreadyp, int clock)
2894 {
2895   int i, nready = *nreadyp;
2896   int pipe_0, pipe_1, pipe_hbrp, pipe_ls, schedule_i;
2897   rtx insn;
2898
2899   clock_var = clock;
2900
2901   if (nready <= 0 || pipe1_clock >= clock)
2902     return 0;
2903
2904   /* Find any rtl insns that don't generate assembly insns and schedule
2905      them first. */
2906   for (i = nready - 1; i >= 0; i--)
2907     {
2908       insn = ready[i];
2909       if (INSN_CODE (insn) == -1
2910           || INSN_CODE (insn) == CODE_FOR_blockage
2911           || INSN_CODE (insn) == CODE_FOR__spu_convert)
2912         {
2913           ready[i] = ready[nready - 1];
2914           ready[nready - 1] = insn;
2915           return 1;
2916         }
2917     }
2918
2919   pipe_0 = pipe_1 = pipe_hbrp = pipe_ls = schedule_i = -1;
2920   for (i = 0; i < nready; i++)
2921     if (INSN_CODE (ready[i]) != -1)
2922       {
2923         insn = ready[i];
2924         switch (get_attr_type (insn))
2925           {
2926           default:
2927           case TYPE_MULTI0:
2928           case TYPE_CONVERT:
2929           case TYPE_FX2:
2930           case TYPE_FX3:
2931           case TYPE_SPR:
2932           case TYPE_NOP:
2933           case TYPE_FXB:
2934           case TYPE_FPD:
2935           case TYPE_FP6:
2936           case TYPE_FP7:
2937             pipe_0 = i;
2938             break;
2939           case TYPE_LOAD:
2940           case TYPE_STORE:
2941             pipe_ls = i;
2942           case TYPE_LNOP:
2943           case TYPE_SHUF:
2944           case TYPE_BR:
2945           case TYPE_MULTI1:
2946           case TYPE_HBR:
2947             pipe_1 = i;
2948             break;
2949           case TYPE_IPREFETCH:
2950             pipe_hbrp = i;
2951             break;
2952           }
2953       }
2954
2955   /* In the first scheduling phase, schedule loads and stores together
2956      to increase the chance they will get merged during postreload CSE. */
2957   if (!reload_completed && pipe_ls >= 0)
2958     {
2959       insn = ready[pipe_ls];
2960       ready[pipe_ls] = ready[nready - 1];
2961       ready[nready - 1] = insn;
2962       return 1;
2963     }
2964
2965   /* If there is an hbrp ready, prefer it over other pipe 1 insns. */
2966   if (pipe_hbrp >= 0)
2967     pipe_1 = pipe_hbrp;
2968
2969   /* When we have loads/stores in every cycle of the last 15 insns and
2970      we are about to schedule another load/store, emit an hbrp insn
2971      instead. */
2972   if (in_spu_reorg
2973       && spu_sched_length - spu_ls_first >= 4 * 15
2974       && !(pipe0_clock < clock && pipe_0 >= 0) && pipe_1 == pipe_ls)
2975     {
2976       insn = sched_emit_insn (gen_iprefetch (GEN_INT (3)));
2977       recog_memoized (insn);
2978       if (pipe0_clock < clock)
2979         PUT_MODE (insn, TImode);
2980       spu_sched_variable_issue (file, verbose, insn, -1);
2981       return 0;
2982     }
2983
2984   /* In general, we want to emit nops to increase dual issue, but dual
2985      issue isn't faster when one of the insns could be scheduled later
2986      without effecting the critical path.  We look at INSN_PRIORITY to
2987      make a good guess, but it isn't perfect so -mdual-nops=n can be
2988      used to effect it. */
2989   if (in_spu_reorg && spu_dual_nops < 10)
2990     {
2991       /* When we are at an even address and we are not issueing nops to
2992          improve scheduling then we need to advance the cycle.  */
2993       if ((spu_sched_length & 7) == 0 && prev_clock_var == clock
2994           && (spu_dual_nops == 0
2995               || (pipe_1 != -1
2996                   && prev_priority >
2997                   INSN_PRIORITY (ready[pipe_1]) + spu_dual_nops)))
2998         return 0;
2999
3000       /* When at an odd address, schedule the highest priority insn
3001          without considering pipeline. */
3002       if ((spu_sched_length & 7) == 4 && prev_clock_var != clock
3003           && (spu_dual_nops == 0
3004               || (prev_priority >
3005                   INSN_PRIORITY (ready[nready - 1]) + spu_dual_nops)))
3006         return 1;
3007     }
3008
3009
3010   /* We haven't issued a pipe0 insn yet this cycle, if there is a
3011      pipe0 insn in the ready list, schedule it. */
3012   if (pipe0_clock < clock && pipe_0 >= 0)
3013     schedule_i = pipe_0;
3014
3015   /* Either we've scheduled a pipe0 insn already or there is no pipe0
3016      insn to schedule.  Put a pipe1 insn at the front of the ready list. */
3017   else
3018     schedule_i = pipe_1;
3019
3020   if (schedule_i > -1)
3021     {
3022       insn = ready[schedule_i];
3023       ready[schedule_i] = ready[nready - 1];
3024       ready[nready - 1] = insn;
3025       return 1;
3026     }
3027   return 0;
3028 }
3029
3030 /* INSN is dependent on DEP_INSN. */
3031 static int
3032 spu_sched_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost)
3033 {
3034   rtx set;
3035
3036   /* The blockage pattern is used to prevent instructions from being
3037      moved across it and has no cost. */
3038   if (INSN_CODE (insn) == CODE_FOR_blockage
3039       || INSN_CODE (dep_insn) == CODE_FOR_blockage)
3040     return 0;
3041
3042   if (INSN_CODE (insn) == CODE_FOR__spu_convert
3043       || INSN_CODE (dep_insn) == CODE_FOR__spu_convert)
3044     return 0;
3045
3046   /* Make sure hbrps are spread out. */
3047   if (INSN_CODE (insn) == CODE_FOR_iprefetch
3048       && INSN_CODE (dep_insn) == CODE_FOR_iprefetch)
3049     return 8;
3050
3051   /* Make sure hints and hbrps are 2 cycles apart. */
3052   if ((INSN_CODE (insn) == CODE_FOR_iprefetch
3053        || INSN_CODE (insn) == CODE_FOR_hbr)
3054        && (INSN_CODE (dep_insn) == CODE_FOR_iprefetch
3055            || INSN_CODE (dep_insn) == CODE_FOR_hbr))
3056     return 2;
3057
3058   /* An hbrp has no real dependency on other insns. */
3059   if (INSN_CODE (insn) == CODE_FOR_iprefetch
3060       || INSN_CODE (dep_insn) == CODE_FOR_iprefetch)
3061     return 0;
3062
3063   /* Assuming that it is unlikely an argument register will be used in
3064      the first cycle of the called function, we reduce the cost for
3065      slightly better scheduling of dep_insn.  When not hinted, the
3066      mispredicted branch would hide the cost as well.  */
3067   if (CALL_P (insn))
3068   {
3069     rtx target = get_branch_target (insn);
3070     if (GET_CODE (target) != REG || !set_of (target, insn))
3071       return cost - 2;
3072     return cost;
3073   }
3074
3075   /* And when returning from a function, let's assume the return values
3076      are completed sooner too. */
3077   if (CALL_P (dep_insn))
3078     return cost - 2;
3079
3080   /* Make sure an instruction that loads from the back chain is schedule
3081      away from the return instruction so a hint is more likely to get
3082      issued. */
3083   if (INSN_CODE (insn) == CODE_FOR__return
3084       && (set = single_set (dep_insn))
3085       && GET_CODE (SET_DEST (set)) == REG
3086       && REGNO (SET_DEST (set)) == LINK_REGISTER_REGNUM)
3087     return 20;
3088
3089   /* The dfa scheduler sets cost to 0 for all anti-dependencies and the
3090      scheduler makes every insn in a block anti-dependent on the final
3091      jump_insn.  We adjust here so higher cost insns will get scheduled
3092      earlier. */
3093   if (JUMP_P (insn) && REG_NOTE_KIND (link) == REG_DEP_ANTI)
3094     return insn_cost (dep_insn) - 3;
3095
3096   return cost;
3097 }
3098 \f
3099 /* Create a CONST_DOUBLE from a string.  */
3100 struct rtx_def *
3101 spu_float_const (const char *string, enum machine_mode mode)
3102 {
3103   REAL_VALUE_TYPE value;
3104   value = REAL_VALUE_ATOF (string, mode);
3105   return CONST_DOUBLE_FROM_REAL_VALUE (value, mode);
3106 }
3107
3108 int
3109 spu_constant_address_p (rtx x)
3110 {
3111   return (GET_CODE (x) == LABEL_REF || GET_CODE (x) == SYMBOL_REF
3112           || GET_CODE (x) == CONST_INT || GET_CODE (x) == CONST
3113           || GET_CODE (x) == HIGH);
3114 }
3115
3116 static enum spu_immediate
3117 which_immediate_load (HOST_WIDE_INT val)
3118 {
3119   gcc_assert (val == trunc_int_for_mode (val, SImode));
3120
3121   if (val >= -0x8000 && val <= 0x7fff)
3122     return SPU_IL;
3123   if (val >= 0 && val <= 0x3ffff)
3124     return SPU_ILA;
3125   if ((val & 0xffff) == ((val >> 16) & 0xffff))
3126     return SPU_ILH;
3127   if ((val & 0xffff) == 0)
3128     return SPU_ILHU;
3129
3130   return SPU_NONE;
3131 }
3132
3133 /* Return true when OP can be loaded by one of the il instructions, or
3134    when flow2 is not completed and OP can be loaded using ilhu and iohl. */
3135 int
3136 immediate_load_p (rtx op, enum machine_mode mode)
3137 {
3138   if (CONSTANT_P (op))
3139     {
3140       enum immediate_class c = classify_immediate (op, mode);
3141       return c == IC_IL1 || c == IC_IL1s
3142              || (!epilogue_completed && (c == IC_IL2 || c == IC_IL2s));
3143     }
3144   return 0;
3145 }
3146
3147 /* Return true if the first SIZE bytes of arr is a constant that can be
3148    generated with cbd, chd, cwd or cdd.  When non-NULL, PRUN and PSTART
3149    represent the size and offset of the instruction to use. */
3150 static int
3151 cpat_info(unsigned char *arr, int size, int *prun, int *pstart)
3152 {
3153   int cpat, run, i, start;
3154   cpat = 1;
3155   run = 0;
3156   start = -1;
3157   for (i = 0; i < size && cpat; i++)
3158     if (arr[i] != i+16)
3159       { 
3160         if (!run)
3161           {
3162             start = i;
3163             if (arr[i] == 3)
3164               run = 1;
3165             else if (arr[i] == 2 && arr[i+1] == 3)
3166               run = 2;
3167             else if (arr[i] == 0)
3168               {
3169                 while (arr[i+run] == run && i+run < 16)
3170                   run++;
3171                 if (run != 4 && run != 8)
3172                   cpat = 0;
3173               }
3174             else
3175               cpat = 0;
3176             if ((i & (run-1)) != 0)
3177               cpat = 0;
3178             i += run;
3179           }
3180         else
3181           cpat = 0;
3182       }
3183   if (cpat && (run || size < 16))
3184     {
3185       if (run == 0)
3186         run = 1;
3187       if (prun)
3188         *prun = run;
3189       if (pstart)
3190         *pstart = start == -1 ? 16-run : start;
3191       return 1;
3192     }
3193   return 0;
3194 }
3195
3196 /* OP is a CONSTANT_P.  Determine what instructions can be used to load
3197    it into a register.  MODE is only valid when OP is a CONST_INT. */
3198 static enum immediate_class
3199 classify_immediate (rtx op, enum machine_mode mode)
3200 {
3201   HOST_WIDE_INT val;
3202   unsigned char arr[16];
3203   int i, j, repeated, fsmbi, repeat;
3204
3205   gcc_assert (CONSTANT_P (op));
3206
3207   if (GET_MODE (op) != VOIDmode)
3208     mode = GET_MODE (op);
3209
3210   /* A V4SI const_vector with all identical symbols is ok. */
3211   if (!flag_pic
3212       && mode == V4SImode
3213       && GET_CODE (op) == CONST_VECTOR
3214       && GET_CODE (CONST_VECTOR_ELT (op, 0)) != CONST_INT
3215       && GET_CODE (CONST_VECTOR_ELT (op, 0)) != CONST_DOUBLE
3216       && CONST_VECTOR_ELT (op, 0) == CONST_VECTOR_ELT (op, 1)
3217       && CONST_VECTOR_ELT (op, 1) == CONST_VECTOR_ELT (op, 2)
3218       && CONST_VECTOR_ELT (op, 2) == CONST_VECTOR_ELT (op, 3))
3219     op = CONST_VECTOR_ELT (op, 0);
3220
3221   switch (GET_CODE (op))
3222     {
3223     case SYMBOL_REF:
3224     case LABEL_REF:
3225       return TARGET_LARGE_MEM ? IC_IL2s : IC_IL1s;
3226
3227     case CONST:
3228       /* We can never know if the resulting address fits in 18 bits and can be
3229          loaded with ila.  For now, assume the address will not overflow if
3230          the displacement is "small" (fits 'K' constraint).  */
3231       if (!TARGET_LARGE_MEM && GET_CODE (XEXP (op, 0)) == PLUS)
3232         {
3233           rtx sym = XEXP (XEXP (op, 0), 0);
3234           rtx cst = XEXP (XEXP (op, 0), 1);
3235
3236           if (GET_CODE (sym) == SYMBOL_REF
3237               && GET_CODE (cst) == CONST_INT
3238               && satisfies_constraint_K (cst))
3239             return IC_IL1s;
3240         }
3241       return IC_IL2s;
3242
3243     case HIGH:
3244       return IC_IL1s;
3245
3246     case CONST_VECTOR:
3247       for (i = 0; i < GET_MODE_NUNITS (mode); i++)
3248         if (GET_CODE (CONST_VECTOR_ELT (op, i)) != CONST_INT
3249             && GET_CODE (CONST_VECTOR_ELT (op, i)) != CONST_DOUBLE)
3250           return IC_POOL;
3251       /* Fall through. */
3252
3253     case CONST_INT:
3254     case CONST_DOUBLE:
3255       constant_to_array (mode, op, arr);
3256
3257       /* Check that each 4-byte slot is identical. */
3258       repeated = 1;
3259       for (i = 4; i < 16; i += 4)
3260         for (j = 0; j < 4; j++)
3261           if (arr[j] != arr[i + j])
3262             repeated = 0;
3263
3264       if (repeated)
3265         {
3266           val = (arr[0] << 24) | (arr[1] << 16) | (arr[2] << 8) | arr[3];
3267           val = trunc_int_for_mode (val, SImode);
3268
3269           if (which_immediate_load (val) != SPU_NONE)
3270             return IC_IL1;
3271         }
3272
3273       /* Any mode of 2 bytes or smaller can be loaded with an il
3274          instruction. */
3275       gcc_assert (GET_MODE_SIZE (mode) > 2);
3276
3277       fsmbi = 1;
3278       repeat = 0;
3279       for (i = 0; i < 16 && fsmbi; i++)
3280         if (arr[i] != 0 && repeat == 0)
3281           repeat = arr[i];
3282         else if (arr[i] != 0 && arr[i] != repeat)
3283           fsmbi = 0;
3284       if (fsmbi)
3285         return repeat == 0xff ? IC_FSMBI : IC_FSMBI2;
3286
3287       if (cpat_info (arr, GET_MODE_SIZE (mode), 0, 0))
3288         return IC_CPAT;
3289
3290       if (repeated)
3291         return IC_IL2;
3292
3293       return IC_POOL;
3294     default:
3295       break;
3296     }
3297   gcc_unreachable ();
3298 }
3299
3300 static enum spu_immediate
3301 which_logical_immediate (HOST_WIDE_INT val)
3302 {
3303   gcc_assert (val == trunc_int_for_mode (val, SImode));
3304
3305   if (val >= -0x200 && val <= 0x1ff)
3306     return SPU_ORI;
3307   if (val >= 0 && val <= 0xffff)
3308     return SPU_IOHL;
3309   if ((val & 0xffff) == ((val >> 16) & 0xffff))
3310     {
3311       val = trunc_int_for_mode (val, HImode);
3312       if (val >= -0x200 && val <= 0x1ff)
3313         return SPU_ORHI;
3314       if ((val & 0xff) == ((val >> 8) & 0xff))
3315         {
3316           val = trunc_int_for_mode (val, QImode);
3317           if (val >= -0x200 && val <= 0x1ff)
3318             return SPU_ORBI;
3319         }
3320     }
3321   return SPU_NONE;
3322 }
3323
3324 /* Return TRUE when X, a CONST_VECTOR, only contains CONST_INTs or
3325    CONST_DOUBLEs. */
3326 static int
3327 const_vector_immediate_p (rtx x)
3328 {
3329   int i;
3330   gcc_assert (GET_CODE (x) == CONST_VECTOR);
3331   for (i = 0; i < GET_MODE_NUNITS (GET_MODE (x)); i++)
3332     if (GET_CODE (CONST_VECTOR_ELT (x, i)) != CONST_INT
3333         && GET_CODE (CONST_VECTOR_ELT (x, i)) != CONST_DOUBLE)
3334       return 0;
3335   return 1;
3336 }
3337
3338 int
3339 logical_immediate_p (rtx op, enum machine_mode mode)
3340 {
3341   HOST_WIDE_INT val;
3342   unsigned char arr[16];
3343   int i, j;
3344
3345   gcc_assert (GET_CODE (op) == CONST_INT || GET_CODE (op) == CONST_DOUBLE
3346               || GET_CODE (op) == CONST_VECTOR);
3347
3348   if (GET_CODE (op) == CONST_VECTOR
3349       && !const_vector_immediate_p (op))
3350     return 0;
3351
3352   if (GET_MODE (op) != VOIDmode)
3353     mode = GET_MODE (op);
3354
3355   constant_to_array (mode, op, arr);
3356
3357   /* Check that bytes are repeated. */
3358   for (i = 4; i < 16; i += 4)
3359     for (j = 0; j < 4; j++)
3360       if (arr[j] != arr[i + j])
3361         return 0;
3362
3363   val = (arr[0] << 24) | (arr[1] << 16) | (arr[2] << 8) | arr[3];
3364   val = trunc_int_for_mode (val, SImode);
3365
3366   i = which_logical_immediate (val);
3367   return i != SPU_NONE && i != SPU_IOHL;
3368 }
3369
3370 int
3371 iohl_immediate_p (rtx op, enum machine_mode mode)
3372 {
3373   HOST_WIDE_INT val;
3374   unsigned char arr[16];
3375   int i, j;
3376
3377   gcc_assert (GET_CODE (op) == CONST_INT || GET_CODE (op) == CONST_DOUBLE
3378               || GET_CODE (op) == CONST_VECTOR);
3379
3380   if (GET_CODE (op) == CONST_VECTOR
3381       && !const_vector_immediate_p (op))
3382     return 0;
3383
3384   if (GET_MODE (op) != VOIDmode)
3385     mode = GET_MODE (op);
3386
3387   constant_to_array (mode, op, arr);
3388
3389   /* Check that bytes are repeated. */
3390   for (i = 4; i < 16; i += 4)
3391     for (j = 0; j < 4; j++)
3392       if (arr[j] != arr[i + j])
3393         return 0;
3394
3395   val = (arr[0] << 24) | (arr[1] << 16) | (arr[2] << 8) | arr[3];
3396   val = trunc_int_for_mode (val, SImode);
3397
3398   return val >= 0 && val <= 0xffff;
3399 }
3400
3401 int
3402 arith_immediate_p (rtx op, enum machine_mode mode,
3403                    HOST_WIDE_INT low, HOST_WIDE_INT high)
3404 {
3405   HOST_WIDE_INT val;
3406   unsigned char arr[16];
3407   int bytes, i, j;
3408
3409   gcc_assert (GET_CODE (op) == CONST_INT || GET_CODE (op) == CONST_DOUBLE
3410               || GET_CODE (op) == CONST_VECTOR);
3411
3412   if (GET_CODE (op) == CONST_VECTOR
3413       && !const_vector_immediate_p (op))
3414     return 0;
3415
3416   if (GET_MODE (op) != VOIDmode)
3417     mode = GET_MODE (op);
3418
3419   constant_to_array (mode, op, arr);
3420
3421   if (VECTOR_MODE_P (mode))
3422     mode = GET_MODE_INNER (mode);
3423
3424   bytes = GET_MODE_SIZE (mode);
3425   mode = mode_for_size (GET_MODE_BITSIZE (mode), MODE_INT, 0);
3426
3427   /* Check that bytes are repeated. */
3428   for (i = bytes; i < 16; i += bytes)
3429     for (j = 0; j < bytes; j++)
3430       if (arr[j] != arr[i + j])
3431         return 0;
3432
3433   val = arr[0];
3434   for (j = 1; j < bytes; j++)
3435     val = (val << 8) | arr[j];
3436
3437   val = trunc_int_for_mode (val, mode);
3438
3439   return val >= low && val <= high;
3440 }
3441
3442 /* We accept:
3443    - any 32-bit constant (SImode, SFmode)
3444    - any constant that can be generated with fsmbi (any mode)
3445    - a 64-bit constant where the high and low bits are identical
3446      (DImode, DFmode)
3447    - a 128-bit constant where the four 32-bit words match.  */
3448 int
3449 spu_legitimate_constant_p (rtx x)
3450 {
3451   if (GET_CODE (x) == HIGH)
3452     x = XEXP (x, 0);
3453   /* V4SI with all identical symbols is valid. */
3454   if (!flag_pic
3455       && GET_MODE (x) == V4SImode
3456       && (GET_CODE (CONST_VECTOR_ELT (x, 0)) == SYMBOL_REF
3457           || GET_CODE (CONST_VECTOR_ELT (x, 0)) == LABEL_REF
3458           || GET_CODE (CONST_VECTOR_ELT (x, 0)) == CONST))
3459     return CONST_VECTOR_ELT (x, 0) == CONST_VECTOR_ELT (x, 1)
3460            && CONST_VECTOR_ELT (x, 1) == CONST_VECTOR_ELT (x, 2)
3461            && CONST_VECTOR_ELT (x, 2) == CONST_VECTOR_ELT (x, 3);
3462
3463   if (GET_CODE (x) == CONST_VECTOR
3464       && !const_vector_immediate_p (x))
3465     return 0;
3466   return 1;
3467 }
3468
3469 /* Valid address are:
3470    - symbol_ref, label_ref, const
3471    - reg
3472    - reg + const, where either reg or const is 16 byte aligned
3473    - reg + reg, alignment doesn't matter
3474   The alignment matters in the reg+const case because lqd and stqd
3475   ignore the 4 least significant bits of the const.  (TODO: It might be
3476   preferable to allow any alignment and fix it up when splitting.) */
3477 int
3478 spu_legitimate_address (enum machine_mode mode ATTRIBUTE_UNUSED,
3479                         rtx x, int reg_ok_strict)
3480 {
3481   if (mode == TImode && GET_CODE (x) == AND
3482       && GET_CODE (XEXP (x, 1)) == CONST_INT
3483       && INTVAL (XEXP (x, 1)) == (HOST_WIDE_INT) -16)
3484     x = XEXP (x, 0);
3485   switch (GET_CODE (x))
3486     {
3487     case SYMBOL_REF:
3488     case LABEL_REF:
3489       return !TARGET_LARGE_MEM;
3490
3491     case CONST:
3492       if (!TARGET_LARGE_MEM && GET_CODE (XEXP (x, 0)) == PLUS)
3493         {
3494           rtx sym = XEXP (XEXP (x, 0), 0);
3495           rtx cst = XEXP (XEXP (x, 0), 1);
3496
3497           /* Accept any symbol_ref + constant, assuming it does not
3498              wrap around the local store addressability limit.  */
3499           if (GET_CODE (sym) == SYMBOL_REF && GET_CODE (cst) == CONST_INT)
3500             return 1;
3501         }
3502       return 0;
3503
3504     case CONST_INT:
3505       return INTVAL (x) >= 0 && INTVAL (x) <= 0x3ffff;
3506
3507     case SUBREG:
3508       x = XEXP (x, 0);
3509       gcc_assert (GET_CODE (x) == REG);
3510
3511     case REG:
3512       return INT_REG_OK_FOR_BASE_P (x, reg_ok_strict);
3513
3514     case PLUS:
3515     case LO_SUM:
3516       {
3517         rtx op0 = XEXP (x, 0);
3518         rtx op1 = XEXP (x, 1);
3519         if (GET_CODE (op0) == SUBREG)
3520           op0 = XEXP (op0, 0);
3521         if (GET_CODE (op1) == SUBREG)
3522           op1 = XEXP (op1, 0);
3523         /* We can't just accept any aligned register because CSE can
3524            change it to a register that is not marked aligned and then
3525            recog will fail.   So we only accept frame registers because
3526            they will only be changed to other frame registers. */
3527         if (GET_CODE (op0) == REG
3528             && INT_REG_OK_FOR_BASE_P (op0, reg_ok_strict)
3529             && GET_CODE (op1) == CONST_INT
3530             && INTVAL (op1) >= -0x2000
3531             && INTVAL (op1) <= 0x1fff
3532             && (regno_aligned_for_load (REGNO (op0)) || (INTVAL (op1) & 15) == 0))
3533           return 1;
3534         if (GET_CODE (op0) == REG
3535             && INT_REG_OK_FOR_BASE_P (op0, reg_ok_strict)
3536             && GET_CODE (op1) == REG
3537             && INT_REG_OK_FOR_INDEX_P (op1, reg_ok_strict))
3538           return 1;
3539       }
3540       break;
3541
3542     default:
3543       break;
3544     }
3545   return 0;
3546 }
3547
3548 /* When the address is reg + const_int, force the const_int into a
3549    register.  */
3550 rtx
3551 spu_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
3552                         enum machine_mode mode)
3553 {
3554   rtx op0, op1;
3555   /* Make sure both operands are registers.  */
3556   if (GET_CODE (x) == PLUS)
3557     {
3558       op0 = XEXP (x, 0);
3559       op1 = XEXP (x, 1);
3560       if (ALIGNED_SYMBOL_REF_P (op0))
3561         {
3562           op0 = force_reg (Pmode, op0);
3563           mark_reg_pointer (op0, 128);
3564         }
3565       else if (GET_CODE (op0) != REG)
3566         op0 = force_reg (Pmode, op0);
3567       if (ALIGNED_SYMBOL_REF_P (op1))
3568         {
3569           op1 = force_reg (Pmode, op1);
3570           mark_reg_pointer (op1, 128);
3571         }
3572       else if (GET_CODE (op1) != REG)
3573         op1 = force_reg (Pmode, op1);
3574       x = gen_rtx_PLUS (Pmode, op0, op1);
3575       if (spu_legitimate_address (mode, x, 0))
3576         return x;
3577     }
3578   return NULL_RTX;
3579 }
3580
3581 /* Handle an attribute requiring a FUNCTION_DECL; arguments as in
3582    struct attribute_spec.handler.  */
3583 static tree
3584 spu_handle_fndecl_attribute (tree * node,
3585                              tree name,
3586                              tree args ATTRIBUTE_UNUSED,
3587                              int flags ATTRIBUTE_UNUSED, bool * no_add_attrs)
3588 {
3589   if (TREE_CODE (*node) != FUNCTION_DECL)
3590     {
3591       warning (0, "`%s' attribute only applies to functions",
3592                IDENTIFIER_POINTER (name));
3593       *no_add_attrs = true;
3594     }
3595
3596   return NULL_TREE;
3597 }
3598
3599 /* Handle the "vector" attribute.  */
3600 static tree
3601 spu_handle_vector_attribute (tree * node, tree name,
3602                              tree args ATTRIBUTE_UNUSED,
3603                              int flags ATTRIBUTE_UNUSED, bool * no_add_attrs)
3604 {
3605   tree type = *node, result = NULL_TREE;
3606   enum machine_mode mode;
3607   int unsigned_p;
3608
3609   while (POINTER_TYPE_P (type)
3610          || TREE_CODE (type) == FUNCTION_TYPE
3611          || TREE_CODE (type) == METHOD_TYPE || TREE_CODE (type) == ARRAY_TYPE)
3612     type = TREE_TYPE (type);
3613
3614   mode = TYPE_MODE (type);
3615
3616   unsigned_p = TYPE_UNSIGNED (type);
3617   switch (mode)
3618     {
3619     case DImode:
3620       result = (unsigned_p ? unsigned_V2DI_type_node : V2DI_type_node);
3621       break;
3622     case SImode:
3623       result = (unsigned_p ? unsigned_V4SI_type_node : V4SI_type_node);
3624       break;
3625     case HImode:
3626       result = (unsigned_p ? unsigned_V8HI_type_node : V8HI_type_node);
3627       break;
3628     case QImode:
3629       result = (unsigned_p ? unsigned_V16QI_type_node : V16QI_type_node);
3630       break;
3631     case SFmode:
3632       result = V4SF_type_node;
3633       break;
3634     case DFmode:
3635       result = V2DF_type_node;
3636       break;
3637     default:
3638       break;
3639     }
3640
3641   /* Propagate qualifiers attached to the element type
3642      onto the vector type.  */
3643   if (result && result != type && TYPE_QUALS (type))
3644     result = build_qualified_type (result, TYPE_QUALS (type));
3645
3646   *no_add_attrs = true;         /* No need to hang on to the attribute.  */
3647
3648   if (!result)
3649     warning (0, "`%s' attribute ignored", IDENTIFIER_POINTER (name));
3650   else
3651     *node = lang_hooks.types.reconstruct_complex_type (*node, result);
3652
3653   return NULL_TREE;
3654 }
3655
3656 /* Return nonzero if FUNC is a naked function.  */
3657 static int
3658 spu_naked_function_p (tree func)
3659 {
3660   tree a;
3661
3662   if (TREE_CODE (func) != FUNCTION_DECL)
3663     abort ();
3664
3665   a = lookup_attribute ("naked", DECL_ATTRIBUTES (func));
3666   return a != NULL_TREE;
3667 }
3668
3669 int
3670 spu_initial_elimination_offset (int from, int to)
3671 {
3672   int saved_regs_size = spu_saved_regs_size ();
3673   int sp_offset = 0;
3674   if (!current_function_is_leaf || crtl->outgoing_args_size
3675       || get_frame_size () || saved_regs_size)
3676     sp_offset = STACK_POINTER_OFFSET;
3677   if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
3678     return get_frame_size () + crtl->outgoing_args_size + sp_offset;
3679   else if (from == FRAME_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM)
3680     return get_frame_size ();
3681   else if (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
3682     return sp_offset + crtl->outgoing_args_size
3683       + get_frame_size () + saved_regs_size + STACK_POINTER_OFFSET;
3684   else if (from == ARG_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM)
3685     return get_frame_size () + saved_regs_size + sp_offset;
3686   else
3687     gcc_unreachable ();
3688 }
3689
3690 rtx
3691 spu_function_value (const_tree type, const_tree func ATTRIBUTE_UNUSED)
3692 {
3693   enum machine_mode mode = TYPE_MODE (type);
3694   int byte_size = ((mode == BLKmode)
3695                    ? int_size_in_bytes (type) : GET_MODE_SIZE (mode));
3696
3697   /* Make sure small structs are left justified in a register. */
3698   if ((mode == BLKmode || (type && AGGREGATE_TYPE_P (type)))
3699       && byte_size <= UNITS_PER_WORD * MAX_REGISTER_RETURN && byte_size > 0)
3700     {
3701       enum machine_mode smode;
3702       rtvec v;
3703       int i;
3704       int nregs = (byte_size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
3705       int n = byte_size / UNITS_PER_WORD;
3706       v = rtvec_alloc (nregs);
3707       for (i = 0; i < n; i++)
3708         {
3709           RTVEC_ELT (v, i) = gen_rtx_EXPR_LIST (VOIDmode,
3710                                                 gen_rtx_REG (TImode,
3711                                                              FIRST_RETURN_REGNUM
3712                                                              + i),
3713                                                 GEN_INT (UNITS_PER_WORD * i));
3714           byte_size -= UNITS_PER_WORD;
3715         }
3716
3717       if (n < nregs)
3718         {
3719           if (byte_size < 4)
3720             byte_size = 4;
3721           smode =
3722             smallest_mode_for_size (byte_size * BITS_PER_UNIT, MODE_INT);
3723           RTVEC_ELT (v, n) =
3724             gen_rtx_EXPR_LIST (VOIDmode,
3725                                gen_rtx_REG (smode, FIRST_RETURN_REGNUM + n),
3726                                GEN_INT (UNITS_PER_WORD * n));
3727         }
3728       return gen_rtx_PARALLEL (mode, v);
3729     }
3730   return gen_rtx_REG (mode, FIRST_RETURN_REGNUM);
3731 }
3732
3733 rtx
3734 spu_function_arg (CUMULATIVE_ARGS cum,
3735                   enum machine_mode mode,
3736                   tree type, int named ATTRIBUTE_UNUSED)
3737 {
3738   int byte_size;
3739
3740   if (cum >= MAX_REGISTER_ARGS)
3741     return 0;
3742
3743   byte_size = ((mode == BLKmode)
3744                ? int_size_in_bytes (type) : GET_MODE_SIZE (mode));
3745
3746   /* The ABI does not allow parameters to be passed partially in
3747      reg and partially in stack. */
3748   if ((cum + (byte_size + 15) / 16) > MAX_REGISTER_ARGS)
3749     return 0;
3750
3751   /* Make sure small structs are left justified in a register. */
3752   if ((mode == BLKmode || (type && AGGREGATE_TYPE_P (type)))
3753       && byte_size < UNITS_PER_WORD && byte_size > 0)
3754     {
3755       enum machine_mode smode;
3756       rtx gr_reg;
3757       if (byte_size < 4)
3758         byte_size = 4;
3759       smode = smallest_mode_for_size (byte_size * BITS_PER_UNIT, MODE_INT);
3760       gr_reg = gen_rtx_EXPR_LIST (VOIDmode,
3761                                   gen_rtx_REG (smode, FIRST_ARG_REGNUM + cum),
3762                                   const0_rtx);
3763       return gen_rtx_PARALLEL (mode, gen_rtvec (1, gr_reg));
3764     }
3765   else
3766     return gen_rtx_REG (mode, FIRST_ARG_REGNUM + cum);
3767 }
3768
3769 /* Variable sized types are passed by reference.  */
3770 static bool
3771 spu_pass_by_reference (CUMULATIVE_ARGS * cum ATTRIBUTE_UNUSED,
3772                        enum machine_mode mode ATTRIBUTE_UNUSED,
3773                        const_tree type, bool named ATTRIBUTE_UNUSED)
3774 {
3775   return type && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST;
3776 }
3777 \f
3778
3779 /* Var args. */
3780
3781 /* Create and return the va_list datatype.
3782
3783    On SPU, va_list is an array type equivalent to
3784
3785       typedef struct __va_list_tag
3786         {
3787             void *__args __attribute__((__aligned(16)));
3788             void *__skip __attribute__((__aligned(16)));
3789             
3790         } va_list[1];
3791
3792    where __args points to the arg that will be returned by the next
3793    va_arg(), and __skip points to the previous stack frame such that
3794    when __args == __skip we should advance __args by 32 bytes. */
3795 static tree
3796 spu_build_builtin_va_list (void)
3797 {
3798   tree f_args, f_skip, record, type_decl;
3799   bool owp;
3800
3801   record = (*lang_hooks.types.make_type) (RECORD_TYPE);
3802
3803   type_decl =
3804     build_decl (TYPE_DECL, get_identifier ("__va_list_tag"), record);
3805
3806   f_args = build_decl (FIELD_DECL, get_identifier ("__args"), ptr_type_node);
3807   f_skip = build_decl (FIELD_DECL, get_identifier ("__skip"), ptr_type_node);
3808
3809   DECL_FIELD_CONTEXT (f_args) = record;
3810   DECL_ALIGN (f_args) = 128;
3811   DECL_USER_ALIGN (f_args) = 1;
3812
3813   DECL_FIELD_CONTEXT (f_skip) = record;
3814   DECL_ALIGN (f_skip) = 128;
3815   DECL_USER_ALIGN (f_skip) = 1;
3816
3817   TREE_CHAIN (record) = type_decl;
3818   TYPE_NAME (record) = type_decl;
3819   TYPE_FIELDS (record) = f_args;
3820   TREE_CHAIN (f_args) = f_skip;
3821
3822   /* We know this is being padded and we want it too.  It is an internal
3823      type so hide the warnings from the user. */
3824   owp = warn_padded;
3825   warn_padded = false;
3826
3827   layout_type (record);
3828
3829   warn_padded = owp;
3830
3831   /* The correct type is an array type of one element.  */
3832   return build_array_type (record, build_index_type (size_zero_node));
3833 }
3834
3835 /* Implement va_start by filling the va_list structure VALIST.
3836    NEXTARG points to the first anonymous stack argument.
3837
3838    The following global variables are used to initialize
3839    the va_list structure:
3840
3841      crtl->args.info;
3842        the CUMULATIVE_ARGS for this function
3843
3844      crtl->args.arg_offset_rtx:
3845        holds the offset of the first anonymous stack argument
3846        (relative to the virtual arg pointer).  */
3847
3848 static void
3849 spu_va_start (tree valist, rtx nextarg)
3850 {
3851   tree f_args, f_skip;
3852   tree args, skip, t;
3853
3854   f_args = TYPE_FIELDS (TREE_TYPE (va_list_type_node));
3855   f_skip = TREE_CHAIN (f_args);
3856
3857   valist = build_va_arg_indirect_ref (valist);
3858   args =
3859     build3 (COMPONENT_REF, TREE_TYPE (f_args), valist, f_args, NULL_TREE);
3860   skip =
3861     build3 (COMPONENT_REF, TREE_TYPE (f_skip), valist, f_skip, NULL_TREE);
3862
3863   /* Find the __args area.  */
3864   t = make_tree (TREE_TYPE (args), nextarg);
3865   if (crtl->args.pretend_args_size > 0)
3866     t = build2 (POINTER_PLUS_EXPR, TREE_TYPE (args), t,
3867                 size_int (-STACK_POINTER_OFFSET));
3868   t = build2 (MODIFY_EXPR, TREE_TYPE (args), args, t);
3869   TREE_SIDE_EFFECTS (t) = 1;
3870   expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
3871
3872   /* Find the __skip area.  */
3873   t = make_tree (TREE_TYPE (skip), virtual_incoming_args_rtx);
3874   t = build2 (POINTER_PLUS_EXPR, TREE_TYPE (skip), t,
3875               size_int (crtl->args.pretend_args_size
3876                          - STACK_POINTER_OFFSET));
3877   t = build2 (MODIFY_EXPR, TREE_TYPE (skip), skip, t);
3878   TREE_SIDE_EFFECTS (t) = 1;
3879   expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
3880 }
3881
3882 /* Gimplify va_arg by updating the va_list structure 
3883    VALIST as required to retrieve an argument of type
3884    TYPE, and returning that argument. 
3885    
3886    ret = va_arg(VALIST, TYPE);
3887
3888    generates code equivalent to:
3889    
3890     paddedsize = (sizeof(TYPE) + 15) & -16;
3891     if (VALIST.__args + paddedsize > VALIST.__skip
3892         && VALIST.__args <= VALIST.__skip)
3893       addr = VALIST.__skip + 32;
3894     else
3895       addr = VALIST.__args;
3896     VALIST.__args = addr + paddedsize;
3897     ret = *(TYPE *)addr;
3898  */
3899 static tree
3900 spu_gimplify_va_arg_expr (tree valist, tree type, gimple_seq * pre_p,
3901                           gimple_seq * post_p ATTRIBUTE_UNUSED)
3902 {
3903   tree f_args, f_skip;
3904   tree args, skip;
3905   HOST_WIDE_INT size, rsize;
3906   tree paddedsize, addr, tmp;
3907   bool pass_by_reference_p;
3908
3909   f_args = TYPE_FIELDS (TREE_TYPE (va_list_type_node));
3910   f_skip = TREE_CHAIN (f_args);
3911
3912   valist = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (valist)), valist);
3913   args =
3914     build3 (COMPONENT_REF, TREE_TYPE (f_args), valist, f_args, NULL_TREE);
3915   skip =
3916     build3 (COMPONENT_REF, TREE_TYPE (f_skip), valist, f_skip, NULL_TREE);
3917
3918   addr = create_tmp_var (ptr_type_node, "va_arg");
3919   DECL_POINTER_ALIAS_SET (addr) = get_varargs_alias_set ();
3920
3921   /* if an object is dynamically sized, a pointer to it is passed
3922      instead of the object itself. */
3923   pass_by_reference_p = spu_pass_by_reference (NULL, TYPE_MODE (type), type,
3924                                                false);
3925   if (pass_by_reference_p)
3926     type = build_pointer_type (type);
3927   size = int_size_in_bytes (type);
3928   rsize = ((size + UNITS_PER_WORD - 1) / UNITS_PER_WORD) * UNITS_PER_WORD;
3929
3930   /* build conditional expression to calculate addr. The expression
3931      will be gimplified later. */
3932   paddedsize = size_int (rsize);
3933   tmp = build2 (POINTER_PLUS_EXPR, ptr_type_node, unshare_expr (args), paddedsize);
3934   tmp = build2 (TRUTH_AND_EXPR, boolean_type_node,
3935                 build2 (GT_EXPR, boolean_type_node, tmp, unshare_expr (skip)),
3936                 build2 (LE_EXPR, boolean_type_node, unshare_expr (args),
3937                 unshare_expr (skip)));
3938
3939   tmp = build3 (COND_EXPR, ptr_type_node, tmp,
3940                 build2 (POINTER_PLUS_EXPR, ptr_type_node, unshare_expr (skip),
3941                         size_int (32)), unshare_expr (args));
3942
3943   gimplify_assign (addr, tmp, pre_p);
3944
3945   /* update VALIST.__args */
3946   tmp = build2 (POINTER_PLUS_EXPR, ptr_type_node, addr, paddedsize);
3947   gimplify_assign (unshare_expr (args), tmp, pre_p);
3948
3949   addr = fold_convert (build_pointer_type (type), addr);
3950
3951   if (pass_by_reference_p)
3952     addr = build_va_arg_indirect_ref (addr);
3953
3954   return build_va_arg_indirect_ref (addr);
3955 }
3956
3957 /* Save parameter registers starting with the register that corresponds
3958    to the first unnamed parameters.  If the first unnamed parameter is
3959    in the stack then save no registers.  Set pretend_args_size to the
3960    amount of space needed to save the registers. */
3961 void
3962 spu_setup_incoming_varargs (CUMULATIVE_ARGS * cum, enum machine_mode mode,
3963                             tree type, int *pretend_size, int no_rtl)
3964 {
3965   if (!no_rtl)
3966     {
3967       rtx tmp;
3968       int regno;
3969       int offset;
3970       int ncum = *cum;
3971
3972       /* cum currently points to the last named argument, we want to
3973          start at the next argument. */
3974       FUNCTION_ARG_ADVANCE (ncum, mode, type, 1);
3975
3976       offset = -STACK_POINTER_OFFSET;
3977       for (regno = ncum; regno < MAX_REGISTER_ARGS; regno++)
3978         {
3979           tmp = gen_frame_mem (V4SImode,
3980                                plus_constant (virtual_incoming_args_rtx,
3981                                               offset));
3982           emit_move_insn (tmp,
3983                           gen_rtx_REG (V4SImode, FIRST_ARG_REGNUM + regno));
3984           offset += 16;
3985         }
3986       *pretend_size = offset + STACK_POINTER_OFFSET;
3987     }
3988 }
3989 \f
3990 void
3991 spu_conditional_register_usage (void)
3992 {
3993   if (flag_pic)
3994     {
3995       fixed_regs[PIC_OFFSET_TABLE_REGNUM] = 1;
3996       call_used_regs[PIC_OFFSET_TABLE_REGNUM] = 1;
3997     }
3998 }
3999
4000 /* This is called to decide when we can simplify a load instruction.  We
4001    must only return true for registers which we know will always be
4002    aligned.  Taking into account that CSE might replace this reg with
4003    another one that has not been marked aligned.  
4004    So this is really only true for frame, stack and virtual registers,
4005    which we know are always aligned and should not be adversely effected
4006    by CSE.  */
4007 static int
4008 regno_aligned_for_load (int regno)
4009 {
4010   return regno == FRAME_POINTER_REGNUM
4011     || (frame_pointer_needed && regno == HARD_FRAME_POINTER_REGNUM)
4012     || regno == ARG_POINTER_REGNUM
4013     || regno == STACK_POINTER_REGNUM
4014     || (regno >= FIRST_VIRTUAL_REGISTER 
4015         && regno <= LAST_VIRTUAL_REGISTER);
4016 }
4017
4018 /* Return TRUE when mem is known to be 16-byte aligned. */
4019 int
4020 aligned_mem_p (rtx mem)
4021 {
4022   if (MEM_ALIGN (mem) >= 128)
4023     return 1;
4024   if (GET_MODE_SIZE (GET_MODE (mem)) >= 16)
4025     return 1;
4026   if (GET_CODE (XEXP (mem, 0)) == PLUS)
4027     {
4028       rtx p0 = XEXP (XEXP (mem, 0), 0);
4029       rtx p1 = XEXP (XEXP (mem, 0), 1);
4030       if (regno_aligned_for_load (REGNO (p0)))
4031         {
4032           if (GET_CODE (p1) == REG && regno_aligned_for_load (REGNO (p1)))
4033             return 1;
4034           if (GET_CODE (p1) == CONST_INT && (INTVAL (p1) & 15) == 0)
4035             return 1;
4036         }
4037     }
4038   else if (GET_CODE (XEXP (mem, 0)) == REG)
4039     {
4040       if (regno_aligned_for_load (REGNO (XEXP (mem, 0))))
4041         return 1;
4042     }
4043   else if (ALIGNED_SYMBOL_REF_P (XEXP (mem, 0)))
4044     return 1;
4045   else if (GET_CODE (XEXP (mem, 0)) == CONST)
4046     {
4047       rtx p0 = XEXP (XEXP (XEXP (mem, 0), 0), 0);
4048       rtx p1 = XEXP (XEXP (XEXP (mem, 0), 0), 1);
4049       if (GET_CODE (p0) == SYMBOL_REF
4050           && GET_CODE (p1) == CONST_INT && (INTVAL (p1) & 15) == 0)
4051         return 1;
4052     }
4053   return 0;
4054 }
4055
4056 /* Encode symbol attributes (local vs. global, tls model) of a SYMBOL_REF
4057    into its SYMBOL_REF_FLAGS.  */
4058 static void
4059 spu_encode_section_info (tree decl, rtx rtl, int first)
4060 {
4061   default_encode_section_info (decl, rtl, first);
4062
4063   /* If a variable has a forced alignment to < 16 bytes, mark it with
4064      SYMBOL_FLAG_ALIGN1.  */
4065   if (TREE_CODE (decl) == VAR_DECL
4066       && DECL_USER_ALIGN (decl) && DECL_ALIGN (decl) < 128)
4067     SYMBOL_REF_FLAGS (XEXP (rtl, 0)) |= SYMBOL_FLAG_ALIGN1;
4068 }
4069
4070 /* Return TRUE if we are certain the mem refers to a complete object
4071    which is both 16-byte aligned and padded to a 16-byte boundary.  This
4072    would make it safe to store with a single instruction. 
4073    We guarantee the alignment and padding for static objects by aligning
4074    all of them to 16-bytes. (DATA_ALIGNMENT and CONSTANT_ALIGNMENT.)
4075    FIXME: We currently cannot guarantee this for objects on the stack
4076    because assign_parm_setup_stack calls assign_stack_local with the
4077    alignment of the parameter mode and in that case the alignment never
4078    gets adjusted by LOCAL_ALIGNMENT. */
4079 static int
4080 store_with_one_insn_p (rtx mem)
4081 {
4082   rtx addr = XEXP (mem, 0);
4083   if (GET_MODE (mem) == BLKmode)
4084     return 0;
4085   /* Only static objects. */
4086   if (GET_CODE (addr) == SYMBOL_REF)
4087     {
4088       /* We use the associated declaration to make sure the access is
4089          referring to the whole object.
4090          We check