OSDN Git Service

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