OSDN Git Service

f96326842b1ff1d2a70936e0f123e0e3ee0f5e21
[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 static int spu_builtin_vectorization_cost (bool);
137
138 extern const char *reg_names[];
139 rtx spu_compare_op0, spu_compare_op1;
140
141 enum spu_immediate {
142   SPU_NONE,
143   SPU_IL,
144   SPU_ILA,
145   SPU_ILH,
146   SPU_ILHU,
147   SPU_ORI,
148   SPU_ORHI,
149   SPU_ORBI,
150   SPU_IOHL
151 };
152 enum immediate_class
153 {
154   IC_POOL,                      /* constant pool */
155   IC_IL1,                       /* one il* instruction */
156   IC_IL2,                       /* both ilhu and iohl instructions */
157   IC_IL1s,                      /* one il* instruction */
158   IC_IL2s,                      /* both ilhu and iohl instructions */
159   IC_FSMBI,                     /* the fsmbi instruction */
160   IC_CPAT,                      /* one of the c*d instructions */
161   IC_FSMBI2                     /* fsmbi plus 1 other instruction */
162 };
163
164 static enum spu_immediate which_immediate_load (HOST_WIDE_INT val);
165 static enum spu_immediate which_logical_immediate (HOST_WIDE_INT val);
166 static int cpat_info(unsigned char *arr, int size, int *prun, int *pstart);
167 static enum immediate_class classify_immediate (rtx op,
168                                                 enum machine_mode mode);
169
170 /* Built in types.  */
171 tree spu_builtin_types[SPU_BTI_MAX];
172 \f
173 /*  TARGET overrides.  */
174
175 #undef TARGET_INIT_BUILTINS
176 #define TARGET_INIT_BUILTINS spu_init_builtins
177
178 #undef TARGET_EXPAND_BUILTIN
179 #define TARGET_EXPAND_BUILTIN spu_expand_builtin
180
181 #undef TARGET_EH_RETURN_FILTER_MODE
182 #define TARGET_EH_RETURN_FILTER_MODE spu_eh_return_filter_mode
183
184 /* The .8byte directive doesn't seem to work well for a 32 bit
185    architecture. */
186 #undef TARGET_ASM_UNALIGNED_DI_OP
187 #define TARGET_ASM_UNALIGNED_DI_OP NULL
188
189 #undef TARGET_RTX_COSTS
190 #define TARGET_RTX_COSTS spu_rtx_costs
191
192 #undef TARGET_ADDRESS_COST
193 #define TARGET_ADDRESS_COST hook_int_rtx_0
194
195 #undef TARGET_SCHED_ISSUE_RATE
196 #define TARGET_SCHED_ISSUE_RATE spu_sched_issue_rate
197
198 #undef TARGET_SCHED_VARIABLE_ISSUE
199 #define TARGET_SCHED_VARIABLE_ISSUE spu_sched_variable_issue
200
201 #undef TARGET_SCHED_ADJUST_PRIORITY
202 #define TARGET_SCHED_ADJUST_PRIORITY spu_sched_adjust_priority
203
204 #undef TARGET_SCHED_ADJUST_COST
205 #define TARGET_SCHED_ADJUST_COST spu_sched_adjust_cost
206
207 const struct attribute_spec spu_attribute_table[];
208 #undef  TARGET_ATTRIBUTE_TABLE
209 #define TARGET_ATTRIBUTE_TABLE spu_attribute_table
210
211 #undef TARGET_ASM_INTEGER
212 #define TARGET_ASM_INTEGER spu_assemble_integer
213
214 #undef TARGET_SCALAR_MODE_SUPPORTED_P
215 #define TARGET_SCALAR_MODE_SUPPORTED_P  spu_scalar_mode_supported_p
216
217 #undef TARGET_VECTOR_MODE_SUPPORTED_P
218 #define TARGET_VECTOR_MODE_SUPPORTED_P  spu_vector_mode_supported_p
219
220 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
221 #define TARGET_FUNCTION_OK_FOR_SIBCALL spu_function_ok_for_sibcall
222
223 #undef TARGET_ASM_GLOBALIZE_LABEL
224 #define TARGET_ASM_GLOBALIZE_LABEL spu_asm_globalize_label
225
226 #undef TARGET_PASS_BY_REFERENCE
227 #define TARGET_PASS_BY_REFERENCE spu_pass_by_reference
228
229 #undef TARGET_MUST_PASS_IN_STACK
230 #define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size
231
232 #undef TARGET_BUILD_BUILTIN_VA_LIST
233 #define TARGET_BUILD_BUILTIN_VA_LIST spu_build_builtin_va_list
234
235 #undef TARGET_SETUP_INCOMING_VARARGS
236 #define TARGET_SETUP_INCOMING_VARARGS spu_setup_incoming_varargs
237
238 #undef TARGET_MACHINE_DEPENDENT_REORG
239 #define TARGET_MACHINE_DEPENDENT_REORG spu_machine_dependent_reorg
240
241 #undef TARGET_GIMPLIFY_VA_ARG_EXPR
242 #define TARGET_GIMPLIFY_VA_ARG_EXPR spu_gimplify_va_arg_expr
243
244 #undef TARGET_DEFAULT_TARGET_FLAGS
245 #define TARGET_DEFAULT_TARGET_FLAGS (TARGET_DEFAULT)
246
247 #undef TARGET_INIT_LIBFUNCS
248 #define TARGET_INIT_LIBFUNCS spu_init_libfuncs
249
250 #undef TARGET_RETURN_IN_MEMORY
251 #define TARGET_RETURN_IN_MEMORY spu_return_in_memory
252
253 #undef  TARGET_ENCODE_SECTION_INFO
254 #define TARGET_ENCODE_SECTION_INFO spu_encode_section_info
255
256 #undef TARGET_VECTORIZE_BUILTIN_MUL_WIDEN_EVEN
257 #define TARGET_VECTORIZE_BUILTIN_MUL_WIDEN_EVEN spu_builtin_mul_widen_even
258
259 #undef TARGET_VECTORIZE_BUILTIN_MUL_WIDEN_ODD
260 #define TARGET_VECTORIZE_BUILTIN_MUL_WIDEN_ODD spu_builtin_mul_widen_odd
261
262 #undef TARGET_VECTORIZE_BUILTIN_MASK_FOR_LOAD
263 #define TARGET_VECTORIZE_BUILTIN_MASK_FOR_LOAD spu_builtin_mask_for_load
264
265 #undef TARGET_VECTORIZE_BUILTIN_VECTORIZATION_COST
266 #define TARGET_VECTORIZE_BUILTIN_VECTORIZATION_COST spu_builtin_vectorization_cost
267
268 struct gcc_target targetm = TARGET_INITIALIZER;
269
270 void
271 spu_optimization_options (int level ATTRIBUTE_UNUSED, int size ATTRIBUTE_UNUSED)
272 {
273   /* Override some of the default param values.  With so many registers
274      larger values are better for these params.  */
275   MAX_PENDING_LIST_LENGTH = 128;
276
277   /* With so many registers this is better on by default. */
278   flag_rename_registers = 1;
279 }
280
281 /* Sometimes certain combinations of command options do not make sense
282    on a particular target machine.  You can define a macro
283    OVERRIDE_OPTIONS to take account of this. This macro, if defined, is
284    executed once just after all the command options have been parsed.  */
285 void
286 spu_override_options (void)
287 {
288   /* Small loops will be unpeeled at -O3.  For SPU it is more important
289      to keep code small by default.  */
290   if (!flag_unroll_loops && !flag_peel_loops
291       && !PARAM_SET_P (PARAM_MAX_COMPLETELY_PEEL_TIMES))
292     PARAM_VALUE (PARAM_MAX_COMPLETELY_PEEL_TIMES) = 1;
293
294   flag_omit_frame_pointer = 1;
295
296   if (align_functions < 8)
297     align_functions = 8;
298
299   if (spu_fixed_range_string)
300     fix_range (spu_fixed_range_string);
301 }
302 \f
303 /* Handle an attribute requiring a FUNCTION_DECL; arguments as in
304    struct attribute_spec.handler.  */
305
306 /*  Table of machine attributes.  */
307 const struct attribute_spec spu_attribute_table[] =
308 {
309   /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
310   { "naked",          0, 0, true,  false, false, spu_handle_fndecl_attribute },
311   { "spu_vector",     0, 0, false, true,  false, spu_handle_vector_attribute },
312   { NULL,             0, 0, false, false, false, NULL }
313 };
314
315 /* True if MODE is valid for the target.  By "valid", we mean able to
316    be manipulated in non-trivial ways.  In particular, this means all
317    the arithmetic is supported.  */
318 static bool
319 spu_scalar_mode_supported_p (enum machine_mode mode)
320 {
321   switch (mode)
322     {
323     case QImode:
324     case HImode:
325     case SImode:
326     case SFmode:
327     case DImode:
328     case TImode:
329     case DFmode:
330       return true;
331
332     default:
333       return false;
334     }
335 }
336
337 /* Similarly for vector modes.  "Supported" here is less strict.  At
338    least some operations are supported; need to check optabs or builtins
339    for further details.  */
340 static bool
341 spu_vector_mode_supported_p (enum machine_mode mode)
342 {
343   switch (mode)
344     {
345     case V16QImode:
346     case V8HImode:
347     case V4SImode:
348     case V2DImode:
349     case V4SFmode:
350     case V2DFmode:
351       return true;
352
353     default:
354       return false;
355     }
356 }
357
358 /* GCC assumes that in a paradoxical SUBREG the inner mode occupies the
359    least significant bytes of the outer mode.  This function returns
360    TRUE for the SUBREG's where this is correct.  */
361 int
362 valid_subreg (rtx op)
363 {
364   enum machine_mode om = GET_MODE (op);
365   enum machine_mode im = GET_MODE (SUBREG_REG (op));
366   return om != VOIDmode && im != VOIDmode
367     && (GET_MODE_SIZE (im) == GET_MODE_SIZE (om)
368         || (GET_MODE_SIZE (im) <= 4 && GET_MODE_SIZE (om) <= 4));
369 }
370
371 /* When insv and ext[sz]v ar passed a TI SUBREG, we want to strip it off
372    and adjust the start offset.  */
373 static rtx
374 adjust_operand (rtx op, HOST_WIDE_INT * start)
375 {
376   enum machine_mode mode;
377   int op_size;
378   /* Strip any SUBREG */
379   if (GET_CODE (op) == SUBREG)
380     {
381       if (start)
382         *start -=
383           GET_MODE_BITSIZE (GET_MODE (op)) -
384           GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (op)));
385       op = SUBREG_REG (op);
386     }
387   /* If it is smaller than SI, assure a SUBREG */
388   op_size = GET_MODE_BITSIZE (GET_MODE (op));
389   if (op_size < 32)
390     {
391       if (start)
392         *start += 32 - op_size;
393       op_size = 32;
394     }
395   /* If it is not a MODE_INT (and/or it is smaller than SI) add a SUBREG. */
396   mode = mode_for_size (op_size, MODE_INT, 0);
397   if (mode != GET_MODE (op))
398     op = gen_rtx_SUBREG (mode, op, 0);
399   return op;
400 }
401
402 void
403 spu_expand_extv (rtx ops[], int unsignedp)
404 {
405   HOST_WIDE_INT width = INTVAL (ops[2]);
406   HOST_WIDE_INT start = INTVAL (ops[3]);
407   HOST_WIDE_INT src_size, dst_size;
408   enum machine_mode src_mode, dst_mode;
409   rtx dst = ops[0], src = ops[1];
410   rtx s;
411
412   dst = adjust_operand (ops[0], 0);
413   dst_mode = GET_MODE (dst);
414   dst_size = GET_MODE_BITSIZE (GET_MODE (dst));
415
416   src = adjust_operand (src, &start);
417   src_mode = GET_MODE (src);
418   src_size = GET_MODE_BITSIZE (GET_MODE (src));
419
420   if (start > 0)
421     {
422       s = gen_reg_rtx (src_mode);
423       switch (src_mode)
424         {
425         case SImode:
426           emit_insn (gen_ashlsi3 (s, src, GEN_INT (start)));
427           break;
428         case DImode:
429           emit_insn (gen_ashldi3 (s, src, GEN_INT (start)));
430           break;
431         case TImode:
432           emit_insn (gen_ashlti3 (s, src, GEN_INT (start)));
433           break;
434         default:
435           abort ();
436         }
437       src = s;
438     }
439
440   if (width < src_size)
441     {
442       rtx pat;
443       int icode;
444       switch (src_mode)
445         {
446         case SImode:
447           icode = unsignedp ? CODE_FOR_lshrsi3 : CODE_FOR_ashrsi3;
448           break;
449         case DImode:
450           icode = unsignedp ? CODE_FOR_lshrdi3 : CODE_FOR_ashrdi3;
451           break;
452         case TImode:
453           icode = unsignedp ? CODE_FOR_lshrti3 : CODE_FOR_ashrti3;
454           break;
455         default:
456           abort ();
457         }
458       s = gen_reg_rtx (src_mode);
459       pat = GEN_FCN (icode) (s, src, GEN_INT (src_size - width));
460       emit_insn (pat);
461       src = s;
462     }
463
464   convert_move (dst, src, unsignedp);
465 }
466
467 void
468 spu_expand_insv (rtx ops[])
469 {
470   HOST_WIDE_INT width = INTVAL (ops[1]);
471   HOST_WIDE_INT start = INTVAL (ops[2]);
472   HOST_WIDE_INT maskbits;
473   enum machine_mode dst_mode, src_mode;
474   rtx dst = ops[0], src = ops[3];
475   int dst_size, src_size;
476   rtx mask;
477   rtx shift_reg;
478   int shift;
479
480
481   if (GET_CODE (ops[0]) == MEM)
482     dst = gen_reg_rtx (TImode);
483   else
484     dst = adjust_operand (dst, &start);
485   dst_mode = GET_MODE (dst);
486   dst_size = GET_MODE_BITSIZE (GET_MODE (dst));
487
488   if (CONSTANT_P (src))
489     {
490       enum machine_mode m =
491         (width <= 32 ? SImode : width <= 64 ? DImode : TImode);
492       src = force_reg (m, convert_to_mode (m, src, 0));
493     }
494   src = adjust_operand (src, 0);
495   src_mode = GET_MODE (src);
496   src_size = GET_MODE_BITSIZE (GET_MODE (src));
497
498   mask = gen_reg_rtx (dst_mode);
499   shift_reg = gen_reg_rtx (dst_mode);
500   shift = dst_size - start - width;
501
502   /* It's not safe to use subreg here because the compiler assumes
503      that the SUBREG_REG is right justified in the SUBREG. */
504   convert_move (shift_reg, src, 1);
505
506   if (shift > 0)
507     {
508       switch (dst_mode)
509         {
510         case SImode:
511           emit_insn (gen_ashlsi3 (shift_reg, shift_reg, GEN_INT (shift)));
512           break;
513         case DImode:
514           emit_insn (gen_ashldi3 (shift_reg, shift_reg, GEN_INT (shift)));
515           break;
516         case TImode:
517           emit_insn (gen_ashlti3 (shift_reg, shift_reg, GEN_INT (shift)));
518           break;
519         default:
520           abort ();
521         }
522     }
523   else if (shift < 0)
524     abort ();
525
526   switch (dst_size)
527     {
528     case 32:
529       maskbits = (-1ll << (32 - width - start));
530       if (start)
531         maskbits += (1ll << (32 - start));
532       emit_move_insn (mask, GEN_INT (maskbits));
533       break;
534     case 64:
535       maskbits = (-1ll << (64 - width - start));
536       if (start)
537         maskbits += (1ll << (64 - start));
538       emit_move_insn (mask, GEN_INT (maskbits));
539       break;
540     case 128:
541       {
542         unsigned char arr[16];
543         int i = start / 8;
544         memset (arr, 0, sizeof (arr));
545         arr[i] = 0xff >> (start & 7);
546         for (i++; i <= (start + width - 1) / 8; i++)
547           arr[i] = 0xff;
548         arr[i - 1] &= 0xff << (7 - ((start + width - 1) & 7));
549         emit_move_insn (mask, array_to_constant (TImode, arr));
550       }
551       break;
552     default:
553       abort ();
554     }
555   if (GET_CODE (ops[0]) == MEM)
556     {
557       rtx aligned = gen_reg_rtx (SImode);
558       rtx low = gen_reg_rtx (SImode);
559       rtx addr = gen_reg_rtx (SImode);
560       rtx rotl = gen_reg_rtx (SImode);
561       rtx mask0 = gen_reg_rtx (TImode);
562       rtx mem;
563
564       emit_move_insn (addr, XEXP (ops[0], 0));
565       emit_insn (gen_andsi3 (aligned, addr, GEN_INT (-16)));
566       emit_insn (gen_andsi3 (low, addr, GEN_INT (15)));
567       emit_insn (gen_negsi2 (rotl, low));
568       emit_insn (gen_rotqby_ti (shift_reg, shift_reg, rotl));
569       emit_insn (gen_rotqmby_ti (mask0, mask, rotl));
570       mem = change_address (ops[0], TImode, aligned);
571       set_mem_alias_set (mem, 0);
572       emit_move_insn (dst, mem);
573       emit_insn (gen_selb (dst, dst, shift_reg, mask0));
574       emit_move_insn (mem, dst);
575       if (start + width > MEM_ALIGN (ops[0]))
576         {
577           rtx shl = gen_reg_rtx (SImode);
578           rtx mask1 = gen_reg_rtx (TImode);
579           rtx dst1 = gen_reg_rtx (TImode);
580           rtx mem1;
581           emit_insn (gen_subsi3 (shl, GEN_INT (16), low));
582           emit_insn (gen_shlqby_ti (mask1, mask, shl));
583           mem1 = adjust_address (mem, TImode, 16);
584           set_mem_alias_set (mem1, 0);
585           emit_move_insn (dst1, mem1);
586           emit_insn (gen_selb (dst1, dst1, shift_reg, mask1));
587           emit_move_insn (mem1, dst1);
588         }
589     }
590   else
591     emit_insn (gen_selb (dst, dst, shift_reg, mask));
592 }
593
594
595 int
596 spu_expand_block_move (rtx ops[])
597 {
598   HOST_WIDE_INT bytes, align, offset;
599   rtx src, dst, sreg, dreg, target;
600   int i;
601   if (GET_CODE (ops[2]) != CONST_INT
602       || GET_CODE (ops[3]) != CONST_INT
603       || INTVAL (ops[2]) > (HOST_WIDE_INT) (MOVE_RATIO * 8))
604     return 0;
605
606   bytes = INTVAL (ops[2]);
607   align = INTVAL (ops[3]);
608
609   if (bytes <= 0)
610     return 1;
611
612   dst = ops[0];
613   src = ops[1];
614
615   if (align == 16)
616     {
617       for (offset = 0; offset + 16 <= bytes; offset += 16)
618         {
619           dst = adjust_address (ops[0], V16QImode, offset);
620           src = adjust_address (ops[1], V16QImode, offset);
621           emit_move_insn (dst, src);
622         }
623       if (offset < bytes)
624         {
625           rtx mask;
626           unsigned char arr[16] = { 0 };
627           for (i = 0; i < bytes - offset; i++)
628             arr[i] = 0xff;
629           dst = adjust_address (ops[0], V16QImode, offset);
630           src = adjust_address (ops[1], V16QImode, offset);
631           mask = gen_reg_rtx (V16QImode);
632           sreg = gen_reg_rtx (V16QImode);
633           dreg = gen_reg_rtx (V16QImode);
634           target = gen_reg_rtx (V16QImode);
635           emit_move_insn (mask, array_to_constant (V16QImode, arr));
636           emit_move_insn (dreg, dst);
637           emit_move_insn (sreg, src);
638           emit_insn (gen_selb (target, dreg, sreg, mask));
639           emit_move_insn (dst, target);
640         }
641       return 1;
642     }
643   return 0;
644 }
645
646 enum spu_comp_code
647 { SPU_EQ, SPU_GT, SPU_GTU };
648
649
650 int spu_comp_icode[8][3] = {
651   {CODE_FOR_ceq_qi, CODE_FOR_cgt_qi, CODE_FOR_clgt_qi},
652   {CODE_FOR_ceq_hi, CODE_FOR_cgt_hi, CODE_FOR_clgt_hi},
653   {CODE_FOR_ceq_si, CODE_FOR_cgt_si, CODE_FOR_clgt_si},
654   {CODE_FOR_ceq_di, CODE_FOR_cgt_di, CODE_FOR_clgt_di},
655   {CODE_FOR_ceq_ti, CODE_FOR_cgt_ti, CODE_FOR_clgt_ti},
656   {CODE_FOR_ceq_sf, CODE_FOR_cgt_sf, 0},
657   {0, 0, 0},
658   {CODE_FOR_ceq_vec, 0, 0},
659 };
660
661 /* Generate a compare for CODE.  Return a brand-new rtx that represents
662    the result of the compare.   GCC can figure this out too if we don't
663    provide all variations of compares, but GCC always wants to use
664    WORD_MODE, we can generate better code in most cases if we do it
665    ourselves.  */
666 void
667 spu_emit_branch_or_set (int is_set, enum rtx_code code, rtx operands[])
668 {
669   int reverse_compare = 0;
670   int reverse_test = 0;
671   rtx compare_result;
672   rtx comp_rtx;
673   rtx target = operands[0];
674   enum machine_mode comp_mode;
675   enum machine_mode op_mode;
676   enum spu_comp_code scode;
677   int index;
678
679   /* When spu_compare_op1 is a CONST_INT change (X >= C) to (X > C-1),
680      and so on, to keep the constant in operand 1. */
681   if (GET_CODE (spu_compare_op1) == CONST_INT)
682     {
683       HOST_WIDE_INT val = INTVAL (spu_compare_op1) - 1;
684       if (trunc_int_for_mode (val, GET_MODE (spu_compare_op0)) == val)
685         switch (code)
686           {
687           case GE:
688             spu_compare_op1 = GEN_INT (val);
689             code = GT;
690             break;
691           case LT:
692             spu_compare_op1 = GEN_INT (val);
693             code = LE;
694             break;
695           case GEU:
696             spu_compare_op1 = GEN_INT (val);
697             code = GTU;
698             break;
699           case LTU:
700             spu_compare_op1 = GEN_INT (val);
701             code = LEU;
702             break;
703           default:
704             break;
705           }
706     }
707
708   switch (code)
709     {
710     case GE:
711       reverse_compare = 1;
712       reverse_test = 1;
713       scode = SPU_GT;
714       break;
715     case LE:
716       reverse_compare = 0;
717       reverse_test = 1;
718       scode = SPU_GT;
719       break;
720     case LT:
721       reverse_compare = 1;
722       reverse_test = 0;
723       scode = SPU_GT;
724       break;
725     case GEU:
726       reverse_compare = 1;
727       reverse_test = 1;
728       scode = SPU_GTU;
729       break;
730     case LEU:
731       reverse_compare = 0;
732       reverse_test = 1;
733       scode = SPU_GTU;
734       break;
735     case LTU:
736       reverse_compare = 1;
737       reverse_test = 0;
738       scode = SPU_GTU;
739       break;
740     case NE:
741       reverse_compare = 0;
742       reverse_test = 1;
743       scode = SPU_EQ;
744       break;
745
746     case EQ:
747       scode = SPU_EQ;
748       break;
749     case GT:
750       scode = SPU_GT;
751       break;
752     case GTU:
753       scode = SPU_GTU;
754       break;
755     default:
756       scode = SPU_EQ;
757       break;
758     }
759
760   comp_mode = SImode;
761   op_mode = GET_MODE (spu_compare_op0);
762
763   switch (op_mode)
764     {
765     case QImode:
766       index = 0;
767       comp_mode = QImode;
768       break;
769     case HImode:
770       index = 1;
771       comp_mode = HImode;
772       break;
773     case SImode:
774       index = 2;
775       break;
776     case DImode:
777       index = 3;
778       break;
779     case TImode:
780       index = 4;
781       break;
782     case SFmode:
783       index = 5;
784       break;
785     case DFmode:
786       index = 6;
787       break;
788     case V16QImode:
789     case V8HImode:
790     case V4SImode:
791     case V2DImode:
792     case V4SFmode:
793     case V2DFmode:
794       index = 7;
795       break;
796     default:
797       abort ();
798     }
799
800   if (GET_MODE (spu_compare_op1) == DFmode)
801     {
802       rtx reg = gen_reg_rtx (DFmode);
803       if (!flag_unsafe_math_optimizations
804           || (scode != SPU_GT && scode != SPU_EQ))
805         abort ();
806       if (reverse_compare)
807         emit_insn (gen_subdf3 (reg, spu_compare_op1, spu_compare_op0));
808       else
809         emit_insn (gen_subdf3 (reg, spu_compare_op0, spu_compare_op1));
810       reverse_compare = 0;
811       spu_compare_op0 = reg;
812       spu_compare_op1 = CONST0_RTX (DFmode);
813     }
814
815   if (is_set == 0 && spu_compare_op1 == const0_rtx
816       && (GET_MODE (spu_compare_op0) == SImode
817           || GET_MODE (spu_compare_op0) == HImode) && scode == SPU_EQ)
818     {
819       /* Don't need to set a register with the result when we are 
820          comparing against zero and branching. */
821       reverse_test = !reverse_test;
822       compare_result = spu_compare_op0;
823     }
824   else
825     {
826       compare_result = gen_reg_rtx (comp_mode);
827
828       if (reverse_compare)
829         {
830           rtx t = spu_compare_op1;
831           spu_compare_op1 = spu_compare_op0;
832           spu_compare_op0 = t;
833         }
834
835       if (spu_comp_icode[index][scode] == 0)
836         abort ();
837
838       if (!(*insn_data[spu_comp_icode[index][scode]].operand[1].predicate)
839           (spu_compare_op0, op_mode))
840         spu_compare_op0 = force_reg (op_mode, spu_compare_op0);
841       if (!(*insn_data[spu_comp_icode[index][scode]].operand[2].predicate)
842           (spu_compare_op1, op_mode))
843         spu_compare_op1 = force_reg (op_mode, spu_compare_op1);
844       comp_rtx = GEN_FCN (spu_comp_icode[index][scode]) (compare_result,
845                                                          spu_compare_op0,
846                                                          spu_compare_op1);
847       if (comp_rtx == 0)
848         abort ();
849       emit_insn (comp_rtx);
850
851     }
852
853   if (is_set == 0)
854     {
855       rtx bcomp;
856       rtx loc_ref;
857
858       /* We don't have branch on QI compare insns, so we convert the
859          QI compare result to a HI result. */
860       if (comp_mode == QImode)
861         {
862           rtx old_res = compare_result;
863           compare_result = gen_reg_rtx (HImode);
864           comp_mode = HImode;
865           emit_insn (gen_extendqihi2 (compare_result, old_res));
866         }
867
868       if (reverse_test)
869         bcomp = gen_rtx_EQ (comp_mode, compare_result, const0_rtx);
870       else
871         bcomp = gen_rtx_NE (comp_mode, compare_result, const0_rtx);
872
873       loc_ref = gen_rtx_LABEL_REF (VOIDmode, target);
874       emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx,
875                                    gen_rtx_IF_THEN_ELSE (VOIDmode, bcomp,
876                                                          loc_ref, pc_rtx)));
877     }
878   else if (is_set == 2)
879     {
880       int compare_size = GET_MODE_BITSIZE (comp_mode);
881       int target_size = GET_MODE_BITSIZE (GET_MODE (target));
882       enum machine_mode mode = mode_for_size (target_size, MODE_INT, 0);
883       rtx select_mask;
884       rtx op_t = operands[2];
885       rtx op_f = operands[3];
886
887       /* The result of the comparison can be SI, HI or QI mode.  Create a
888          mask based on that result. */
889       if (target_size > compare_size)
890         {
891           select_mask = gen_reg_rtx (mode);
892           emit_insn (gen_extend_compare (select_mask, compare_result));
893         }
894       else if (target_size < compare_size)
895         select_mask =
896           gen_rtx_SUBREG (mode, compare_result,
897                           (compare_size - target_size) / BITS_PER_UNIT);
898       else if (comp_mode != mode)
899         select_mask = gen_rtx_SUBREG (mode, compare_result, 0);
900       else
901         select_mask = compare_result;
902
903       if (GET_MODE (target) != GET_MODE (op_t)
904           || GET_MODE (target) != GET_MODE (op_f))
905         abort ();
906
907       if (reverse_test)
908         emit_insn (gen_selb (target, op_t, op_f, select_mask));
909       else
910         emit_insn (gen_selb (target, op_f, op_t, select_mask));
911     }
912   else
913     {
914       if (reverse_test)
915         emit_insn (gen_rtx_SET (VOIDmode, compare_result,
916                                 gen_rtx_NOT (comp_mode, compare_result)));
917       if (GET_MODE (target) == SImode && GET_MODE (compare_result) == HImode)
918         emit_insn (gen_extendhisi2 (target, compare_result));
919       else if (GET_MODE (target) == SImode
920                && GET_MODE (compare_result) == QImode)
921         emit_insn (gen_extend_compare (target, compare_result));
922       else
923         emit_move_insn (target, compare_result);
924     }
925 }
926
927 HOST_WIDE_INT
928 const_double_to_hwint (rtx x)
929 {
930   HOST_WIDE_INT val;
931   REAL_VALUE_TYPE rv;
932   if (GET_MODE (x) == SFmode)
933     {
934       REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
935       REAL_VALUE_TO_TARGET_SINGLE (rv, val);
936     }
937   else if (GET_MODE (x) == DFmode)
938     {
939       long l[2];
940       REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
941       REAL_VALUE_TO_TARGET_DOUBLE (rv, l);
942       val = l[0];
943       val = (val << 32) | (l[1] & 0xffffffff);
944     }
945   else
946     abort ();
947   return val;
948 }
949
950 rtx
951 hwint_to_const_double (enum machine_mode mode, HOST_WIDE_INT v)
952 {
953   long tv[2];
954   REAL_VALUE_TYPE rv;
955   gcc_assert (mode == SFmode || mode == DFmode);
956
957   if (mode == SFmode)
958     tv[0] = (v << 32) >> 32;
959   else if (mode == DFmode)
960     {
961       tv[1] = (v << 32) >> 32;
962       tv[0] = v >> 32;
963     }
964   real_from_target (&rv, tv, mode);
965   return CONST_DOUBLE_FROM_REAL_VALUE (rv, mode);
966 }
967
968 void
969 print_operand_address (FILE * file, register rtx addr)
970 {
971   rtx reg;
972   rtx offset;
973
974   if (GET_CODE (addr) == AND
975       && GET_CODE (XEXP (addr, 1)) == CONST_INT
976       && INTVAL (XEXP (addr, 1)) == -16)
977     addr = XEXP (addr, 0);
978
979   switch (GET_CODE (addr))
980     {
981     case REG:
982       fprintf (file, "0(%s)", reg_names[REGNO (addr)]);
983       break;
984
985     case PLUS:
986       reg = XEXP (addr, 0);
987       offset = XEXP (addr, 1);
988       if (GET_CODE (offset) == REG)
989         {
990           fprintf (file, "%s,%s", reg_names[REGNO (reg)],
991                    reg_names[REGNO (offset)]);
992         }
993       else if (GET_CODE (offset) == CONST_INT)
994         {
995           fprintf (file, HOST_WIDE_INT_PRINT_DEC "(%s)",
996                    INTVAL (offset), reg_names[REGNO (reg)]);
997         }
998       else
999         abort ();
1000       break;
1001
1002     case CONST:
1003     case LABEL_REF:
1004     case SYMBOL_REF:
1005     case CONST_INT:
1006       output_addr_const (file, addr);
1007       break;
1008
1009     default:
1010       debug_rtx (addr);
1011       abort ();
1012     }
1013 }
1014
1015 void
1016 print_operand (FILE * file, rtx x, int code)
1017 {
1018   enum machine_mode mode = GET_MODE (x);
1019   HOST_WIDE_INT val;
1020   unsigned char arr[16];
1021   int xcode = GET_CODE (x);
1022   int i, info;
1023   if (GET_MODE (x) == VOIDmode)
1024     switch (code)
1025       {
1026       case 'L':                 /* 128 bits, signed */
1027       case 'm':                 /* 128 bits, signed */
1028       case 'T':                 /* 128 bits, signed */
1029       case 't':                 /* 128 bits, signed */
1030         mode = TImode;
1031         break;
1032       case 'K':                 /* 64 bits, signed */
1033       case 'k':                 /* 64 bits, signed */
1034       case 'D':                 /* 64 bits, signed */
1035       case 'd':                 /* 64 bits, signed */
1036         mode = DImode;
1037         break;
1038       case 'J':                 /* 32 bits, signed */
1039       case 'j':                 /* 32 bits, signed */
1040       case 's':                 /* 32 bits, signed */
1041       case 'S':                 /* 32 bits, signed */
1042         mode = SImode;
1043         break;
1044       }
1045   switch (code)
1046     {
1047
1048     case 'j':                   /* 32 bits, signed */
1049     case 'k':                   /* 64 bits, signed */
1050     case 'm':                   /* 128 bits, signed */
1051       if (xcode == CONST_INT
1052           || xcode == CONST_DOUBLE || xcode == CONST_VECTOR)
1053         {
1054           gcc_assert (logical_immediate_p (x, mode));
1055           constant_to_array (mode, x, arr);
1056           val = (arr[0] << 24) | (arr[1] << 16) | (arr[2] << 8) | arr[3];
1057           val = trunc_int_for_mode (val, SImode);
1058           switch (which_logical_immediate (val))
1059           {
1060           case SPU_ORI:
1061             break;
1062           case SPU_ORHI:
1063             fprintf (file, "h");
1064             break;
1065           case SPU_ORBI:
1066             fprintf (file, "b");
1067             break;
1068           default:
1069             gcc_unreachable();
1070           }
1071         }
1072       else
1073         gcc_unreachable();
1074       return;
1075
1076     case 'J':                   /* 32 bits, signed */
1077     case 'K':                   /* 64 bits, signed */
1078     case 'L':                   /* 128 bits, signed */
1079       if (xcode == CONST_INT
1080           || xcode == CONST_DOUBLE || xcode == CONST_VECTOR)
1081         {
1082           gcc_assert (logical_immediate_p (x, mode)
1083                       || iohl_immediate_p (x, mode));
1084           constant_to_array (mode, x, arr);
1085           val = (arr[0] << 24) | (arr[1] << 16) | (arr[2] << 8) | arr[3];
1086           val = trunc_int_for_mode (val, SImode);
1087           switch (which_logical_immediate (val))
1088           {
1089           case SPU_ORI:
1090           case SPU_IOHL:
1091             break;
1092           case SPU_ORHI:
1093             val = trunc_int_for_mode (val, HImode);
1094             break;
1095           case SPU_ORBI:
1096             val = trunc_int_for_mode (val, QImode);
1097             break;
1098           default:
1099             gcc_unreachable();
1100           }
1101           fprintf (file, HOST_WIDE_INT_PRINT_DEC, val);
1102         }
1103       else
1104         gcc_unreachable();
1105       return;
1106
1107     case 't':                   /* 128 bits, signed */
1108     case 'd':                   /* 64 bits, signed */
1109     case 's':                   /* 32 bits, signed */
1110       if (CONSTANT_P (x))
1111         {
1112           enum immediate_class c = classify_immediate (x, mode);
1113           switch (c)
1114             {
1115             case IC_IL1:
1116               constant_to_array (mode, x, arr);
1117               val = (arr[0] << 24) | (arr[1] << 16) | (arr[2] << 8) | arr[3];
1118               val = trunc_int_for_mode (val, SImode);
1119               switch (which_immediate_load (val))
1120                 {
1121                 case SPU_IL:
1122                   break;
1123                 case SPU_ILA:
1124                   fprintf (file, "a");
1125                   break;
1126                 case SPU_ILH:
1127                   fprintf (file, "h");
1128                   break;
1129                 case SPU_ILHU:
1130                   fprintf (file, "hu");
1131                   break;
1132                 default:
1133                   gcc_unreachable ();
1134                 }
1135               break;
1136             case IC_CPAT:
1137               constant_to_array (mode, x, arr);
1138               cpat_info (arr, GET_MODE_SIZE (mode), &info, 0);
1139               if (info == 1)
1140                 fprintf (file, "b");
1141               else if (info == 2)
1142                 fprintf (file, "h");
1143               else if (info == 4)
1144                 fprintf (file, "w");
1145               else if (info == 8)
1146                 fprintf (file, "d");
1147               break;
1148             case IC_IL1s:
1149               if (xcode == CONST_VECTOR)
1150                 {
1151                   x = CONST_VECTOR_ELT (x, 0);
1152                   xcode = GET_CODE (x);
1153                 }
1154               if (xcode == SYMBOL_REF || xcode == LABEL_REF || xcode == CONST)
1155                 fprintf (file, "a");
1156               else if (xcode == HIGH)
1157                 fprintf (file, "hu");
1158               break;
1159             case IC_FSMBI:
1160             case IC_FSMBI2:
1161             case IC_IL2:
1162             case IC_IL2s:
1163             case IC_POOL:
1164               abort ();
1165             }
1166         }
1167       else
1168         gcc_unreachable ();
1169       return;
1170
1171     case 'T':                   /* 128 bits, signed */
1172     case 'D':                   /* 64 bits, signed */
1173     case 'S':                   /* 32 bits, signed */
1174       if (CONSTANT_P (x))
1175         {
1176           enum immediate_class c = classify_immediate (x, mode);
1177           switch (c)
1178             {
1179             case IC_IL1:
1180               constant_to_array (mode, x, arr);
1181               val = (arr[0] << 24) | (arr[1] << 16) | (arr[2] << 8) | arr[3];
1182               val = trunc_int_for_mode (val, SImode);
1183               switch (which_immediate_load (val))
1184                 {
1185                 case SPU_IL:
1186                 case SPU_ILA:
1187                   break;
1188                 case SPU_ILH:
1189                 case SPU_ILHU:
1190                   val = trunc_int_for_mode (((arr[0] << 8) | arr[1]), HImode);
1191                   break;
1192                 default:
1193                   gcc_unreachable ();
1194                 }
1195               fprintf (file, HOST_WIDE_INT_PRINT_DEC, val);
1196               break;
1197             case IC_FSMBI:
1198               constant_to_array (mode, x, arr);
1199               val = 0;
1200               for (i = 0; i < 16; i++)
1201                 {
1202                   val <<= 1;
1203                   val |= arr[i] & 1;
1204                 }
1205               print_operand (file, GEN_INT (val), 0);
1206               break;
1207             case IC_CPAT:
1208               constant_to_array (mode, x, arr);
1209               cpat_info (arr, GET_MODE_SIZE (mode), 0, &info);
1210               fprintf (file, HOST_WIDE_INT_PRINT_DEC, (HOST_WIDE_INT)info);
1211               break;
1212             case IC_IL1s:
1213               if (xcode == HIGH)
1214                 x = XEXP (x, 0);
1215               if (GET_CODE (x) == CONST_VECTOR)
1216                 x = CONST_VECTOR_ELT (x, 0);
1217               output_addr_const (file, x);
1218               if (xcode == HIGH)
1219                 fprintf (file, "@h");
1220               break;
1221             case IC_IL2:
1222             case IC_IL2s:
1223             case IC_FSMBI2:
1224             case IC_POOL:
1225               abort ();
1226             }
1227         }
1228       else
1229         gcc_unreachable ();
1230       return;
1231
1232     case 'C':
1233       if (xcode == CONST_INT)
1234         {
1235           /* Only 4 least significant bits are relevant for generate
1236              control word instructions. */
1237           fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x) & 15);
1238           return;
1239         }
1240       break;
1241
1242     case 'M':                   /* print code for c*d */
1243       if (GET_CODE (x) == CONST_INT)
1244         switch (INTVAL (x))
1245           {
1246           case 1:
1247             fprintf (file, "b");
1248             break;
1249           case 2:
1250             fprintf (file, "h");
1251             break;
1252           case 4:
1253             fprintf (file, "w");
1254             break;
1255           case 8:
1256             fprintf (file, "d");
1257             break;
1258           default:
1259             gcc_unreachable();
1260           }
1261       else
1262         gcc_unreachable();
1263       return;
1264
1265     case 'N':                   /* Negate the operand */
1266       if (xcode == CONST_INT)
1267         fprintf (file, HOST_WIDE_INT_PRINT_DEC, -INTVAL (x));
1268       else if (xcode == CONST_VECTOR)
1269         fprintf (file, HOST_WIDE_INT_PRINT_DEC,
1270                  -INTVAL (CONST_VECTOR_ELT (x, 0)));
1271       return;
1272
1273     case 'I':                   /* enable/disable interrupts */
1274       if (xcode == CONST_INT)
1275         fprintf (file, "%s",  INTVAL (x) == 0 ? "d" : "e");
1276       return;
1277
1278     case 'b':                   /* branch modifiers */
1279       if (xcode == REG)
1280         fprintf (file, "%s", GET_MODE (x) == HImode ? "h" : "");
1281       else if (COMPARISON_P (x))
1282         fprintf (file, "%s", xcode == NE ? "n" : "");
1283       return;
1284
1285     case 'i':                   /* indirect call */
1286       if (xcode == MEM)
1287         {
1288           if (GET_CODE (XEXP (x, 0)) == REG)
1289             /* Used in indirect function calls. */
1290             fprintf (file, "%s", reg_names[REGNO (XEXP (x, 0))]);
1291           else
1292             output_address (XEXP (x, 0));
1293         }
1294       return;
1295
1296     case 'p':                   /* load/store */
1297       if (xcode == MEM)
1298         {
1299           x = XEXP (x, 0);
1300           xcode = GET_CODE (x);
1301         }
1302       if (xcode == AND)
1303         {
1304           x = XEXP (x, 0);
1305           xcode = GET_CODE (x);
1306         }
1307       if (xcode == REG)
1308         fprintf (file, "d");
1309       else if (xcode == CONST_INT)
1310         fprintf (file, "a");
1311       else if (xcode == CONST || xcode == SYMBOL_REF || xcode == LABEL_REF)
1312         fprintf (file, "r");
1313       else if (xcode == PLUS || xcode == LO_SUM)
1314         {
1315           if (GET_CODE (XEXP (x, 1)) == REG)
1316             fprintf (file, "x");
1317           else
1318             fprintf (file, "d");
1319         }
1320       return;
1321
1322     case 'e':
1323       val = xcode == CONST_INT ? INTVAL (x) : INTVAL (CONST_VECTOR_ELT (x, 0));
1324       val &= 0x7;
1325       output_addr_const (file, GEN_INT (val));
1326       return;
1327
1328     case 'f':
1329       val = xcode == CONST_INT ? INTVAL (x) : INTVAL (CONST_VECTOR_ELT (x, 0));
1330       val &= 0x1f;
1331       output_addr_const (file, GEN_INT (val));
1332       return;
1333
1334     case 'g':
1335       val = xcode == CONST_INT ? INTVAL (x) : INTVAL (CONST_VECTOR_ELT (x, 0));
1336       val &= 0x3f;
1337       output_addr_const (file, GEN_INT (val));
1338       return;
1339
1340     case 'h':
1341       val = xcode == CONST_INT ? INTVAL (x) : INTVAL (CONST_VECTOR_ELT (x, 0));
1342       val = (val >> 3) & 0x1f;
1343       output_addr_const (file, GEN_INT (val));
1344       return;
1345
1346     case 'E':
1347       val = xcode == CONST_INT ? INTVAL (x) : INTVAL (CONST_VECTOR_ELT (x, 0));
1348       val = -val;
1349       val &= 0x7;
1350       output_addr_const (file, GEN_INT (val));
1351       return;
1352
1353     case 'F':
1354       val = xcode == CONST_INT ? INTVAL (x) : INTVAL (CONST_VECTOR_ELT (x, 0));
1355       val = -val;
1356       val &= 0x1f;
1357       output_addr_const (file, GEN_INT (val));
1358       return;
1359
1360     case 'G':
1361       val = xcode == CONST_INT ? INTVAL (x) : INTVAL (CONST_VECTOR_ELT (x, 0));
1362       val = -val;
1363       val &= 0x3f;
1364       output_addr_const (file, GEN_INT (val));
1365       return;
1366
1367     case 'H':
1368       val = xcode == CONST_INT ? INTVAL (x) : INTVAL (CONST_VECTOR_ELT (x, 0));
1369       val = -(val & -8ll);
1370       val = (val >> 3) & 0x1f;
1371       output_addr_const (file, GEN_INT (val));
1372       return;
1373
1374     case 0:
1375       if (xcode == REG)
1376         fprintf (file, "%s", reg_names[REGNO (x)]);
1377       else if (xcode == MEM)
1378         output_address (XEXP (x, 0));
1379       else if (xcode == CONST_VECTOR)
1380         print_operand (file, CONST_VECTOR_ELT (x, 0), 0);
1381       else
1382         output_addr_const (file, x);
1383       return;
1384
1385       /* unused letters
1386                       o qr  uvw yz
1387         AB            OPQR  UVWXYZ */
1388     default:
1389       output_operand_lossage ("invalid %%xn code");
1390     }
1391   gcc_unreachable ();
1392 }
1393
1394 extern char call_used_regs[];
1395
1396 /* For PIC mode we've reserved PIC_OFFSET_TABLE_REGNUM, which is a
1397    caller saved register.  For leaf functions it is more efficient to
1398    use a volatile register because we won't need to save and restore the
1399    pic register.  This routine is only valid after register allocation
1400    is completed, so we can pick an unused register.  */
1401 static rtx
1402 get_pic_reg (void)
1403 {
1404   rtx pic_reg = pic_offset_table_rtx;
1405   if (!reload_completed && !reload_in_progress)
1406     abort ();
1407   return pic_reg;
1408 }
1409
1410 /* Split constant addresses to handle cases that are too large. 
1411    Add in the pic register when in PIC mode.
1412    Split immediates that require more than 1 instruction. */
1413 int
1414 spu_split_immediate (rtx * ops)
1415 {
1416   enum machine_mode mode = GET_MODE (ops[0]);
1417   enum immediate_class c = classify_immediate (ops[1], mode);
1418
1419   switch (c)
1420     {
1421     case IC_IL2:
1422       {
1423         unsigned char arrhi[16];
1424         unsigned char arrlo[16];
1425         rtx to, hi, lo;
1426         int i;
1427         constant_to_array (mode, ops[1], arrhi);
1428         to = !can_create_pseudo_p () ? ops[0] : gen_reg_rtx (mode);
1429         for (i = 0; i < 16; i += 4)
1430           {
1431             arrlo[i + 2] = arrhi[i + 2];
1432             arrlo[i + 3] = arrhi[i + 3];
1433             arrlo[i + 0] = arrlo[i + 1] = 0;
1434             arrhi[i + 2] = arrhi[i + 3] = 0;
1435           }
1436         hi = array_to_constant (mode, arrhi);
1437         lo = array_to_constant (mode, arrlo);
1438         emit_move_insn (to, hi);
1439         emit_insn (gen_rtx_SET
1440                    (VOIDmode, ops[0], gen_rtx_IOR (mode, to, lo)));
1441         return 1;
1442       }
1443     case IC_FSMBI2:
1444       {
1445         unsigned char arr_fsmbi[16];
1446         unsigned char arr_andbi[16];
1447         rtx to, reg_fsmbi, reg_and;
1448         int i;
1449         enum machine_mode imode = mode;
1450         /* We need to do reals as ints because the constant used in the
1451          * AND might not be a legitimate real constant. */
1452         imode = int_mode_for_mode (mode);
1453         constant_to_array (mode, ops[1], arr_fsmbi);
1454         if (imode != mode)
1455           to = simplify_gen_subreg(imode, ops[0], GET_MODE (ops[0]), 0);
1456         else
1457           to = ops[0];
1458         for (i = 0; i < 16; i++)
1459           if (arr_fsmbi[i] != 0)
1460             {
1461               arr_andbi[0] = arr_fsmbi[i];
1462               arr_fsmbi[i] = 0xff;
1463             }
1464         for (i = 1; i < 16; i++)
1465           arr_andbi[i] = arr_andbi[0];
1466         reg_fsmbi = array_to_constant (imode, arr_fsmbi);
1467         reg_and = array_to_constant (imode, arr_andbi);
1468         emit_move_insn (to, reg_fsmbi);
1469         emit_insn (gen_rtx_SET
1470                    (VOIDmode, to, gen_rtx_AND (imode, to, reg_and)));
1471         return 1;
1472       }
1473     case IC_POOL:
1474       if (reload_in_progress || reload_completed)
1475         {
1476           rtx mem = force_const_mem (mode, ops[1]);
1477           if (TARGET_LARGE_MEM)
1478             {
1479               rtx addr = gen_rtx_REG (Pmode, REGNO (ops[0]));
1480               emit_move_insn (addr, XEXP (mem, 0));
1481               mem = replace_equiv_address (mem, addr);
1482             }
1483           emit_move_insn (ops[0], mem);
1484           return 1;
1485         }
1486       break;
1487     case IC_IL1s:
1488     case IC_IL2s:
1489       if (reload_completed && GET_CODE (ops[1]) != HIGH)
1490         {
1491           if (c == IC_IL2s)
1492             {
1493               emit_move_insn (ops[0], gen_rtx_HIGH (mode, ops[1]));
1494               emit_move_insn (ops[0], gen_rtx_LO_SUM (mode, ops[0], ops[1]));
1495             }
1496           else if (flag_pic)
1497             emit_insn (gen_pic (ops[0], ops[1]));
1498           if (flag_pic)
1499             {
1500               rtx pic_reg = get_pic_reg ();
1501               emit_insn (gen_addsi3 (ops[0], ops[0], pic_reg));
1502               current_function_uses_pic_offset_table = 1;
1503             }
1504           return flag_pic || c == IC_IL2s;
1505         }
1506       break;
1507     case IC_IL1:
1508     case IC_FSMBI:
1509     case IC_CPAT:
1510       break;
1511     }
1512   return 0;
1513 }
1514
1515 /* SAVING is TRUE when we are generating the actual load and store
1516    instructions for REGNO.  When determining the size of the stack
1517    needed for saving register we must allocate enough space for the
1518    worst case, because we don't always have the information early enough
1519    to not allocate it.  But we can at least eliminate the actual loads
1520    and stores during the prologue/epilogue.  */
1521 static int
1522 need_to_save_reg (int regno, int saving)
1523 {
1524   if (df_regs_ever_live_p (regno) && !call_used_regs[regno])
1525     return 1;
1526   if (flag_pic
1527       && regno == PIC_OFFSET_TABLE_REGNUM
1528       && (!saving || current_function_uses_pic_offset_table)
1529       && (!saving
1530           || !current_function_is_leaf || df_regs_ever_live_p (LAST_ARG_REGNUM)))
1531     return 1;
1532   return 0;
1533 }
1534
1535 /* This function is only correct starting with local register
1536    allocation */
1537 int
1538 spu_saved_regs_size (void)
1539 {
1540   int reg_save_size = 0;
1541   int regno;
1542
1543   for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; --regno)
1544     if (need_to_save_reg (regno, 0))
1545       reg_save_size += 0x10;
1546   return reg_save_size;
1547 }
1548
1549 static rtx
1550 frame_emit_store (int regno, rtx addr, HOST_WIDE_INT offset)
1551 {
1552   rtx reg = gen_rtx_REG (V4SImode, regno);
1553   rtx mem =
1554     gen_frame_mem (V4SImode, gen_rtx_PLUS (Pmode, addr, GEN_INT (offset)));
1555   return emit_insn (gen_movv4si (mem, reg));
1556 }
1557
1558 static rtx
1559 frame_emit_load (int regno, rtx addr, HOST_WIDE_INT offset)
1560 {
1561   rtx reg = gen_rtx_REG (V4SImode, regno);
1562   rtx mem =
1563     gen_frame_mem (V4SImode, gen_rtx_PLUS (Pmode, addr, GEN_INT (offset)));
1564   return emit_insn (gen_movv4si (reg, mem));
1565 }
1566
1567 /* This happens after reload, so we need to expand it.  */
1568 static rtx
1569 frame_emit_add_imm (rtx dst, rtx src, HOST_WIDE_INT imm, rtx scratch)
1570 {
1571   rtx insn;
1572   if (satisfies_constraint_K (GEN_INT (imm)))
1573     {
1574       insn = emit_insn (gen_addsi3 (dst, src, GEN_INT (imm)));
1575     }
1576   else
1577     {
1578       emit_insn (gen_movsi (scratch, gen_int_mode (imm, SImode)));
1579       insn = emit_insn (gen_addsi3 (dst, src, scratch));
1580       if (REGNO (src) == REGNO (scratch))
1581         abort ();
1582     }
1583   return insn;
1584 }
1585
1586 /* Return nonzero if this function is known to have a null epilogue.  */
1587
1588 int
1589 direct_return (void)
1590 {
1591   if (reload_completed)
1592     {
1593       if (cfun->static_chain_decl == 0
1594           && (spu_saved_regs_size ()
1595               + get_frame_size ()
1596               + current_function_outgoing_args_size
1597               + current_function_pretend_args_size == 0)
1598           && current_function_is_leaf)
1599         return 1;
1600     }
1601   return 0;
1602 }
1603
1604 /*
1605    The stack frame looks like this:
1606          +-------------+
1607          |  incoming   | 
1608       AP |    args     | 
1609          +-------------+
1610          | $lr save    |
1611          +-------------+
1612  prev SP | back chain  | 
1613          +-------------+
1614          |  var args   | 
1615          |  reg save   | current_function_pretend_args_size bytes
1616          +-------------+
1617          |    ...      | 
1618          | saved regs  | spu_saved_regs_size() bytes
1619          +-------------+
1620          |    ...      | 
1621       FP |   vars      | get_frame_size()  bytes
1622          +-------------+
1623          |    ...      | 
1624          |  outgoing   | 
1625          |    args     | current_function_outgoing_args_size bytes
1626          +-------------+
1627          | $lr of next |
1628          |   frame     | 
1629          +-------------+
1630       SP | back chain  | 
1631          +-------------+
1632
1633 */
1634 void
1635 spu_expand_prologue (void)
1636 {
1637   HOST_WIDE_INT size = get_frame_size (), offset, regno;
1638   HOST_WIDE_INT total_size;
1639   HOST_WIDE_INT saved_regs_size;
1640   rtx sp_reg = gen_rtx_REG (Pmode, STACK_POINTER_REGNUM);
1641   rtx scratch_reg_0, scratch_reg_1;
1642   rtx insn, real;
1643
1644   /* A NOTE_INSN_DELETED is supposed to be at the start and end of
1645      the "toplevel" insn chain.  */
1646   emit_note (NOTE_INSN_DELETED);
1647
1648   if (flag_pic && optimize == 0)
1649     current_function_uses_pic_offset_table = 1;
1650
1651   if (spu_naked_function_p (current_function_decl))
1652     return;
1653
1654   scratch_reg_0 = gen_rtx_REG (SImode, LAST_ARG_REGNUM + 1);
1655   scratch_reg_1 = gen_rtx_REG (SImode, LAST_ARG_REGNUM + 2);
1656
1657   saved_regs_size = spu_saved_regs_size ();
1658   total_size = size + saved_regs_size
1659     + current_function_outgoing_args_size
1660     + current_function_pretend_args_size;
1661
1662   if (!current_function_is_leaf
1663       || current_function_calls_alloca || total_size > 0)
1664     total_size += STACK_POINTER_OFFSET;
1665
1666   /* Save this first because code after this might use the link
1667      register as a scratch register. */
1668   if (!current_function_is_leaf)
1669     {
1670       insn = frame_emit_store (LINK_REGISTER_REGNUM, sp_reg, 16);
1671       RTX_FRAME_RELATED_P (insn) = 1;
1672     }
1673
1674   if (total_size > 0)
1675     {
1676       offset = -current_function_pretend_args_size;
1677       for (regno = 0; regno < FIRST_PSEUDO_REGISTER; ++regno)
1678         if (need_to_save_reg (regno, 1))
1679           {
1680             offset -= 16;
1681             insn = frame_emit_store (regno, sp_reg, offset);
1682             RTX_FRAME_RELATED_P (insn) = 1;
1683           }
1684     }
1685
1686   if (flag_pic && current_function_uses_pic_offset_table)
1687     {
1688       rtx pic_reg = get_pic_reg ();
1689       insn = emit_insn (gen_load_pic_offset (pic_reg, scratch_reg_0));
1690       insn = emit_insn (gen_subsi3 (pic_reg, pic_reg, scratch_reg_0));
1691     }
1692
1693   if (total_size > 0)
1694     {
1695       if (flag_stack_check)
1696         {
1697           /* We compare against total_size-1 because
1698              ($sp >= total_size) <=> ($sp > total_size-1) */
1699           rtx scratch_v4si = gen_rtx_REG (V4SImode, REGNO (scratch_reg_0));
1700           rtx sp_v4si = gen_rtx_REG (V4SImode, STACK_POINTER_REGNUM);
1701           rtx size_v4si = spu_const (V4SImode, total_size - 1);
1702           if (!satisfies_constraint_K (GEN_INT (total_size - 1)))
1703             {
1704               emit_move_insn (scratch_v4si, size_v4si);
1705               size_v4si = scratch_v4si;
1706             }
1707           emit_insn (gen_cgt_v4si (scratch_v4si, sp_v4si, size_v4si));
1708           emit_insn (gen_vec_extractv4si
1709                      (scratch_reg_0, scratch_v4si, GEN_INT (1)));
1710           emit_insn (gen_spu_heq (scratch_reg_0, GEN_INT (0)));
1711         }
1712
1713       /* Adjust the stack pointer, and make sure scratch_reg_0 contains
1714          the value of the previous $sp because we save it as the back
1715          chain. */
1716       if (total_size <= 2000)
1717         {
1718           /* In this case we save the back chain first. */
1719           insn = frame_emit_store (STACK_POINTER_REGNUM, sp_reg, -total_size);
1720           insn =
1721             frame_emit_add_imm (sp_reg, sp_reg, -total_size, scratch_reg_0);
1722         }
1723       else if (satisfies_constraint_K (GEN_INT (-total_size)))
1724         {
1725           insn = emit_move_insn (scratch_reg_0, sp_reg);
1726           insn =
1727             emit_insn (gen_addsi3 (sp_reg, sp_reg, GEN_INT (-total_size)));
1728         }
1729       else
1730         {
1731           insn = emit_move_insn (scratch_reg_0, sp_reg);
1732           insn =
1733             frame_emit_add_imm (sp_reg, sp_reg, -total_size, scratch_reg_1);
1734         }
1735       RTX_FRAME_RELATED_P (insn) = 1;
1736       real = gen_addsi3 (sp_reg, sp_reg, GEN_INT (-total_size));
1737       REG_NOTES (insn) =
1738         gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, real, REG_NOTES (insn));
1739
1740       if (total_size > 2000)
1741         {
1742           /* Save the back chain ptr */
1743           insn = frame_emit_store (REGNO (scratch_reg_0), sp_reg, 0);
1744         }
1745
1746       if (frame_pointer_needed)
1747         {
1748           rtx fp_reg = gen_rtx_REG (Pmode, HARD_FRAME_POINTER_REGNUM);
1749           HOST_WIDE_INT fp_offset = STACK_POINTER_OFFSET
1750             + current_function_outgoing_args_size;
1751           /* Set the new frame_pointer */
1752           insn = frame_emit_add_imm (fp_reg, sp_reg, fp_offset, scratch_reg_0);
1753           RTX_FRAME_RELATED_P (insn) = 1;
1754           real = gen_addsi3 (fp_reg, sp_reg, GEN_INT (fp_offset));
1755           REG_NOTES (insn) = 
1756             gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
1757                                real, REG_NOTES (insn));
1758           REGNO_POINTER_ALIGN (HARD_FRAME_POINTER_REGNUM) = STACK_BOUNDARY;
1759         }
1760     }
1761
1762   emit_note (NOTE_INSN_DELETED);
1763 }
1764
1765 void
1766 spu_expand_epilogue (bool sibcall_p)
1767 {
1768   int size = get_frame_size (), offset, regno;
1769   HOST_WIDE_INT saved_regs_size, total_size;
1770   rtx sp_reg = gen_rtx_REG (Pmode, STACK_POINTER_REGNUM);
1771   rtx jump, scratch_reg_0;
1772
1773   /* A NOTE_INSN_DELETED is supposed to be at the start and end of
1774      the "toplevel" insn chain.  */
1775   emit_note (NOTE_INSN_DELETED);
1776
1777   if (spu_naked_function_p (current_function_decl))
1778     return;
1779
1780   scratch_reg_0 = gen_rtx_REG (SImode, LAST_ARG_REGNUM + 1);
1781
1782   saved_regs_size = spu_saved_regs_size ();
1783   total_size = size + saved_regs_size
1784     + current_function_outgoing_args_size
1785     + current_function_pretend_args_size;
1786
1787   if (!current_function_is_leaf
1788       || current_function_calls_alloca || total_size > 0)
1789     total_size += STACK_POINTER_OFFSET;
1790
1791   if (total_size > 0)
1792     {
1793       if (current_function_calls_alloca)
1794         frame_emit_load (STACK_POINTER_REGNUM, sp_reg, 0);
1795       else
1796         frame_emit_add_imm (sp_reg, sp_reg, total_size, scratch_reg_0);
1797
1798
1799       if (saved_regs_size > 0)
1800         {
1801           offset = -current_function_pretend_args_size;
1802           for (regno = 0; regno < FIRST_PSEUDO_REGISTER; ++regno)
1803             if (need_to_save_reg (regno, 1))
1804               {
1805                 offset -= 0x10;
1806                 frame_emit_load (regno, sp_reg, offset);
1807               }
1808         }
1809     }
1810
1811   if (!current_function_is_leaf)
1812     frame_emit_load (LINK_REGISTER_REGNUM, sp_reg, 16);
1813
1814   if (!sibcall_p)
1815     {
1816       emit_insn (gen_rtx_USE
1817                  (VOIDmode, gen_rtx_REG (SImode, LINK_REGISTER_REGNUM)));
1818       jump = emit_jump_insn (gen__return ());
1819       emit_barrier_after (jump);
1820     }
1821
1822   emit_note (NOTE_INSN_DELETED);
1823 }
1824
1825 rtx
1826 spu_return_addr (int count, rtx frame ATTRIBUTE_UNUSED)
1827 {
1828   if (count != 0)
1829     return 0;
1830   /* This is inefficient because it ends up copying to a save-register
1831      which then gets saved even though $lr has already been saved.  But
1832      it does generate better code for leaf functions and we don't need
1833      to use RETURN_ADDRESS_POINTER_REGNUM to get it working.  It's only
1834      used for __builtin_return_address anyway, so maybe we don't care if
1835      it's inefficient. */
1836   return get_hard_reg_initial_val (Pmode, LINK_REGISTER_REGNUM);
1837 }
1838 \f
1839
1840 /* Given VAL, generate a constant appropriate for MODE.
1841    If MODE is a vector mode, every element will be VAL.
1842    For TImode, VAL will be zero extended to 128 bits. */
1843 rtx
1844 spu_const (enum machine_mode mode, HOST_WIDE_INT val)
1845 {
1846   rtx inner;
1847   rtvec v;
1848   int units, i;
1849
1850   gcc_assert (GET_MODE_CLASS (mode) == MODE_INT
1851               || GET_MODE_CLASS (mode) == MODE_FLOAT
1852               || GET_MODE_CLASS (mode) == MODE_VECTOR_INT
1853               || GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT);
1854
1855   if (GET_MODE_CLASS (mode) == MODE_INT)
1856     return immed_double_const (val, 0, mode);
1857
1858   /* val is the bit representation of the float */
1859   if (GET_MODE_CLASS (mode) == MODE_FLOAT)
1860     return hwint_to_const_double (mode, val);
1861
1862   if (GET_MODE_CLASS (mode) == MODE_VECTOR_INT)
1863     inner = immed_double_const (val, 0, GET_MODE_INNER (mode));
1864   else 
1865     inner = hwint_to_const_double (GET_MODE_INNER (mode), val);
1866
1867   units = GET_MODE_NUNITS (mode);
1868
1869   v = rtvec_alloc (units);
1870
1871   for (i = 0; i < units; ++i)
1872     RTVEC_ELT (v, i) = inner;
1873
1874   return gen_rtx_CONST_VECTOR (mode, v);
1875 }
1876 \f
1877 /* branch hint stuff */
1878
1879 /* The hardware requires 8 insns between a hint and the branch it
1880    effects.  This variable describes how many rtl instructions the
1881    compiler needs to see before inserting a hint.  (FIXME: We should
1882    accept less and insert nops to enforce it because hinting is always
1883    profitable for performance, but we do need to be careful of code
1884    size.) */
1885 int spu_hint_dist = (8 * 4);
1886
1887 /* An array of these is used to propagate hints to predecessor blocks. */
1888 struct spu_bb_info
1889 {
1890   rtx prop_jump;                /* propagated from another block */
1891   basic_block bb;               /* the original block. */
1892 };
1893
1894 /* The special $hbr register is used to prevent the insn scheduler from
1895    moving hbr insns across instructions which invalidate them.  It
1896    should only be used in a clobber, and this function searches for
1897    insns which clobber it.  */
1898 static bool
1899 insn_clobbers_hbr (rtx insn)
1900 {
1901   if (INSN_P (insn) && GET_CODE (PATTERN (insn)) == PARALLEL)
1902     {
1903       rtx parallel = PATTERN (insn);
1904       rtx clobber;
1905       int j;
1906       for (j = XVECLEN (parallel, 0) - 1; j >= 0; j--)
1907         {
1908           clobber = XVECEXP (parallel, 0, j);
1909           if (GET_CODE (clobber) == CLOBBER
1910               && GET_CODE (XEXP (clobber, 0)) == REG
1911               && REGNO (XEXP (clobber, 0)) == HBR_REGNUM)
1912             return 1;
1913         }
1914     }
1915   return 0;
1916 }
1917
1918 static void
1919 spu_emit_branch_hint (rtx before, rtx branch, rtx target, int distance)
1920 {
1921   rtx branch_label;
1922   rtx hint, insn, prev, next;
1923
1924   if (before == 0 || branch == 0 || target == 0)
1925     return;
1926
1927   if (distance > 600)
1928     return;
1929
1930
1931   branch_label = gen_label_rtx ();
1932   LABEL_NUSES (branch_label)++;
1933   LABEL_PRESERVE_P (branch_label) = 1;
1934   insn = emit_label_before (branch_label, branch);
1935   branch_label = gen_rtx_LABEL_REF (VOIDmode, branch_label);
1936
1937   /* If the previous insn is pipe0, make the hbr dual issue with it.  If
1938      the current insn is pipe0, dual issue with it. */
1939   prev = prev_active_insn (before);
1940   if (prev && get_pipe (prev) == 0)
1941     hint = emit_insn_before (gen_hbr (branch_label, target), before);
1942   else if (get_pipe (before) == 0 && distance > spu_hint_dist)
1943     {
1944       next = next_active_insn (before);
1945       hint = emit_insn_after (gen_hbr (branch_label, target), before);
1946       if (next)
1947         PUT_MODE (next, TImode);
1948     }
1949   else
1950     {
1951       hint = emit_insn_before (gen_hbr (branch_label, target), before);
1952       PUT_MODE (hint, TImode);
1953     }
1954   recog_memoized (hint);
1955 }
1956
1957 /* Returns 0 if we don't want a hint for this branch.  Otherwise return
1958    the rtx for the branch target. */
1959 static rtx
1960 get_branch_target (rtx branch)
1961 {
1962   if (GET_CODE (branch) == JUMP_INSN)
1963     {
1964       rtx set, src;
1965
1966       /* Return statements */
1967       if (GET_CODE (PATTERN (branch)) == RETURN)
1968         return gen_rtx_REG (SImode, LINK_REGISTER_REGNUM);
1969
1970       /* jump table */
1971       if (GET_CODE (PATTERN (branch)) == ADDR_VEC
1972           || GET_CODE (PATTERN (branch)) == ADDR_DIFF_VEC)
1973         return 0;
1974
1975       set = single_set (branch);
1976       src = SET_SRC (set);
1977       if (GET_CODE (SET_DEST (set)) != PC)
1978         abort ();
1979
1980       if (GET_CODE (src) == IF_THEN_ELSE)
1981         {
1982           rtx lab = 0;
1983           rtx note = find_reg_note (branch, REG_BR_PROB, 0);
1984           if (note)
1985             {
1986               /* If the more probable case is not a fall through, then
1987                  try a branch hint.  */
1988               HOST_WIDE_INT prob = INTVAL (XEXP (note, 0));
1989               if (prob > (REG_BR_PROB_BASE * 6 / 10)
1990                   && GET_CODE (XEXP (src, 1)) != PC)
1991                 lab = XEXP (src, 1);
1992               else if (prob < (REG_BR_PROB_BASE * 4 / 10)
1993                        && GET_CODE (XEXP (src, 2)) != PC)
1994                 lab = XEXP (src, 2);
1995             }
1996           if (lab)
1997             {
1998               if (GET_CODE (lab) == RETURN)
1999                 return gen_rtx_REG (SImode, LINK_REGISTER_REGNUM);
2000               return lab;
2001             }
2002           return 0;
2003         }
2004
2005       return src;
2006     }
2007   else if (GET_CODE (branch) == CALL_INSN)
2008     {
2009       rtx call;
2010       /* All of our call patterns are in a PARALLEL and the CALL is
2011          the first pattern in the PARALLEL. */
2012       if (GET_CODE (PATTERN (branch)) != PARALLEL)
2013         abort ();
2014       call = XVECEXP (PATTERN (branch), 0, 0);
2015       if (GET_CODE (call) == SET)
2016         call = SET_SRC (call);
2017       if (GET_CODE (call) != CALL)
2018         abort ();
2019       return XEXP (XEXP (call, 0), 0);
2020     }
2021   return 0;
2022 }
2023
2024 static void
2025 insert_branch_hints (void)
2026 {
2027   struct spu_bb_info *spu_bb_info;
2028   rtx branch, insn, next;
2029   rtx branch_target = 0;
2030   int branch_addr = 0, insn_addr, head_addr;
2031   basic_block bb;
2032   unsigned int j;
2033
2034   spu_bb_info =
2035     (struct spu_bb_info *) xcalloc (last_basic_block + 1,
2036                                     sizeof (struct spu_bb_info));
2037
2038   /* We need exact insn addresses and lengths.  */
2039   shorten_branches (get_insns ());
2040
2041   FOR_EACH_BB_REVERSE (bb)
2042   {
2043     head_addr = INSN_ADDRESSES (INSN_UID (BB_HEAD (bb)));
2044     branch = 0;
2045     if (spu_bb_info[bb->index].prop_jump)
2046       {
2047         branch = spu_bb_info[bb->index].prop_jump;
2048         branch_target = get_branch_target (branch);
2049         branch_addr = INSN_ADDRESSES (INSN_UID (branch));
2050       }
2051     /* Search from end of a block to beginning.   In this loop, find
2052        jumps which need a branch and emit them only when:
2053        - it's an indirect branch and we're at the insn which sets
2054        the register  
2055        - we're at an insn that will invalidate the hint. e.g., a
2056        call, another hint insn, inline asm that clobbers $hbr, and
2057        some inlined operations (divmodsi4).  Don't consider jumps
2058        because they are only at the end of a block and are
2059        considered when we are deciding whether to propagate
2060        - we're getting too far away from the branch.  The hbr insns
2061        only have a signed 10-bit offset
2062        We go back as far as possible so the branch will be considered
2063        for propagation when we get to the beginning of the block.  */
2064     next = 0;
2065     for (insn = BB_END (bb); insn; insn = PREV_INSN (insn))
2066       {
2067         if (INSN_P (insn))
2068           {
2069             insn_addr = INSN_ADDRESSES (INSN_UID (insn));
2070             if (branch && next
2071                 && ((GET_CODE (branch_target) == REG
2072                      && set_of (branch_target, insn) != NULL_RTX)
2073                     || insn_clobbers_hbr (insn)
2074                     || branch_addr - insn_addr > 600))
2075               {
2076                 int next_addr = INSN_ADDRESSES (INSN_UID (next));
2077                 if (insn != BB_END (bb)
2078                     && branch_addr - next_addr >= spu_hint_dist)
2079                   {
2080                     if (dump_file)
2081                       fprintf (dump_file,
2082                                "hint for %i in block %i before %i\n",
2083                                INSN_UID (branch), bb->index, INSN_UID (next));
2084                     spu_emit_branch_hint (next, branch, branch_target,
2085                                           branch_addr - next_addr);
2086                   }
2087                 branch = 0;
2088               }
2089
2090             /* JUMP_P will only be true at the end of a block.  When
2091                branch is already set it means we've previously decided
2092                to propagate a hint for that branch into this block. */
2093             if (CALL_P (insn) || (JUMP_P (insn) && !branch))
2094               {
2095                 branch = 0;
2096                 if ((branch_target = get_branch_target (insn)))
2097                   {
2098                     branch = insn;
2099                     branch_addr = insn_addr;
2100                   }
2101               }
2102
2103             /* When a branch hint is emitted it will be inserted
2104                before "next".  Make sure next is the beginning of a
2105                cycle to minimize impact on the scheduled insns. */
2106             if (GET_MODE (insn) == TImode)
2107               next = insn;
2108           }
2109         if (insn == BB_HEAD (bb))
2110           break;
2111       }
2112
2113     if (branch)
2114       {
2115         /* If we haven't emitted a hint for this branch yet, it might
2116            be profitable to emit it in one of the predecessor blocks,
2117            especially for loops.  */
2118         rtx bbend;
2119         basic_block prev = 0, prop = 0, prev2 = 0;
2120         int loop_exit = 0, simple_loop = 0;
2121         int next_addr = 0;
2122         if (next)
2123           next_addr = INSN_ADDRESSES (INSN_UID (next));
2124
2125         for (j = 0; j < EDGE_COUNT (bb->preds); j++)
2126           if (EDGE_PRED (bb, j)->flags & EDGE_FALLTHRU)
2127             prev = EDGE_PRED (bb, j)->src;
2128           else
2129             prev2 = EDGE_PRED (bb, j)->src;
2130
2131         for (j = 0; j < EDGE_COUNT (bb->succs); j++)
2132           if (EDGE_SUCC (bb, j)->flags & EDGE_LOOP_EXIT)
2133             loop_exit = 1;
2134           else if (EDGE_SUCC (bb, j)->dest == bb)
2135             simple_loop = 1;
2136
2137         /* If this branch is a loop exit then propagate to previous
2138            fallthru block. This catches the cases when it is a simple
2139            loop or when there is an initial branch into the loop. */
2140         if (prev && loop_exit && prev->loop_depth <= bb->loop_depth)
2141           prop = prev;
2142
2143         /* If there is only one adjacent predecessor.  Don't propagate
2144            outside this loop.  This loop_depth test isn't perfect, but
2145            I'm not sure the loop_father member is valid at this point.  */
2146         else if (prev && single_pred_p (bb)
2147                  && prev->loop_depth == bb->loop_depth)
2148           prop = prev;
2149
2150         /* If this is the JOIN block of a simple IF-THEN then
2151            propagate the hint to the HEADER block. */
2152         else if (prev && prev2
2153                  && EDGE_COUNT (bb->preds) == 2
2154                  && EDGE_COUNT (prev->preds) == 1
2155                  && EDGE_PRED (prev, 0)->src == prev2
2156                  && prev2->loop_depth == bb->loop_depth
2157                  && GET_CODE (branch_target) != REG)
2158           prop = prev;
2159
2160         /* Don't propagate when:
2161            - this is a simple loop and the hint would be too far
2162            - this is not a simple loop and there are 16 insns in
2163            this block already
2164            - the predecessor block ends in a branch that will be
2165            hinted
2166            - the predecessor block ends in an insn that invalidates
2167            the hint */
2168         if (prop
2169             && prop->index >= 0
2170             && (bbend = BB_END (prop))
2171             && branch_addr - INSN_ADDRESSES (INSN_UID (bbend)) <
2172             (simple_loop ? 600 : 16 * 4) && get_branch_target (bbend) == 0
2173             && (JUMP_P (bbend) || !insn_clobbers_hbr (bbend)))
2174           {
2175             if (dump_file)
2176               fprintf (dump_file, "propagate from %i to %i (loop depth %i) "
2177                        "for %i (loop_exit %i simple_loop %i dist %i)\n",
2178                        bb->index, prop->index, bb->loop_depth,
2179                        INSN_UID (branch), loop_exit, simple_loop,
2180                        branch_addr - INSN_ADDRESSES (INSN_UID (bbend)));
2181
2182             spu_bb_info[prop->index].prop_jump = branch;
2183             spu_bb_info[prop->index].bb = bb;
2184           }
2185         else if (next && branch_addr - next_addr >= spu_hint_dist)
2186           {
2187             if (dump_file)
2188               fprintf (dump_file, "hint for %i in block %i before %i\n",
2189                        INSN_UID (branch), bb->index, INSN_UID (next));
2190             spu_emit_branch_hint (next, branch, branch_target,
2191                                   branch_addr - next_addr);
2192           }
2193         branch = 0;
2194       }
2195   }
2196   free (spu_bb_info);
2197 }
2198 \f
2199 /* Emit a nop for INSN such that the two will dual issue.  This assumes
2200    INSN is 8-byte aligned.  When INSN is inline asm we emit an lnop.
2201    We check for TImode to handle a MULTI1 insn which has dual issued its
2202    first instruction.  get_pipe returns -1 for MULTI0, inline asm, or
2203    ADDR_VEC insns. */
2204 static void
2205 emit_nop_for_insn (rtx insn)
2206 {
2207   int p;
2208   rtx new_insn;
2209   p = get_pipe (insn);
2210   if (p == 1 && GET_MODE (insn) == TImode)
2211     {
2212       new_insn = emit_insn_before (gen_nopn (GEN_INT (127)), insn);
2213       PUT_MODE (new_insn, TImode);
2214       PUT_MODE (insn, VOIDmode);
2215     }
2216   else
2217     new_insn = emit_insn_after (gen_lnop (), insn);
2218 }
2219
2220 /* Insert nops in basic blocks to meet dual issue alignment
2221    requirements. */
2222 static void
2223 insert_nops (void)
2224 {
2225   rtx insn, next_insn, prev_insn;
2226   int length;
2227   int addr;
2228
2229   /* This sets up INSN_ADDRESSES. */
2230   shorten_branches (get_insns ());
2231
2232   /* Keep track of length added by nops. */
2233   length = 0;
2234
2235   prev_insn = 0;
2236   for (insn = get_insns (); insn; insn = next_insn)
2237     {
2238       next_insn = next_active_insn (insn);
2239       addr = INSN_ADDRESSES (INSN_UID (insn));
2240       if (GET_MODE (insn) == TImode
2241           && next_insn
2242           && GET_MODE (next_insn) != TImode
2243           && ((addr + length) & 7) != 0)
2244         {
2245           /* prev_insn will always be set because the first insn is
2246              always 8-byte aligned. */
2247           emit_nop_for_insn (prev_insn);
2248           length += 4;
2249         }
2250       prev_insn = insn;
2251     }
2252 }
2253
2254 static void
2255 spu_machine_dependent_reorg (void)
2256 {
2257   if (optimize > 0)
2258     {
2259       if (TARGET_BRANCH_HINTS)
2260         insert_branch_hints ();
2261       insert_nops ();
2262     }
2263 }
2264 \f
2265
2266 /* Insn scheduling routines, primarily for dual issue. */
2267 static int
2268 spu_sched_issue_rate (void)
2269 {
2270   return 2;
2271 }
2272
2273 static int
2274 spu_sched_variable_issue (FILE * dump ATTRIBUTE_UNUSED,
2275                           int verbose ATTRIBUTE_UNUSED, rtx insn,
2276                           int can_issue_more)
2277 {
2278   if (GET_CODE (PATTERN (insn)) != USE
2279       && GET_CODE (PATTERN (insn)) != CLOBBER
2280       && get_pipe (insn) != -2)
2281     can_issue_more--;
2282   return can_issue_more;
2283 }
2284
2285 static int
2286 get_pipe (rtx insn)
2287 {
2288   enum attr_type t;
2289   /* Handle inline asm */
2290   if (INSN_CODE (insn) == -1)
2291     return -1;
2292   t = get_attr_type (insn);
2293   switch (t)
2294     {
2295     case TYPE_CONVERT:
2296       return -2;
2297     case TYPE_MULTI0:
2298       return -1;
2299
2300     case TYPE_FX2:
2301     case TYPE_FX3:
2302     case TYPE_SPR:
2303     case TYPE_NOP:
2304     case TYPE_FXB:
2305     case TYPE_FPD:
2306     case TYPE_FP6:
2307     case TYPE_FP7:
2308     case TYPE_IPREFETCH:
2309       return 0;
2310
2311     case TYPE_LNOP:
2312     case TYPE_SHUF:
2313     case TYPE_LOAD:
2314     case TYPE_STORE:
2315     case TYPE_BR:
2316     case TYPE_MULTI1:
2317     case TYPE_HBR:
2318       return 1;
2319     default:
2320       abort ();
2321     }
2322 }
2323
2324 static int
2325 spu_sched_adjust_priority (rtx insn, int pri)
2326 {
2327   int p = get_pipe (insn);
2328   /* Schedule UNSPEC_CONVERT's early so they have less effect on
2329    * scheduling.  */
2330   if (GET_CODE (PATTERN (insn)) == USE
2331       || GET_CODE (PATTERN (insn)) == CLOBBER
2332       || p == -2)
2333     return pri + 100; 
2334   /* Schedule pipe0 insns early for greedier dual issue. */
2335   if (p != 1)
2336     return pri + 50;
2337   return pri;
2338 }
2339
2340 /* INSN is dependent on DEP_INSN. */
2341 static int
2342 spu_sched_adjust_cost (rtx insn, rtx link ATTRIBUTE_UNUSED,
2343                        rtx dep_insn ATTRIBUTE_UNUSED, int cost)
2344 {
2345   if (GET_CODE (insn) == CALL_INSN)
2346     return cost - 2;
2347   /* The dfa scheduler sets cost to 0 for all anti-dependencies and the
2348      scheduler makes every insn in a block anti-dependent on the final
2349      jump_insn.  We adjust here so higher cost insns will get scheduled
2350      earlier. */
2351   if (GET_CODE (insn) == JUMP_INSN && REG_NOTE_KIND (link) == REG_DEP_ANTI)
2352     return insn_cost (dep_insn) - 3;
2353   return cost;
2354 }
2355 \f
2356 /* Create a CONST_DOUBLE from a string.  */
2357 struct rtx_def *
2358 spu_float_const (const char *string, enum machine_mode mode)
2359 {
2360   REAL_VALUE_TYPE value;
2361   value = REAL_VALUE_ATOF (string, mode);
2362   return CONST_DOUBLE_FROM_REAL_VALUE (value, mode);
2363 }
2364
2365 /* Given a (CONST (PLUS (SYMBOL_REF) (CONST_INT))) return TRUE when the
2366    CONST_INT fits constraint 'K', i.e., is small. */
2367 int
2368 legitimate_const (rtx x, int aligned)
2369 {
2370   /* We can never know if the resulting address fits in 18 bits and can be
2371      loaded with ila.  Instead we should use the HI and LO relocations to
2372      load a 32-bit address.  */
2373   rtx sym, cst;
2374
2375   gcc_assert (GET_CODE (x) == CONST);
2376
2377   if (GET_CODE (XEXP (x, 0)) != PLUS)
2378     return 0;
2379   sym = XEXP (XEXP (x, 0), 0);
2380   cst = XEXP (XEXP (x, 0), 1);
2381   if (GET_CODE (sym) != SYMBOL_REF || GET_CODE (cst) != CONST_INT)
2382     return 0;
2383   if (aligned && ((INTVAL (cst) & 15) != 0 || !ALIGNED_SYMBOL_REF_P (sym)))
2384     return 0;
2385   return satisfies_constraint_K (cst);
2386 }
2387
2388 int
2389 spu_constant_address_p (rtx x)
2390 {
2391   return (GET_CODE (x) == LABEL_REF || GET_CODE (x) == SYMBOL_REF
2392           || GET_CODE (x) == CONST_INT || GET_CODE (x) == CONST
2393           || GET_CODE (x) == HIGH);
2394 }
2395
2396 static enum spu_immediate
2397 which_immediate_load (HOST_WIDE_INT val)
2398 {
2399   gcc_assert (val == trunc_int_for_mode (val, SImode));
2400
2401   if (val >= -0x8000 && val <= 0x7fff)
2402     return SPU_IL;
2403   if (val >= 0 && val <= 0x3ffff)
2404     return SPU_ILA;
2405   if ((val & 0xffff) == ((val >> 16) & 0xffff))
2406     return SPU_ILH;
2407   if ((val & 0xffff) == 0)
2408     return SPU_ILHU;
2409
2410   return SPU_NONE;
2411 }
2412
2413 /* Return true when OP can be loaded by one of the il instructions, or
2414    when flow2 is not completed and OP can be loaded using ilhu and iohl. */
2415 int
2416 immediate_load_p (rtx op, enum machine_mode mode)
2417 {
2418   if (CONSTANT_P (op))
2419     {
2420       enum immediate_class c = classify_immediate (op, mode);
2421       return c == IC_IL1 || c == IC_IL1s
2422              || (!epilogue_completed && (c == IC_IL2 || c == IC_IL2s));
2423     }
2424   return 0;
2425 }
2426
2427 /* Return true if the first SIZE bytes of arr is a constant that can be
2428    generated with cbd, chd, cwd or cdd.  When non-NULL, PRUN and PSTART
2429    represent the size and offset of the instruction to use. */
2430 static int
2431 cpat_info(unsigned char *arr, int size, int *prun, int *pstart)
2432 {
2433   int cpat, run, i, start;
2434   cpat = 1;
2435   run = 0;
2436   start = -1;
2437   for (i = 0; i < size && cpat; i++)
2438     if (arr[i] != i+16)
2439       { 
2440         if (!run)
2441           {
2442             start = i;
2443             if (arr[i] == 3)
2444               run = 1;
2445             else if (arr[i] == 2 && arr[i+1] == 3)
2446               run = 2;
2447             else if (arr[i] == 0)
2448               {
2449                 while (arr[i+run] == run && i+run < 16)
2450                   run++;
2451                 if (run != 4 && run != 8)
2452                   cpat = 0;
2453               }
2454             else
2455               cpat = 0;
2456             if ((i & (run-1)) != 0)
2457               cpat = 0;
2458             i += run;
2459           }
2460         else
2461           cpat = 0;
2462       }
2463   if (cpat && (run || size < 16))
2464     {
2465       if (run == 0)
2466         run = 1;
2467       if (prun)
2468         *prun = run;
2469       if (pstart)
2470         *pstart = start == -1 ? 16-run : start;
2471       return 1;
2472     }
2473   return 0;
2474 }
2475
2476 /* OP is a CONSTANT_P.  Determine what instructions can be used to load
2477    it into a register.  MODE is only valid when OP is a CONST_INT. */
2478 static enum immediate_class
2479 classify_immediate (rtx op, enum machine_mode mode)
2480 {
2481   HOST_WIDE_INT val;
2482   unsigned char arr[16];
2483   int i, j, repeated, fsmbi, repeat;
2484
2485   gcc_assert (CONSTANT_P (op));
2486
2487   if (GET_MODE (op) != VOIDmode)
2488     mode = GET_MODE (op);
2489
2490   /* A V4SI const_vector with all identical symbols is ok. */
2491   if (!flag_pic
2492       && mode == V4SImode
2493       && GET_CODE (op) == CONST_VECTOR
2494       && GET_CODE (CONST_VECTOR_ELT (op, 0)) != CONST_INT
2495       && GET_CODE (CONST_VECTOR_ELT (op, 0)) != CONST_DOUBLE
2496       && CONST_VECTOR_ELT (op, 0) == CONST_VECTOR_ELT (op, 1)
2497       && CONST_VECTOR_ELT (op, 1) == CONST_VECTOR_ELT (op, 2)
2498       && CONST_VECTOR_ELT (op, 2) == CONST_VECTOR_ELT (op, 3))
2499     op = CONST_VECTOR_ELT (op, 0);
2500
2501   switch (GET_CODE (op))
2502     {
2503     case SYMBOL_REF:
2504     case LABEL_REF:
2505       return TARGET_LARGE_MEM ? IC_IL2s : IC_IL1s;
2506
2507     case CONST:
2508       return TARGET_LARGE_MEM
2509         || !legitimate_const (op, 0) ? IC_IL2s : IC_IL1s;
2510
2511     case HIGH:
2512       return IC_IL1s;
2513
2514     case CONST_VECTOR:
2515       for (i = 0; i < GET_MODE_NUNITS (mode); i++)
2516         if (GET_CODE (CONST_VECTOR_ELT (op, i)) != CONST_INT
2517             && GET_CODE (CONST_VECTOR_ELT (op, i)) != CONST_DOUBLE)
2518           return IC_POOL;
2519       /* Fall through. */
2520
2521     case CONST_INT:
2522     case CONST_DOUBLE:
2523       constant_to_array (mode, op, arr);
2524
2525       /* Check that each 4-byte slot is identical. */
2526       repeated = 1;
2527       for (i = 4; i < 16; i += 4)
2528         for (j = 0; j < 4; j++)
2529           if (arr[j] != arr[i + j])
2530             repeated = 0;
2531
2532       if (repeated)
2533         {
2534           val = (arr[0] << 24) | (arr[1] << 16) | (arr[2] << 8) | arr[3];
2535           val = trunc_int_for_mode (val, SImode);
2536
2537           if (which_immediate_load (val) != SPU_NONE)
2538             return IC_IL1;
2539         }
2540
2541       /* Any mode of 2 bytes or smaller can be loaded with an il
2542          instruction. */
2543       gcc_assert (GET_MODE_SIZE (mode) > 2);
2544
2545       fsmbi = 1;
2546       repeat = 0;
2547       for (i = 0; i < 16 && fsmbi; i++)
2548         if (arr[i] != 0 && repeat == 0)
2549           repeat = arr[i];
2550         else if (arr[i] != 0 && arr[i] != repeat)
2551           fsmbi = 0;
2552       if (fsmbi)
2553         return repeat == 0xff ? IC_FSMBI : IC_FSMBI2;
2554
2555       if (cpat_info (arr, GET_MODE_SIZE (mode), 0, 0))
2556         return IC_CPAT;
2557
2558       if (repeated)
2559         return IC_IL2;
2560
2561       return IC_POOL;
2562     default:
2563       break;
2564     }
2565   gcc_unreachable ();
2566 }
2567
2568 static enum spu_immediate
2569 which_logical_immediate (HOST_WIDE_INT val)
2570 {
2571   gcc_assert (val == trunc_int_for_mode (val, SImode));
2572
2573   if (val >= -0x200 && val <= 0x1ff)
2574     return SPU_ORI;
2575   if (val >= 0 && val <= 0xffff)
2576     return SPU_IOHL;
2577   if ((val & 0xffff) == ((val >> 16) & 0xffff))
2578     {
2579       val = trunc_int_for_mode (val, HImode);
2580       if (val >= -0x200 && val <= 0x1ff)
2581         return SPU_ORHI;
2582       if ((val & 0xff) == ((val >> 8) & 0xff))
2583         {
2584           val = trunc_int_for_mode (val, QImode);
2585           if (val >= -0x200 && val <= 0x1ff)
2586             return SPU_ORBI;
2587         }
2588     }
2589   return SPU_NONE;
2590 }
2591
2592 /* Return TRUE when X, a CONST_VECTOR, only contains CONST_INTs or
2593    CONST_DOUBLEs. */
2594 static int
2595 const_vector_immediate_p (rtx x)
2596 {
2597   int i;
2598   gcc_assert (GET_CODE (x) == CONST_VECTOR);
2599   for (i = 0; i < GET_MODE_NUNITS (GET_MODE (x)); i++)
2600     if (GET_CODE (CONST_VECTOR_ELT (x, i)) != CONST_INT
2601         && GET_CODE (CONST_VECTOR_ELT (x, i)) != CONST_DOUBLE)
2602       return 0;
2603   return 1;
2604 }
2605
2606 int
2607 logical_immediate_p (rtx op, enum machine_mode mode)
2608 {
2609   HOST_WIDE_INT val;
2610   unsigned char arr[16];
2611   int i, j;
2612
2613   gcc_assert (GET_CODE (op) == CONST_INT || GET_CODE (op) == CONST_DOUBLE
2614               || GET_CODE (op) == CONST_VECTOR);
2615
2616   if (GET_CODE (op) == CONST_VECTOR
2617       && !const_vector_immediate_p (op))
2618     return 0;
2619
2620   if (GET_MODE (op) != VOIDmode)
2621     mode = GET_MODE (op);
2622
2623   constant_to_array (mode, op, arr);
2624
2625   /* Check that bytes are repeated. */
2626   for (i = 4; i < 16; i += 4)
2627     for (j = 0; j < 4; j++)
2628       if (arr[j] != arr[i + j])
2629         return 0;
2630
2631   val = (arr[0] << 24) | (arr[1] << 16) | (arr[2] << 8) | arr[3];
2632   val = trunc_int_for_mode (val, SImode);
2633
2634   i = which_logical_immediate (val);
2635   return i != SPU_NONE && i != SPU_IOHL;
2636 }
2637
2638 int
2639 iohl_immediate_p (rtx op, enum machine_mode mode)
2640 {
2641   HOST_WIDE_INT val;
2642   unsigned char arr[16];
2643   int i, j;
2644
2645   gcc_assert (GET_CODE (op) == CONST_INT || GET_CODE (op) == CONST_DOUBLE
2646               || GET_CODE (op) == CONST_VECTOR);
2647
2648   if (GET_CODE (op) == CONST_VECTOR
2649       && !const_vector_immediate_p (op))
2650     return 0;
2651
2652   if (GET_MODE (op) != VOIDmode)
2653     mode = GET_MODE (op);
2654
2655   constant_to_array (mode, op, arr);
2656
2657   /* Check that bytes are repeated. */
2658   for (i = 4; i < 16; i += 4)
2659     for (j = 0; j < 4; j++)
2660       if (arr[j] != arr[i + j])
2661         return 0;
2662
2663   val = (arr[0] << 24) | (arr[1] << 16) | (arr[2] << 8) | arr[3];
2664   val = trunc_int_for_mode (val, SImode);
2665
2666   return val >= 0 && val <= 0xffff;
2667 }
2668
2669 int
2670 arith_immediate_p (rtx op, enum machine_mode mode,
2671                    HOST_WIDE_INT low, HOST_WIDE_INT high)
2672 {
2673   HOST_WIDE_INT val;
2674   unsigned char arr[16];
2675   int bytes, i, j;
2676
2677   gcc_assert (GET_CODE (op) == CONST_INT || GET_CODE (op) == CONST_DOUBLE
2678               || GET_CODE (op) == CONST_VECTOR);
2679
2680   if (GET_CODE (op) == CONST_VECTOR
2681       && !const_vector_immediate_p (op))
2682     return 0;
2683
2684   if (GET_MODE (op) != VOIDmode)
2685     mode = GET_MODE (op);
2686
2687   constant_to_array (mode, op, arr);
2688
2689   if (VECTOR_MODE_P (mode))
2690     mode = GET_MODE_INNER (mode);
2691
2692   bytes = GET_MODE_SIZE (mode);
2693   mode = mode_for_size (GET_MODE_BITSIZE (mode), MODE_INT, 0);
2694
2695   /* Check that bytes are repeated. */
2696   for (i = bytes; i < 16; i += bytes)
2697     for (j = 0; j < bytes; j++)
2698       if (arr[j] != arr[i + j])
2699         return 0;
2700
2701   val = arr[0];
2702   for (j = 1; j < bytes; j++)
2703     val = (val << 8) | arr[j];
2704
2705   val = trunc_int_for_mode (val, mode);
2706
2707   return val >= low && val <= high;
2708 }
2709
2710 /* We accept:
2711    - any 32-bit constant (SImode, SFmode)
2712    - any constant that can be generated with fsmbi (any mode)
2713    - a 64-bit constant where the high and low bits are identical
2714      (DImode, DFmode)
2715    - a 128-bit constant where the four 32-bit words match.  */
2716 int
2717 spu_legitimate_constant_p (rtx x)
2718 {
2719   if (GET_CODE (x) == HIGH)
2720     x = XEXP (x, 0);
2721   /* V4SI with all identical symbols is valid. */
2722   if (!flag_pic
2723       && GET_MODE (x) == V4SImode
2724       && (GET_CODE (CONST_VECTOR_ELT (x, 0)) == SYMBOL_REF
2725           || GET_CODE (CONST_VECTOR_ELT (x, 0)) == LABEL_REF
2726           || GET_CODE (CONST_VECTOR_ELT (x, 0)) == CONST))
2727     return CONST_VECTOR_ELT (x, 0) == CONST_VECTOR_ELT (x, 1)
2728            && CONST_VECTOR_ELT (x, 1) == CONST_VECTOR_ELT (x, 2)
2729            && CONST_VECTOR_ELT (x, 2) == CONST_VECTOR_ELT (x, 3);
2730
2731   if (GET_CODE (x) == CONST_VECTOR
2732       && !const_vector_immediate_p (x))
2733     return 0;
2734   return 1;
2735 }
2736
2737 /* Valid address are:
2738    - symbol_ref, label_ref, const
2739    - reg
2740    - reg + const, where either reg or const is 16 byte aligned
2741    - reg + reg, alignment doesn't matter
2742   The alignment matters in the reg+const case because lqd and stqd
2743   ignore the 4 least significant bits of the const.  (TODO: It might be
2744   preferable to allow any alignment and fix it up when splitting.) */
2745 int
2746 spu_legitimate_address (enum machine_mode mode ATTRIBUTE_UNUSED,
2747                         rtx x, int reg_ok_strict)
2748 {
2749   if (mode == TImode && GET_CODE (x) == AND
2750       && GET_CODE (XEXP (x, 1)) == CONST_INT
2751       && INTVAL (XEXP (x, 1)) == (HOST_WIDE_INT) -16)
2752     x = XEXP (x, 0);
2753   switch (GET_CODE (x))
2754     {
2755     case SYMBOL_REF:
2756     case LABEL_REF:
2757       return !TARGET_LARGE_MEM;
2758
2759     case CONST:
2760       return !TARGET_LARGE_MEM && legitimate_const (x, 0);
2761
2762     case CONST_INT:
2763       return INTVAL (x) >= 0 && INTVAL (x) <= 0x3ffff;
2764
2765     case SUBREG:
2766       x = XEXP (x, 0);
2767       gcc_assert (GET_CODE (x) == REG);
2768
2769     case REG:
2770       return INT_REG_OK_FOR_BASE_P (x, reg_ok_strict);
2771
2772     case PLUS:
2773     case LO_SUM:
2774       {
2775         rtx op0 = XEXP (x, 0);
2776         rtx op1 = XEXP (x, 1);
2777         if (GET_CODE (op0) == SUBREG)
2778           op0 = XEXP (op0, 0);
2779         if (GET_CODE (op1) == SUBREG)
2780           op1 = XEXP (op1, 0);
2781         /* We can't just accept any aligned register because CSE can
2782            change it to a register that is not marked aligned and then
2783            recog will fail.   So we only accept frame registers because
2784            they will only be changed to other frame registers. */
2785         if (GET_CODE (op0) == REG
2786             && INT_REG_OK_FOR_BASE_P (op0, reg_ok_strict)
2787             && GET_CODE (op1) == CONST_INT
2788             && INTVAL (op1) >= -0x2000
2789             && INTVAL (op1) <= 0x1fff
2790             && (regno_aligned_for_load (REGNO (op0)) || (INTVAL (op1) & 15) == 0))
2791           return 1;
2792         if (GET_CODE (op0) == REG
2793             && INT_REG_OK_FOR_BASE_P (op0, reg_ok_strict)
2794             && GET_CODE (op1) == REG
2795             && INT_REG_OK_FOR_INDEX_P (op1, reg_ok_strict))
2796           return 1;
2797       }
2798       break;
2799
2800     default:
2801       break;
2802     }
2803   return 0;
2804 }
2805
2806 /* When the address is reg + const_int, force the const_int into a
2807    register.  */
2808 rtx
2809 spu_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
2810                         enum machine_mode mode)
2811 {
2812   rtx op0, op1;
2813   /* Make sure both operands are registers.  */
2814   if (GET_CODE (x) == PLUS)
2815     {
2816       op0 = XEXP (x, 0);
2817       op1 = XEXP (x, 1);
2818       if (ALIGNED_SYMBOL_REF_P (op0))
2819         {
2820           op0 = force_reg (Pmode, op0);
2821           mark_reg_pointer (op0, 128);
2822         }
2823       else if (GET_CODE (op0) != REG)
2824         op0 = force_reg (Pmode, op0);
2825       if (ALIGNED_SYMBOL_REF_P (op1))
2826         {
2827           op1 = force_reg (Pmode, op1);
2828           mark_reg_pointer (op1, 128);
2829         }
2830       else if (GET_CODE (op1) != REG)
2831         op1 = force_reg (Pmode, op1);
2832       x = gen_rtx_PLUS (Pmode, op0, op1);
2833       if (spu_legitimate_address (mode, x, 0))
2834         return x;
2835     }
2836   return NULL_RTX;
2837 }
2838
2839 /* Handle an attribute requiring a FUNCTION_DECL; arguments as in
2840    struct attribute_spec.handler.  */
2841 static tree
2842 spu_handle_fndecl_attribute (tree * node,
2843                              tree name,
2844                              tree args ATTRIBUTE_UNUSED,
2845                              int flags ATTRIBUTE_UNUSED, bool * no_add_attrs)
2846 {
2847   if (TREE_CODE (*node) != FUNCTION_DECL)
2848     {
2849       warning (0, "`%s' attribute only applies to functions",
2850                IDENTIFIER_POINTER (name));
2851       *no_add_attrs = true;
2852     }
2853
2854   return NULL_TREE;
2855 }
2856
2857 /* Handle the "vector" attribute.  */
2858 static tree
2859 spu_handle_vector_attribute (tree * node, tree name,
2860                              tree args ATTRIBUTE_UNUSED,
2861                              int flags ATTRIBUTE_UNUSED, bool * no_add_attrs)
2862 {
2863   tree type = *node, result = NULL_TREE;
2864   enum machine_mode mode;
2865   int unsigned_p;
2866
2867   while (POINTER_TYPE_P (type)
2868          || TREE_CODE (type) == FUNCTION_TYPE
2869          || TREE_CODE (type) == METHOD_TYPE || TREE_CODE (type) == ARRAY_TYPE)
2870     type = TREE_TYPE (type);
2871
2872   mode = TYPE_MODE (type);
2873
2874   unsigned_p = TYPE_UNSIGNED (type);
2875   switch (mode)
2876     {
2877     case DImode:
2878       result = (unsigned_p ? unsigned_V2DI_type_node : V2DI_type_node);
2879       break;
2880     case SImode:
2881       result = (unsigned_p ? unsigned_V4SI_type_node : V4SI_type_node);
2882       break;
2883     case HImode:
2884       result = (unsigned_p ? unsigned_V8HI_type_node : V8HI_type_node);
2885       break;
2886     case QImode:
2887       result = (unsigned_p ? unsigned_V16QI_type_node : V16QI_type_node);
2888       break;
2889     case SFmode:
2890       result = V4SF_type_node;
2891       break;
2892     case DFmode:
2893       result = V2DF_type_node;
2894       break;
2895     default:
2896       break;
2897     }
2898
2899   /* Propagate qualifiers attached to the element type
2900      onto the vector type.  */
2901   if (result && result != type && TYPE_QUALS (type))
2902     result = build_qualified_type (result, TYPE_QUALS (type));
2903
2904   *no_add_attrs = true;         /* No need to hang on to the attribute.  */
2905
2906   if (!result)
2907     warning (0, "`%s' attribute ignored", IDENTIFIER_POINTER (name));
2908   else
2909     *node = reconstruct_complex_type (*node, result);
2910
2911   return NULL_TREE;
2912 }
2913
2914 /* Return nonzero if FUNC is a naked function.  */
2915 static int
2916 spu_naked_function_p (tree func)
2917 {
2918   tree a;
2919
2920   if (TREE_CODE (func) != FUNCTION_DECL)
2921     abort ();
2922
2923   a = lookup_attribute ("naked", DECL_ATTRIBUTES (func));
2924   return a != NULL_TREE;
2925 }
2926
2927 int
2928 spu_initial_elimination_offset (int from, int to)
2929 {
2930   int saved_regs_size = spu_saved_regs_size ();
2931   int sp_offset = 0;
2932   if (!current_function_is_leaf || current_function_outgoing_args_size
2933       || get_frame_size () || saved_regs_size)
2934     sp_offset = STACK_POINTER_OFFSET;
2935   if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
2936     return (sp_offset + current_function_outgoing_args_size);
2937   else if (from == FRAME_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM)
2938     return 0;
2939   else if (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
2940     return sp_offset + current_function_outgoing_args_size
2941       + get_frame_size () + saved_regs_size + STACK_POINTER_OFFSET;
2942   else if (from == ARG_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM)
2943     return get_frame_size () + saved_regs_size + sp_offset;
2944   return 0;
2945 }
2946
2947 rtx
2948 spu_function_value (tree type, tree func ATTRIBUTE_UNUSED)
2949 {
2950   enum machine_mode mode = TYPE_MODE (type);
2951   int byte_size = ((mode == BLKmode)
2952                    ? int_size_in_bytes (type) : GET_MODE_SIZE (mode));
2953
2954   /* Make sure small structs are left justified in a register. */
2955   if ((mode == BLKmode || (type && AGGREGATE_TYPE_P (type)))
2956       && byte_size <= UNITS_PER_WORD * MAX_REGISTER_RETURN && byte_size > 0)
2957     {
2958       enum machine_mode smode;
2959       rtvec v;
2960       int i;
2961       int nregs = (byte_size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
2962       int n = byte_size / UNITS_PER_WORD;
2963       v = rtvec_alloc (nregs);
2964       for (i = 0; i < n; i++)
2965         {
2966           RTVEC_ELT (v, i) = gen_rtx_EXPR_LIST (VOIDmode,
2967                                                 gen_rtx_REG (TImode,
2968                                                              FIRST_RETURN_REGNUM
2969                                                              + i),
2970                                                 GEN_INT (UNITS_PER_WORD * i));
2971           byte_size -= UNITS_PER_WORD;
2972         }
2973
2974       if (n < nregs)
2975         {
2976           if (byte_size < 4)
2977             byte_size = 4;
2978           smode =
2979             smallest_mode_for_size (byte_size * BITS_PER_UNIT, MODE_INT);
2980           RTVEC_ELT (v, n) =
2981             gen_rtx_EXPR_LIST (VOIDmode,
2982                                gen_rtx_REG (smode, FIRST_RETURN_REGNUM + n),
2983                                GEN_INT (UNITS_PER_WORD * n));
2984         }
2985       return gen_rtx_PARALLEL (mode, v);
2986     }
2987   return gen_rtx_REG (mode, FIRST_RETURN_REGNUM);
2988 }
2989
2990 rtx
2991 spu_function_arg (CUMULATIVE_ARGS cum,
2992                   enum machine_mode mode,
2993                   tree type, int named ATTRIBUTE_UNUSED)
2994 {
2995   int byte_size;
2996
2997   if (cum >= MAX_REGISTER_ARGS)
2998     return 0;
2999
3000   byte_size = ((mode == BLKmode)
3001                ? int_size_in_bytes (type) : GET_MODE_SIZE (mode));
3002
3003   /* The ABI does not allow parameters to be passed partially in
3004      reg and partially in stack. */
3005   if ((cum + (byte_size + 15) / 16) > MAX_REGISTER_ARGS)
3006     return 0;
3007
3008   /* Make sure small structs are left justified in a register. */
3009   if ((mode == BLKmode || (type && AGGREGATE_TYPE_P (type)))
3010       && byte_size < UNITS_PER_WORD && byte_size > 0)
3011     {
3012       enum machine_mode smode;
3013       rtx gr_reg;
3014       if (byte_size < 4)
3015         byte_size = 4;
3016       smode = smallest_mode_for_size (byte_size * BITS_PER_UNIT, MODE_INT);
3017       gr_reg = gen_rtx_EXPR_LIST (VOIDmode,
3018                                   gen_rtx_REG (smode, FIRST_ARG_REGNUM + cum),
3019                                   const0_rtx);
3020       return gen_rtx_PARALLEL (mode, gen_rtvec (1, gr_reg));
3021     }
3022   else
3023     return gen_rtx_REG (mode, FIRST_ARG_REGNUM + cum);
3024 }
3025
3026 /* Variable sized types are passed by reference.  */
3027 static bool
3028 spu_pass_by_reference (CUMULATIVE_ARGS * cum ATTRIBUTE_UNUSED,
3029                        enum machine_mode mode ATTRIBUTE_UNUSED,
3030                        tree type, bool named ATTRIBUTE_UNUSED)
3031 {
3032   return type && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST;
3033 }
3034 \f
3035
3036 /* Var args. */
3037
3038 /* Create and return the va_list datatype.
3039
3040    On SPU, va_list is an array type equivalent to
3041
3042       typedef struct __va_list_tag
3043         {
3044             void *__args __attribute__((__aligned(16)));
3045             void *__skip __attribute__((__aligned(16)));
3046             
3047         } va_list[1];
3048
3049    where __args points to the arg that will be returned by the next
3050    va_arg(), and __skip points to the previous stack frame such that
3051    when __args == __skip we should advance __args by 32 bytes. */
3052 static tree
3053 spu_build_builtin_va_list (void)
3054 {
3055   tree f_args, f_skip, record, type_decl;
3056   bool owp;
3057
3058   record = (*lang_hooks.types.make_type) (RECORD_TYPE);
3059
3060   type_decl =
3061     build_decl (TYPE_DECL, get_identifier ("__va_list_tag"), record);
3062
3063   f_args = build_decl (FIELD_DECL, get_identifier ("__args"), ptr_type_node);
3064   f_skip = build_decl (FIELD_DECL, get_identifier ("__skip"), ptr_type_node);
3065
3066   DECL_FIELD_CONTEXT (f_args) = record;
3067   DECL_ALIGN (f_args) = 128;
3068   DECL_USER_ALIGN (f_args) = 1;
3069
3070   DECL_FIELD_CONTEXT (f_skip) = record;
3071   DECL_ALIGN (f_skip) = 128;
3072   DECL_USER_ALIGN (f_skip) = 1;
3073
3074   TREE_CHAIN (record) = type_decl;
3075   TYPE_NAME (record) = type_decl;
3076   TYPE_FIELDS (record) = f_args;
3077   TREE_CHAIN (f_args) = f_skip;
3078
3079   /* We know this is being padded and we want it too.  It is an internal
3080      type so hide the warnings from the user. */
3081   owp = warn_padded;
3082   warn_padded = false;
3083
3084   layout_type (record);
3085
3086   warn_padded = owp;
3087
3088   /* The correct type is an array type of one element.  */
3089   return build_array_type (record, build_index_type (size_zero_node));
3090 }
3091
3092 /* Implement va_start by filling the va_list structure VALIST.
3093    NEXTARG points to the first anonymous stack argument.
3094
3095    The following global variables are used to initialize
3096    the va_list structure:
3097
3098      current_function_args_info;
3099        the CUMULATIVE_ARGS for this function
3100
3101      current_function_arg_offset_rtx:
3102        holds the offset of the first anonymous stack argument
3103        (relative to the virtual arg pointer).  */
3104
3105 void
3106 spu_va_start (tree valist, rtx nextarg)
3107 {
3108   tree f_args, f_skip;
3109   tree args, skip, t;
3110
3111   f_args = TYPE_FIELDS (TREE_TYPE (va_list_type_node));
3112   f_skip = TREE_CHAIN (f_args);
3113
3114   valist = build_va_arg_indirect_ref (valist);
3115   args =
3116     build3 (COMPONENT_REF, TREE_TYPE (f_args), valist, f_args, NULL_TREE);
3117   skip =
3118     build3 (COMPONENT_REF, TREE_TYPE (f_skip), valist, f_skip, NULL_TREE);
3119
3120   /* Find the __args area.  */
3121   t = make_tree (TREE_TYPE (args), nextarg);
3122   if (current_function_pretend_args_size > 0)
3123     t = build2 (POINTER_PLUS_EXPR, TREE_TYPE (args), t,
3124                 size_int (-STACK_POINTER_OFFSET));
3125   t = build2 (GIMPLE_MODIFY_STMT, TREE_TYPE (args), args, t);
3126   TREE_SIDE_EFFECTS (t) = 1;
3127   expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
3128
3129   /* Find the __skip area.  */
3130   t = make_tree (TREE_TYPE (skip), virtual_incoming_args_rtx);
3131   t = build2 (POINTER_PLUS_EXPR, TREE_TYPE (skip), t,
3132               size_int (current_function_pretend_args_size
3133                          - STACK_POINTER_OFFSET));
3134   t = build2 (GIMPLE_MODIFY_STMT, TREE_TYPE (skip), skip, t);
3135   TREE_SIDE_EFFECTS (t) = 1;
3136   expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
3137 }
3138
3139 /* Gimplify va_arg by updating the va_list structure 
3140    VALIST as required to retrieve an argument of type
3141    TYPE, and returning that argument. 
3142    
3143    ret = va_arg(VALIST, TYPE);
3144
3145    generates code equivalent to:
3146    
3147     paddedsize = (sizeof(TYPE) + 15) & -16;
3148     if (VALIST.__args + paddedsize > VALIST.__skip
3149         && VALIST.__args <= VALIST.__skip)
3150       addr = VALIST.__skip + 32;
3151     else
3152       addr = VALIST.__args;
3153     VALIST.__args = addr + paddedsize;
3154     ret = *(TYPE *)addr;
3155  */
3156 static tree
3157 spu_gimplify_va_arg_expr (tree valist, tree type, tree * pre_p,
3158                           tree * post_p ATTRIBUTE_UNUSED)
3159 {
3160   tree f_args, f_skip;
3161   tree args, skip;
3162   HOST_WIDE_INT size, rsize;
3163   tree paddedsize, addr, tmp;
3164   bool pass_by_reference_p;
3165
3166   f_args = TYPE_FIELDS (TREE_TYPE (va_list_type_node));
3167   f_skip = TREE_CHAIN (f_args);
3168
3169   valist = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (valist)), valist);
3170   args =
3171     build3 (COMPONENT_REF, TREE_TYPE (f_args), valist, f_args, NULL_TREE);
3172   skip =
3173     build3 (COMPONENT_REF, TREE_TYPE (f_skip), valist, f_skip, NULL_TREE);
3174
3175   addr = create_tmp_var (ptr_type_node, "va_arg");
3176   DECL_POINTER_ALIAS_SET (addr) = get_varargs_alias_set ();
3177
3178   /* if an object is dynamically sized, a pointer to it is passed
3179      instead of the object itself. */
3180   pass_by_reference_p = spu_pass_by_reference (NULL, TYPE_MODE (type), type,
3181                                                false);
3182   if (pass_by_reference_p)
3183     type = build_pointer_type (type);
3184   size = int_size_in_bytes (type);
3185   rsize = ((size + UNITS_PER_WORD - 1) / UNITS_PER_WORD) * UNITS_PER_WORD;
3186
3187   /* build conditional expression to calculate addr. The expression
3188      will be gimplified later. */
3189   paddedsize = size_int (rsize);
3190   tmp = build2 (POINTER_PLUS_EXPR, ptr_type_node, args, paddedsize);
3191   tmp = build2 (TRUTH_AND_EXPR, boolean_type_node,
3192                 build2 (GT_EXPR, boolean_type_node, tmp, skip),
3193                 build2 (LE_EXPR, boolean_type_node, args, skip));
3194
3195   tmp = build3 (COND_EXPR, ptr_type_node, tmp,
3196                 build2 (POINTER_PLUS_EXPR, ptr_type_node, skip,
3197                         size_int (32)), args);
3198
3199   tmp = build2 (GIMPLE_MODIFY_STMT, ptr_type_node, addr, tmp);
3200   gimplify_and_add (tmp, pre_p);
3201
3202   /* update VALIST.__args */
3203   tmp = build2 (POINTER_PLUS_EXPR, ptr_type_node, addr, paddedsize);
3204   tmp = build2 (GIMPLE_MODIFY_STMT, TREE_TYPE (args), args, tmp);
3205   gimplify_and_add (tmp, pre_p);
3206
3207   addr = fold_convert (build_pointer_type (type), addr);
3208
3209   if (pass_by_reference_p)
3210     addr = build_va_arg_indirect_ref (addr);
3211
3212   return build_va_arg_indirect_ref (addr);
3213 }
3214
3215 /* Save parameter registers starting with the register that corresponds
3216    to the first unnamed parameters.  If the first unnamed parameter is
3217    in the stack then save no registers.  Set pretend_args_size to the
3218    amount of space needed to save the registers. */
3219 void
3220 spu_setup_incoming_varargs (CUMULATIVE_ARGS * cum, enum machine_mode mode,
3221                             tree type, int *pretend_size, int no_rtl)
3222 {
3223   if (!no_rtl)
3224     {
3225       rtx tmp;
3226       int regno;
3227       int offset;
3228       int ncum = *cum;
3229
3230       /* cum currently points to the last named argument, we want to
3231          start at the next argument. */
3232       FUNCTION_ARG_ADVANCE (ncum, mode, type, 1);
3233
3234       offset = -STACK_POINTER_OFFSET;
3235       for (regno = ncum; regno < MAX_REGISTER_ARGS; regno++)
3236         {
3237           tmp = gen_frame_mem (V4SImode,
3238                                plus_constant (virtual_incoming_args_rtx,
3239                                               offset));
3240           emit_move_insn (tmp,
3241                           gen_rtx_REG (V4SImode, FIRST_ARG_REGNUM + regno));
3242           offset += 16;
3243         }
3244       *pretend_size = offset + STACK_POINTER_OFFSET;
3245     }
3246 }
3247 \f
3248 void
3249 spu_conditional_register_usage (void)
3250 {
3251   if (flag_pic)
3252     {
3253       fixed_regs[PIC_OFFSET_TABLE_REGNUM] = 1;
3254       call_used_regs[PIC_OFFSET_TABLE_REGNUM] = 1;
3255     }
3256 }
3257
3258 /* This is called to decide when we can simplify a load instruction.  We
3259    must only return true for registers which we know will always be
3260    aligned.  Taking into account that CSE might replace this reg with
3261    another one that has not been marked aligned.  
3262    So this is really only true for frame, stack and virtual registers,
3263    which we know are always aligned and should not be adversely effected
3264    by CSE.  */
3265 static int
3266 regno_aligned_for_load (int regno)
3267 {
3268   return regno == FRAME_POINTER_REGNUM
3269     || (frame_pointer_needed && regno == HARD_FRAME_POINTER_REGNUM)
3270     || regno == STACK_POINTER_REGNUM
3271     || (regno >= FIRST_VIRTUAL_REGISTER 
3272         && regno <= LAST_VIRTUAL_REGISTER);
3273 }
3274
3275 /* Return TRUE when mem is known to be 16-byte aligned. */
3276 int
3277 aligned_mem_p (rtx mem)
3278 {
3279   if (MEM_ALIGN (mem) >= 128)
3280     return 1;
3281   if (GET_MODE_SIZE (GET_MODE (mem)) >= 16)
3282     return 1;
3283   if (GET_CODE (XEXP (mem, 0)) == PLUS)
3284     {
3285       rtx p0 = XEXP (XEXP (mem, 0), 0);
3286       rtx p1 = XEXP (XEXP (mem, 0), 1);
3287       if (regno_aligned_for_load (REGNO (p0)))
3288         {
3289           if (GET_CODE (p1) == REG && regno_aligned_for_load (REGNO (p1)))
3290             return 1;
3291           if (GET_CODE (p1) == CONST_INT && (INTVAL (p1) & 15) == 0)
3292             return 1;
3293         }
3294     }
3295   else if (GET_CODE (XEXP (mem, 0)) == REG)
3296     {
3297       if (regno_aligned_for_load (REGNO (XEXP (mem, 0))))
3298         return 1;
3299     }
3300   else if (ALIGNED_SYMBOL_REF_P (XEXP (mem, 0)))
3301     return 1;
3302   else if (GET_CODE (XEXP (mem, 0)) == CONST)
3303     {
3304       rtx p0 = XEXP (XEXP (XEXP (mem, 0), 0), 0);
3305       rtx p1 = XEXP (XEXP (XEXP (mem, 0), 0), 1);
3306       if (GET_CODE (p0) == SYMBOL_REF
3307           && GET_CODE (p1) == CONST_INT && (INTVAL (p1) & 15) == 0)
3308         return 1;
3309     }
3310   return 0;
3311 }
3312
3313 /* Encode symbol attributes (local vs. global, tls model) of a SYMBOL_REF
3314    into its SYMBOL_REF_FLAGS.  */
3315 static void
3316 spu_encode_section_info (tree decl, rtx rtl, int first)
3317 {
3318   default_encode_section_info (decl, rtl, first);
3319
3320   /* If a variable has a forced alignment to < 16 bytes, mark it with
3321      SYMBOL_FLAG_ALIGN1.  */
3322   if (TREE_CODE (decl) == VAR_DECL
3323       && DECL_USER_ALIGN (decl) && DECL_ALIGN (decl) < 128)
3324     SYMBOL_REF_FLAGS (XEXP (rtl, 0)) |= SYMBOL_FLAG_ALIGN1;
3325 }
3326
3327 /* Return TRUE if we are certain the mem refers to a complete object
3328    which is both 16-byte aligned and padded to a 16-byte boundary.  This
3329    would make it safe to store with a single instruction. 
3330    We guarantee the alignment and padding for static objects by aligning
3331    all of them to 16-bytes. (DATA_ALIGNMENT and CONSTANT_ALIGNMENT.)
3332    FIXME: We currently cannot guarantee this for objects on the stack
3333    because assign_parm_setup_stack calls assign_stack_local with the
3334    alignment of the parameter mode and in that case the alignment never
3335    gets adjusted by LOCAL_ALIGNMENT. */
3336 static int
3337 store_with_one_insn_p (rtx mem)
3338 {
3339   rtx addr = XEXP (mem, 0);
3340   if (GET_MODE (mem) == BLKmode)
3341     return 0;
3342   /* Only static objects. */
3343   if (GET_CODE (addr) == SYMBOL_REF)
3344     {
3345       /* We use the associated declaration to make sure the access is
3346          referring to the whole object.
3347          We check both MEM_EXPR and and SYMBOL_REF_DECL.  I'm not sure
3348          if it is necessary.  Will there be cases where one exists, and
3349          the other does not?  Will there be cases where both exist, but
3350          have different types?  */
3351       tree decl = MEM_EXPR (mem);
3352       if (decl
3353           && TREE_CODE (decl) == VAR_DECL
3354           && GET_MODE (mem) == TYPE_MODE (TREE_TYPE (decl)))
3355         return 1;
3356       decl = SYMBOL_REF_DECL (addr);
3357       if (decl
3358           && TREE_CODE (decl) == VAR_DECL
3359           && GET_MODE (mem) == TYPE_MODE (TREE_TYPE (decl)))
3360         return 1;
3361     }
3362   return 0;
3363 }
3364
3365 int
3366 spu_expand_mov (rtx * ops, enum machine_mode mode)
3367 {
3368   if (GET_CODE (ops[0]) == SUBREG && !valid_subreg (ops[0]))
3369     abort ();
3370
3371   if (GET_CODE (ops[1]) == SUBREG && !valid_subreg (ops[1]))
3372     {
3373       rtx from = SUBREG_REG (ops[1]);
3374       enum machine_mode imode = GET_MODE (from);
3375
3376       gcc_assert (GET_MODE_CLASS (mode) == MODE_INT
3377                   && GET_MODE_CLASS (imode) == MODE_INT
3378                   && subreg_lowpart_p (ops[1]));
3379
3380       if (GET_MODE_SIZE (imode) < 4)
3381         {
3382           from = gen_rtx_SUBREG (SImode, from, 0);
3383           imode = SImode;
3384         }
3385
3386       if (GET_MODE_SIZE (mode) < GET_MODE_SIZE (imode))
3387         {
3388           enum insn_code icode = trunc_optab->handlers[mode][imode].insn_code;
3389           emit_insn (GEN_FCN (icode) (ops[0], from));
3390         }
3391       else
3392         emit_insn (gen_extend_insn (ops[0], from, mode, imode, 1));
3393       return 1;
3394     }
3395
3396   /* At least one of the operands needs to be a register. */
3397   if ((reload_in_progress | reload_completed) == 0
3398       && !register_operand (ops[0], mode) && !register_operand (ops[1], mode))
3399     {
3400       rtx temp = force_reg (mode, ops[1]);
3401       emit_move_insn (ops[0], temp);
3402       return 1;
3403     }
3404   if (reload_in_progress || reload_completed)
3405     {
3406       if (CONSTANT_P (ops[1]))
3407         return spu_split_immediate (ops);
3408       return 0;
3409     }
3410   else
3411     {
3412       if (GET_CODE (ops[0]) == MEM)
3413         {
3414           if (!spu_valid_move (ops))
3415             {
3416               emit_insn (gen_store (ops[0], ops[1], gen_reg_rtx (TImode),
3417                                     gen_reg_rtx (TImode)));
3418               return 1;
3419             }
3420         }
3421       else if (GET_CODE (ops[1]) == MEM)
3422         {
3423           if (!spu_valid_move (ops))
3424             {
3425               emit_insn (gen_load
3426                          (ops[0], ops[1], gen_reg_rtx (TImode),
3427                           gen_reg_rtx (SImode)));
3428               return 1;
3429             }
3430         }
3431       /* Catch the SImode immediates greater than 0x7fffffff, and sign
3432          extend them. */
3433       if (GET_CODE (ops[1]) == CONST_INT)
3434         {
3435           HOST_WIDE_INT val = trunc_int_for_mode (INTVAL (ops[1]), mode);
3436           if (val != INTVAL (ops[1]))
3437             {
3438               emit_move_insn (ops[0], GEN_INT (val));
3439               return 1;
3440             }
3441         }
3442     }
3443   return 0;
3444 }
3445
3446 static int
3447 reg_align (rtx reg)
3448 {
3449   /* For now, only frame registers are known to be aligned at all times.
3450      We can't trust REGNO_POINTER_ALIGN because optimization will move
3451      registers around, potentially changing an "aligned" register in an
3452      address to an unaligned register, which would result in an invalid
3453      address. */
3454   int regno = REGNO (reg);
3455   return REGNO_PTR_FRAME_P (regno) ? REGNO_POINTER_ALIGN (regno) : 1;
3456 }
3457
3458 void
3459 spu_split_load (rtx * ops)
3460 {
3461   enum machine_mode mode = GET_MODE (ops[0]);
3462   rtx addr, load, rot, mem, p0, p1;
3463   int rot_amt;
3464
3465   addr = XEXP (ops[1], 0);
3466
3467   rot = 0;
3468   rot_amt = 0;
3469   if (GET_CODE (addr) == PLUS)
3470     {
3471       /* 8 cases:
3472          aligned reg   + aligned reg     => lqx
3473          aligned reg   + unaligned reg   => lqx, rotqby
3474          aligned reg   + aligned const   => lqd
3475          aligned reg   + unaligned const => lqd, rotqbyi
3476          unaligned reg + aligned reg     => lqx, rotqby
3477          unaligned reg + unaligned reg   => lqx, a, rotqby (1 scratch)
3478          unaligned reg + aligned const   => lqd, rotqby
3479          unaligned reg + unaligned const -> not allowed by legitimate address
3480        */
3481       p0 = XEXP (addr, 0);
3482       p1 = XEXP (addr, 1);
3483       if (reg_align (p0) < 128)
3484         {
3485           if (GET_CODE (p1) == REG && reg_align (p1) < 128)
3486             {
3487               emit_insn (gen_addsi3 (ops[3], p0, p1));
3488               rot = ops[3];
3489             }
3490           else
3491             rot = p0;
3492         }
3493       else
3494         {
3495           if (GET_CODE (p1) == CONST_INT && (INTVAL (p1) & 15))
3496             {
3497               rot_amt = INTVAL (p1) & 15;
3498               p1 = GEN_INT (INTVAL (p1) & -16);
3499               addr = gen_rtx_PLUS (SImode, p0, p1);
3500             }
3501           else if (GET_CODE (p1) == REG && reg_align (p1) < 128)
3502             rot = p1;
3503         }
3504     }
3505   else if (GET_CODE (addr) == REG)
3506     {
3507       if (reg_align (addr) < 128)
3508         rot = addr;
3509     }
3510   else if (GET_CODE (addr) == CONST)
3511     {
3512       if (GET_CODE (XEXP (addr, 0)) == PLUS
3513           && ALIGNED_SYMBOL_REF_P (XEXP (XEXP (addr, 0), 0))
3514           && GET_CODE (XEXP (XEXP (addr, 0), 1)) == CONST_INT)
3515         {
3516           rot_amt = INTVAL (XEXP (XEXP (addr, 0), 1));
3517           if (rot_amt & -16)
3518             addr = gen_rtx_CONST (Pmode,
3519                                   gen_rtx_PLUS (Pmode,
3520                                                 XEXP (XEXP (addr, 0), 0),
3521                                                 GEN_INT (rot_amt & -16)));
3522           else
3523             addr = XEXP (XEXP (addr, 0), 0);
3524         }
3525       else
3526         rot = addr;
3527     }
3528   else if (GET_CODE (addr) == CONST_INT)
3529     {
3530       rot_amt = INTVAL (addr);
3531       addr = GEN_INT (rot_amt & -16);
3532     }
3533   else if (!ALIGNED_SYMBOL_REF_P (addr))
3534     rot = addr;
3535
3536   if (GET_MODE_SIZE (mode) < 4)
3537     rot_amt += GET_MODE_SIZE (mode) - 4;
3538
3539   rot_amt &= 15;
3540
3541   if (rot && rot_amt)
3542     {
3543       emit_insn (gen_addsi3 (ops[3], rot, GEN_INT (rot_amt)));
3544       rot = ops[3];
3545       rot_amt = 0;
3546     }
3547
3548   load = ops[2];
3549
3550   addr = gen_rtx_AND (SImode, copy_rtx (addr), GEN_INT (-16));
3551   mem = change_address (ops[1], TImode, addr);
3552
3553   emit_insn (gen_movti (load, mem));
3554
3555   if (rot)
3556     emit_insn (gen_rotqby_ti (load, load, rot));
3557   else if (rot_amt)
3558     emit_insn (gen_rotlti3 (load, load, GEN_INT (rot_amt * 8)));
3559
3560   if (reload_completed)
3561     emit_move_insn (ops[0], gen_rtx_REG (GET_MODE (ops[0]), REGNO (load)));
3562   else
3563     emit_insn (gen_spu_convert (ops[0], load));
3564 }
3565
3566 void
3567 spu_split_store (rtx * ops)
3568 {
3569   enum machine_mode mode = GET_MODE (ops[0]);
3570   rtx pat = ops[2];
3571   rtx reg = ops[3];
3572   rtx addr, p0, p1, p1_lo, smem;
3573   int aform;
3574   int scalar;
3575
3576   addr = XEXP (ops[0], 0);
3577
3578   if (GET_CODE (addr) == PLUS)
3579     {
3580       /* 8 cases:
3581          aligned reg   + aligned reg     => lqx, c?x, shuf, stqx
3582          aligned reg   + unaligned reg   => lqx, c?x, shuf, stqx
3583          aligned reg   + aligned const   => lqd, c?d, shuf, stqx
3584          aligned reg   + unaligned const => lqd, c?d, shuf, stqx
3585          unaligned reg + aligned reg     => lqx, c?x, shuf, stqx
3586          unaligned reg + unaligned reg   => lqx, c?x, shuf, stqx
3587          unaligned reg + aligned const   => lqd, c?d, shuf, stqx
3588          unaligned reg + unaligned const -> not allowed by legitimate address
3589        */
3590       aform = 0;
3591       p0 = XEXP (addr, 0);
3592       p1 = p1_lo = XEXP (addr, 1);
3593       if (GET_CODE (p0) == REG && GET_CODE (p1) == CONST_INT)
3594         {
3595           p1_lo = GEN_INT (INTVAL (p1) & 15);
3596           p1 = GEN_INT (INTVAL (p1) & -16);
3597           addr = gen_rtx_PLUS (SImode, p0, p1);
3598         }
3599     }
3600   else if (GET_CODE (addr) == REG)
3601     {
3602       aform = 0;
3603       p0 = addr;
3604       p1 = p1_lo = const0_rtx;
3605     }
3606   else
3607     {
3608       aform = 1;
3609       p0 = gen_rtx_REG (SImode, STACK_POINTER_REGNUM);
3610       p1 = 0;                   /* aform doesn't use p1 */
3611       p1_lo = addr;
3612       if (ALIGNED_SYMBOL_REF_P (addr))
3613         p1_lo = const0_rtx;
3614       else if (GET_CODE (addr) == CONST)
3615         {
3616           if (GET_CODE (XEXP (addr, 0)) == PLUS
3617               && ALIGNED_SYMBOL_REF_P (XEXP (XEXP (addr, 0), 0))
3618               && GET_CODE (XEXP (XEXP (addr, 0), 1)) == CONST_INT)
3619             {
3620               HOST_WIDE_INT v = INTVAL (XEXP (XEXP (addr, 0), 1));
3621               if ((v & -16) != 0)
3622                 addr = gen_rtx_CONST (Pmode,
3623                                       gen_rtx_PLUS (Pmode,
3624                                                     XEXP (XEXP (addr, 0), 0),
3625                                                     GEN_INT (v & -16)));
3626               else
3627                 addr = XEXP (XEXP (addr, 0), 0);
3628               p1_lo = GEN_INT (v & 15);
3629             }
3630         }
3631       else if (GET_CODE (addr) == CONST_INT)
3632         {
3633           p1_lo = GEN_INT (INTVAL (addr) & 15);
3634           addr = GEN_INT (INTVAL (addr) & -16);
3635         }
3636     }
3637
3638   addr = gen_rtx_AND (SImode, copy_rtx (addr), GEN_INT (-16));
3639
3640   scalar = store_with_one_insn_p (ops[0]);
3641   if (!scalar)
3642     {
3643       /* We could copy the flags from the ops[0] MEM to mem here,
3644          We don't because we want this load to be optimized away if
3645          possible, and copying the flags will prevent that in certain
3646          cases, e.g. consider the volatile flag. */
3647
3648       rtx lmem = change_address (ops[0], TImode, copy_rtx (addr));
3649       set_mem_alias_set (lmem, 0);
3650       emit_insn (gen_movti (reg, lmem));
3651
3652       if (!p0 || reg_align (p0) >= 128)
3653         p0 = stack_pointer_rtx;
3654       if (!p1_lo)
3655         p1_lo = const0_rtx;
3656
3657       emit_insn (gen_cpat (pat, p0, p1_lo, GEN_INT (GET_MODE_SIZE (mode))));
3658       emit_insn (gen_shufb (reg, ops[1], reg, pat));
3659     }
3660   else if (reload_completed)
3661     {
3662       if (GET_CODE (ops[1]) == REG)
3663         emit_move_insn (reg, gen_rtx_REG (GET_MODE (reg), REGNO (ops[1])));
3664       else if (GET_CODE (ops[1]) == SUBREG)
3665         emit_move_insn (reg,
3666                         gen_rtx_REG (GET_MODE (reg),
3667                                      REGNO (SUBREG_REG (ops[1]))));
3668       else
3669         abort ();
3670     }
3671   else
3672     {
3673       if (GET_CODE (ops[1]) == REG)
3674         emit_insn (gen_spu_convert (reg, ops[1]));
3675       else if (GET_CODE (ops[1]) == SUBREG)
3676         emit_insn (gen_spu_convert (reg, SUBREG_REG (ops[1])));
3677       else
3678         abort ();
3679     }
3680
3681   if (GET_MODE_SIZE (mode) < 4 && scalar)
3682     emit_insn (gen_shlqby_ti
3683                (reg, reg, GEN_INT (4 - GET_MODE_SIZE (mode))));
3684
3685   smem = change_address (ops[0], TImode, addr);
3686   /* We can't use the previous alias set because the memory has changed
3687      size and can potentially overlap objects of other types.  */
3688   set_mem_alias_set (smem, 0);
3689
3690   emit_insn (gen_movti (smem, reg));
3691 }
3692
3693 /* Return TRUE if X is MEM which is a struct member reference
3694    and the member can safely be loaded and stored with a single
3695    instruction because it is padded. */
3696 static int
3697 mem_is_padded_component_ref (rtx x)
3698 {
3699   tree t = MEM_EXPR (x);
3700   tree r;
3701   if (!t || TREE_CODE (t) != COMPONENT_REF)
3702     return 0;
3703   t = TREE_OPERAND (t, 1);
3704   if (!t || TREE_CODE (t) != FIELD_DECL
3705       || DECL_ALIGN (t) < 128 || AGGREGATE_TYPE_P (TREE_TYPE (t)))
3706     return 0;
3707   /* Only do this for RECORD_TYPEs, not UNION_TYPEs. */
3708   r = DECL_FIELD_CONTEXT (t);
3709   if (!r || TREE_CODE (r) != RECORD_TYPE)
3710     return 0;
3711   /* Make sure they are the same mode */
3712   if (GET_MODE (x) != TYPE_MODE (TREE_TYPE (t)))
3713     return 0;
3714   /* If there are no following fields then the field alignment assures
3715      the structure is padded to the alignment which means this field is
3716      padded too.  */
3717   if (TREE_CHAIN (t) == 0)
3718     return 1;
3719   /* If the following field is also aligned then this field will be
3720      padded. */
3721   t = TREE_CHAIN (t);
3722   if (TREE_CODE (t) == FIELD_DECL && DECL_ALIGN (t) >= 128)
3723     return 1;
3724   return 0;
3725 }
3726
3727 /* Parse the -mfixed-range= option string.  */
3728 static void
3729 fix_range (const char *const_str)
3730 {
3731   int i, first, last;
3732   char *str, *dash, *comma;
3733   
3734   /* str must be of the form REG1'-'REG2{,REG1'-'REG} where REG1 and
3735      REG2 are either register names or register numbers.  The effect
3736      of this option is to mark the registers in the range from REG1 to
3737      REG2 as ``fixed'' so they won't be used by the compiler.  */
3738   
3739   i = strlen (const_str);
3740   str = (char *) alloca (i + 1);
3741   memcpy (str, const_str, i + 1);
3742   
3743   while (1)
3744     {
3745       dash = strchr (str, '-');
3746       if (!dash)
3747         {
3748           warning (0, "value of -mfixed-range must have form REG1-REG2");
3749           return;
3750         }
3751       *dash = '\0';
3752       comma = strchr (dash + 1, ',');
3753       if (comma)
3754         *comma = '\0';
3755       
3756       first = decode_reg_name (str);
3757       if (first < 0)
3758         {
3759           warning (0, "unknown register name: %s", str);
3760           return;
3761         }
3762       
3763       last = decode_reg_name (dash + 1);
3764       if (last < 0)
3765         {
3766           warning (0, "unknown register name: %s", dash + 1);
3767           return;
3768         }
3769       
3770       *dash = '-';
3771       
3772       if (first > last)
3773         {
3774           warning (0, "%s-%s is an empty range", str, dash + 1);
3775           return;
3776         }
3777       
3778       for (i = first; i <= last; ++i)
3779         fixed_regs[i] = call_used_regs[i] = 1;
3780
3781       if (!comma)
3782         break;
3783
3784       *comma = ',';
3785       str = comma + 1;
3786     }
3787 }
3788
3789 int
3790 spu_valid_move (rtx * ops)
3791 {
3792   enum machine_mode mode = GET_MODE (ops[0]);
3793   if (!register_operand (ops[0], mode) && !register_operand (ops[1], mode))
3794     return 0;
3795
3796   /* init_expr_once tries to recog against load and store insns to set
3797      the direct_load[] and direct_store[] arrays.  We always want to
3798      consider those loads and stores valid.  init_expr_once is called in
3799      the context of a dummy function which does not have a decl. */
3800   if (cfun->decl == 0)
3801     return 1;
3802
3803   /* Don't allows loads/stores which would require more than 1 insn.
3804      During and after reload we assume loads and stores only take 1
3805      insn. */
3806   if (GET_MODE_SIZE (mode) < 16 && !reload_in_progress && !reload_completed)
3807     {
3808       if (GET_CODE (ops[0]) == MEM
3809           && (GET_MODE_SIZE (mode) < 4
3810               || !(store_with_one_insn_p (ops[0])
3811                    || mem_is_padded_component_ref (ops[0]))))
3812         return 0;
3813       if (GET_CODE (ops[1]) == MEM
3814           && (GET_MODE_SIZE (mode) < 4 || !aligned_mem_p (ops[1])))
3815         return 0;
3816     }
3817   return 1;
3818 }
3819
3820 /* Return TRUE if x is a CONST_INT, CONST_DOUBLE or CONST_VECTOR that
3821    can be generated using the fsmbi instruction. */
3822 int
3823 fsmbi_const_p (rtx x)
3824 {
3825   if (CONSTANT_P (x))
3826     {
3827       /* We can always choose TImode for CONST_INT because the high bits
3828          of an SImode will always be all 1s, i.e., valid for fsmbi. */
3829       enum immediate_class c = classify_immediate (x, TImode);
3830       return c == IC_FSMBI || (!epilogue_completed && c == IC_FSMBI2);
3831     }
3832   return 0;
3833 }
3834
3835 /* Return TRUE if x is a CONST_INT, CONST_DOUBLE or CONST_VECTOR that
3836    can be generated using the cbd, chd, cwd or cdd instruction. */
3837 int
3838 cpat_const_p (rtx x, enum machine_mode mode)
3839 {
3840   if (CONSTANT_P (x))
3841     {
3842       enum immediate_class c = classify_immediate (x, mode);
3843       return c == IC_CPAT;
3844     }
3845   return 0;
3846 }
3847
3848 rtx
3849 gen_cpat_const (rtx * ops)
3850 {
3851   unsigned char dst[16];
3852   int i, offset, shift, isize;
3853   if (GET_CODE (ops[3]) != CONST_INT
3854       || GET_CODE (ops[2]) != CONST_INT
3855       || (GET_CODE (ops[1]) != CONST_INT
3856           && GET_CODE (ops[1]) != REG))
3857     return 0;
3858   if (GET_CODE (ops[1]) == REG
3859       && (!REG_POINTER (ops[1])
3860           || REGNO_POINTER_ALIGN (ORIGINAL_REGNO (ops[1])) < 128))
3861     return 0;
3862
3863   for (i = 0; i < 16; i++)
3864     dst[i] = i + 16;
3865   isize = INTVAL (ops[3]);
3866   if (isize == 1)
3867     shift = 3;
3868   else if (isize == 2)
3869     shift = 2;
3870   else
3871     shift = 0;
3872   offset = (INTVAL (ops[2]) +
3873             (GET_CODE (ops[1]) ==
3874              CONST_INT ? INTVAL (ops[1]) : 0)) & 15;
3875   for (i = 0; i < isize; i++)
3876     dst[offset + i] = i + shift;
3877   return array_to_constant (TImode, dst);
3878 }
3879
3880 /* Convert a CONST_INT, CONST_DOUBLE, or CONST_VECTOR into a 16 byte
3881    array.  Use MODE for CONST_INT's.  When the constant's mode is smaller
3882    than 16 bytes, the value is repeated across the rest of the array. */
3883 void
3884 constant_to_array (enum machine_mode mode, rtx x, unsigned char arr[16])
3885 {
3886   HOST_WIDE_INT val;
3887   int i, j, first;
3888
3889   memset (arr, 0, 16);
3890   mode = GET_MODE (x) != VOIDmode ? GET_MODE (x) : mode;
3891   if (GET_CODE (x) == CONST_INT
3892       || (GET_CODE (x) == CONST_DOUBLE
3893           && (mode == SFmode || mode == DFmode)))
3894     {
3895       gcc_assert (mode != VOIDmode && mode != BLKmode);
3896
3897       if (GET_CODE (x) == CONST_DOUBLE)
3898         val = const_double_to_hwint (x);
3899       else
3900         val = INTVAL (x);
3901       first = GET_MODE_SIZE (mode) - 1;
3902       for (i = first; i >= 0; i--)
3903         {
3904           arr[i] = val & 0xff;
3905           val >>= 8;
3906         }
3907       /* Splat the constant across the whole array. */
3908       for (j = 0, i = first + 1; i < 16; i++)
3909         {
3910           arr[i] = arr[j];
3911           j = (j == first) ? 0 : j + 1;
3912         }
3913     }
3914   else if (GET_CODE (x) == CONST_DOUBLE)
3915     {
3916       val = CONST_DOUBLE_LOW (x);
3917       for (i = 15; i >= 8; i--)
3918         {
3919           arr[i] = val & 0xff;
3920           val >>= 8;
3921         }
3922       val = CONST_DOUBLE_HIGH (x);
3923       for (i = 7; i >= 0; i--)
3924         {
3925           arr[i] = val & 0xff;
3926           val >>= 8;
3927         }
3928     }
3929   else if (GET_CODE (x) == CONST_VECTOR)
3930     {
3931       int units;
3932       rtx elt;
3933       mode = GET_MODE_INNER (mode);
3934       units = CONST_VECTOR_NUNITS (x);
3935       for (i = 0; i < units; i++)
3936         {
3937           elt = CONST_VECTOR_ELT (x, i);
3938           if (GET_CODE (elt) == CONST_INT || GET_CODE (elt) == CONST_DOUBLE)
3939             {
3940               if (GET_CODE (elt) == CONST_DOUBLE)
3941                 val = const_double_to_hwint (elt);
3942               else
3943                 val = INTVAL (elt);
3944               first = GET_MODE_SIZE (mode) - 1;
3945               if (first + i * GET_MODE_SIZE (mode) > 16)
3946                 abort ();
3947               for (j = first; j >= 0; j--)
3948                 {
3949                   arr[j + i * GET_MODE_SIZE (mode)] = val & 0xff;
3950                   val >>= 8;
3951                 }
3952             }
3953         }
3954     }
3955   else
3956     gcc_unreachable();
3957 }
3958
3959 /* Convert a 16 byte array to a constant of mode MODE.  When MODE is
3960    smaller than 16 bytes, use the bytes that would represent that value
3961    in a register, e.g., for QImode return the value of arr[3].  */
3962 rtx
3963 array_to_constant (enum machine_mode mode, unsigned char arr[16])
3964 {
3965   enum machine_mode inner_mode;
3966   rtvec v;
3967   int units, size, i, j, k;
3968   HOST_WIDE_INT val;
3969
3970   if (GET_MODE_CLASS (mode) == MODE_INT
3971       && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT)
3972     {
3973       j = GET_MODE_SIZE (mode);
3974       i = j < 4 ? 4 - j : 0;
3975       for (val = 0; i < j; i++)
3976         val = (val << 8) | arr[i];
3977       val = trunc_int_for_mode (val, mode);
3978       return GEN_INT (val);
3979     }
3980
3981   if (mode == TImode)
3982     {
3983       HOST_WIDE_INT high;
3984       for (i = high = 0; i < 8; i++)
3985         high = (high << 8) | arr[i];
3986       for (i = 8, val = 0; i < 16; i++)
3987         val = (val << 8) | arr[i];
3988       return immed_double_const (val, high, TImode);
3989     }
3990   if (mode == SFmode)
3991     {
3992       val = (arr[0] << 24) | (arr[1] << 16) | (arr[2] << 8) | arr[3];
3993       val = trunc_int_for_mode (val, SImode);
3994       return hwint_to_const_double (SFmode, val);
3995     }
3996   if (mode == DFmode)
3997     {
3998       val = (arr[0] << 24) | (arr[1] << 16) | (arr[2] << 8) | arr[3];
3999       val <<= 32;
4000       val |= (arr[4] << 24) | (arr[5] << 16) | (arr[6] << 8) | arr[7];
4001       return hwint_to_const_double (DFmode, val);
4002     }
4003
4004   if (!VECTOR_MODE_P (mode))
4005     abort ();
4006
4007   units = GET_MODE_NUNITS (mode);
4008   size = GET_MODE_UNIT_SIZE (mode);
4009   inner_mode = GET_MODE_INNER (mode);
4010   v = rtvec_alloc (units);
4011
4012   for (k = i = 0; i < units; ++i)
4013     {
4014       val = 0;
4015       for (j = 0; j < size; j++, k++)
4016         val = (val << 8) | arr[k];
4017
4018       if (GET_MODE_CLASS (inner_mode) == MODE_FLOAT)
4019         RTVEC_ELT (v, i) = hwint_to_const_double (inner_mode, val);
4020       else
4021         RTVEC_ELT (v, i) = GEN_INT (trunc_int_for_mode (val, inner_mode));
4022     }
4023   if (k > 16)
4024     abort ();
4025
4026   return gen_rtx_CONST_VECTOR (mode, v);
4027 }
4028
4029 static void
4030 reloc_diagnostic (rtx x)
4031 {
4032   tree loc_decl, decl = 0;
4033   const char *msg;
4034   if (!flag_pic || !(TARGET_WARN_RELOC || TARGET_ERROR_RELOC))
4035     return;
4036
4037   if (GET_CODE (x) == SYMBOL_REF)
4038     decl = SYMBOL_REF_DECL (x);
4039   else if (GET_CODE (x) == CONST
4040            && GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF)
4041     decl = SYMBOL_REF_DECL (XEXP (XEXP (x, 0), 0));
4042
4043   /* SYMBOL_REF_DECL is not necessarily a DECL. */
4044   if (decl && !DECL_P (decl))
4045     decl = 0;
4046
4047   /* We use last_assemble_variable_decl to get line information.  It's
4048      not always going to be right and might not even be close, but will
4049      be right for the more common cases. */
4050   if (!last_assemble_variable_decl || in_section == ctors_section)
4051     loc_decl = decl;
4052   else
4053     loc_decl = last_assemble_variable_decl;
4054
4055   /* The decl could be a string constant.  */
4056   if (decl && DECL_P (decl))
4057     msg = "%Jcreating run-time relocation for %qD";
4058   else
4059     msg = "creating run-time relocation";
4060
4061   if (TARGET_WARN_RELOC)
4062     warning (0, msg, loc_decl, decl);
4063   else
4064     error (msg, loc_decl, decl);
4065 }
4066
4067 /* Hook into assemble_integer so we can generate an error for run-time
4068    relocations.  The SPU ABI disallows them. */
4069 static bool
4070 spu_assemble_integer (rtx x, unsigned int size, int aligned_p)
4071 {
4072   /* By default run-time relocations aren't supported, but we allow them
4073      in case users support it in their own run-time loader.  And we provide
4074      a warning for those users that don't.  */
4075   if ((GET_CODE (x) == SYMBOL_REF)
4076       || GET_CODE (x) == LABEL_REF || GET_CODE (x) == CONST)
4077     reloc_diagnostic (x);
4078
4079   return default_assemble_integer (x, size, aligned_p);
4080 }
4081
4082 static void
4083 spu_asm_globalize_label (FILE * file, const char *name)
4084 {
4085   fputs ("\t.global\t", file);
4086   assemble_name (file, name);
4087   fputs ("\n", file);
4088 }
4089
4090 static bool
4091 spu_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED, int *total)
4092 {
4093   enum machine_mode mode = GET_MODE (x);
4094   int cost = COSTS_N_INSNS (2);
4095
4096   /* Folding to a CONST_VECTOR will use extra space but there might
4097      be only a small savings in cycles.  We'd like to use a CONST_VECTOR
4098      only if it allows us to fold away multiple insns.  Changing the cost
4099      of a CONST_VECTOR here (or in CONST_COSTS) doesn't help though
4100      because this cost will only be compared against a single insn. 
4101      if (code == CONST_VECTOR)
4102        return (LEGITIMATE_CONSTANT_P(x)) ? cost : COSTS_N_INSNS(6);
4103    */
4104
4105   /* Use defaults for float operations.  Not accurate but good enough. */
4106   if (mode == DFmode)
4107     {
4108       *total = COSTS_N_INSNS (13);
4109       return true;
4110     }
4111   if (mode == SFmode)
4112     {
4113       *total = COSTS_N_INSNS (6);
4114       return true;
4115     }
4116   switch (code)
4117     {
4118     case CONST_INT:
4119       if (satisfies_constraint_K (x))
4120         *total = 0;
4121       else if (INTVAL (x) >= -0x80000000ll && INTVAL (x) <= 0xffffffffll)
4122         *total = COSTS_N_INSNS (1);
4123       else
4124         *total = COSTS_N_INSNS (3);
4125       return true;
4126
4127     case CONST:
4128       *total = COSTS_N_INSNS (3);
4129       return true;
4130
4131     case LABEL_REF:
4132     case SYMBOL_REF:
4133       *total = COSTS_N_INSNS (0);
4134       return true;
4135
4136     case CONST_DOUBLE:
4137       *total = COSTS_N_INSNS (5);
4138       return true;
4139
4140     case FLOAT_EXTEND:
4141     case FLOAT_TRUNCATE:
4142     case FLOAT:
4143     case UNSIGNED_FLOAT:
4144     case FIX:
4145     case UNSIGNED_FIX:
4146       *total = COSTS_N_INSNS (7);
4147       return true;
4148
4149     case PLUS:
4150       if (mode == TImode)
4151         {
4152           *total = COSTS_N_INSNS (9);
4153           return true;
4154         }
4155       break;
4156
4157     case MULT:
4158       cost =
4159         GET_CODE (XEXP (x, 0)) ==
4160         REG ? COSTS_N_INSNS (12) : COSTS_N_INSNS (7);
4161       if (mode == SImode && GET_CODE (XEXP (x, 0)) == REG)
4162         {
4163           if (GET_CODE (XEXP (x, 1)) == CONST_INT)
4164             {
4165               HOST_WIDE_INT val = INTVAL (XEXP (x, 1));
4166               cost = COSTS_N_INSNS (14);
4167               if ((val & 0xffff) == 0)
4168                 cost = COSTS_N_INSNS (9);
4169               else if (val > 0 && val < 0x10000)
4170                 cost = COSTS_N_INSNS (11);
4171             }
4172         }
4173       *total = cost;
4174       return true;
4175     case DIV:
4176     case UDIV:
4177     case MOD:
4178     case UMOD:
4179       *total = COSTS_N_INSNS (20);
4180       return true;
4181     case ROTATE:
4182     case ROTATERT:
4183     case ASHIFT:
4184     case ASHIFTRT:
4185     case LSHIFTRT:
4186       *total = COSTS_N_INSNS (4);
4187       return true;
4188     case UNSPEC:
4189       if (XINT (x, 1) == UNSPEC_CONVERT)
4190         *total = COSTS_N_INSNS (0);
4191       else
4192         *total = COSTS_N_INSNS (4);
4193       return true;
4194     }
4195   /* Scale cost by mode size.  Except when initializing (cfun->decl == 0). */
4196   if (GET_MODE_CLASS (mode) == MODE_INT
4197       && GET_MODE_SIZE (mode) > GET_MODE_SIZE (SImode) && cfun && cfun->decl)
4198     cost = cost * (GET_MODE_SIZE (mode) / GET_MODE_SIZE (SImode))
4199       * (GET_MODE_SIZE (mode) / GET_MODE_SIZE (SImode));
4200   *total = cost;
4201   return true;
4202 }
4203
4204 enum machine_mode
4205 spu_eh_return_filter_mode (void)
4206 {
4207   /* We would like this to be SImode, but sjlj exceptions seems to work
4208      only with word_mode. */
4209   return TImode;
4210 }
4211
4212 /* Decide whether we can make a sibling call to a function.  DECL is the
4213    declaration of the function being targeted by the call and EXP is the
4214    CALL_EXPR representing the call.  */
4215 static bool
4216 spu_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED)
4217 {
4218   return decl && !TARGET_LARGE_MEM;
4219 }
4220
4221 /* We need to correctly update the back chain pointer and the Available
4222    Stack Size (which is in the second slot of the sp register.) */
4223 void
4224 spu_allocate_stack (rtx op0, rtx op1)
4225 {
4226   HOST_WIDE_INT v;
4227   rtx chain = gen_reg_rtx (V4SImode);
4228   rtx stack_bot = gen_frame_mem (V4SImode, stack_pointer_rtx);
4229   rtx sp = gen_reg_rtx (V4SImode);
4230   rtx splatted = gen_reg_rtx (V4SImode);
4231   rtx pat = gen_reg_rtx (TImode);
4232
4233   /* copy the back chain so we can save it back again. */
4234   emit_move_insn (chain, stack_bot);
4235
4236   op1 = force_reg (SImode, op1);
4237
4238   v = 0x1020300010203ll;
4239   emit_move_insn (pat, immed_double_const (v, v, TImode));
4240   emit_insn (gen_shufb (splatted, op1, op1, pat));
4241
4242   emit_insn (gen_spu_convert (sp, stack_pointer_rtx));
4243   emit_insn (gen_subv4si3 (sp, sp, splatted));
4244
4245   if (flag_stack_check)
4246     {
4247       rtx avail = gen_reg_rtx(SImode);
4248       rtx result = gen_reg_rtx(SImode);
4249       emit_insn (gen_vec_extractv4si (avail, sp, GEN_INT (1)));
4250       emit_insn (gen_cgt_si(result, avail, GEN_INT (-1)));
4251       emit_insn (gen_spu_heq (result, GEN_INT(0) ));
4252     }
4253
4254   emit_insn (gen_spu_convert (stack_pointer_rtx, sp));
4255
4256   emit_move_insn (stack_bot, chain);
4257
4258   emit_move_insn (op0, virtual_stack_dynamic_rtx);
4259 }
4260
4261 void
4262 spu_restore_stack_nonlocal (rtx op0 ATTRIBUTE_UNUSED, rtx op1)
4263 {
4264   static unsigned char arr[16] =
4265     { 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3 };
4266   rtx temp = gen_reg_rtx (SImode);
4267   rtx temp2 = gen_reg_rtx (SImode);
4268   rtx temp3 = gen_reg_rtx (V4SImode);
4269   rtx temp4 = gen_reg_rtx (V4SImode);
4270   rtx pat = gen_reg_rtx (TImode);
4271   rtx sp = gen_rtx_REG (V4SImode, STACK_POINTER_REGNUM);
4272
4273   /* Restore the backchain from the first word, sp from the second.  */
4274   emit_move_insn (temp2, adjust_address_nv (op1, SImode, 0));
4275   emit_move_insn (temp, adjust_address_nv (op1, SImode, 4));
4276
4277   emit_move_insn (pat, array_to_constant (TImode, arr));
4278
4279   /* Compute Available Stack Size for sp */
4280   emit_insn (gen_subsi3 (temp, temp, stack_pointer_rtx));
4281   emit_insn (gen_shufb (temp3, temp, temp, pat));
4282
4283   /* Compute Available Stack Size for back chain */
4284   emit_insn (gen_subsi3 (temp2, temp2, stack_pointer_rtx));
4285   emit_insn (gen_shufb (temp4, temp2, temp2, pat));
4286   emit_insn (gen_addv4si3 (temp4, sp, temp4));
4287
4288   emit_insn (gen_addv4si3 (sp, sp, temp3));
4289   emit_move_insn (gen_frame_mem (V4SImode, stack_pointer_rtx), temp4);
4290 }
4291
4292 static void
4293 spu_init_libfuncs (void)
4294 {
4295   set_optab_libfunc (smul_optab, DImode, "__muldi3");
4296   set_optab_libfunc (sdiv_optab, DImode, "__divdi3");
4297   set_optab_libfunc (smod_optab, DImode, "__moddi3");
4298   set_optab_libfunc (udiv_optab, DImode, "__udivdi3");
4299   set_optab_libfunc (umod_optab, DImode, "__umoddi3");
4300   set_optab_libfunc (udivmod_optab, DImode, "__udivmoddi4");
4301   set_optab_libfunc (ffs_optab, DImode, "__ffsdi2");
4302   set_optab_libfunc (clz_optab, DImode, "__clzdi2");
4303   set_optab_libfunc (ctz_optab, DImode, "__ctzdi2");
4304   set_optab_libfunc (popcount_optab, DImode, "__popcountdi2");
4305   set_optab_libfunc (parity_optab, DImode, "__paritydi2");
4306
4307   set_conv_libfunc (ufloat_optab, DFmode, SImode, "__float_unssidf");
4308   set_conv_libfunc (ufloat_optab, DFmode, DImode, "__float_unsdidf");
4309 }
4310
4311 /* Make a subreg, stripping any existing subreg.  We could possibly just
4312    call simplify_subreg, but in this case we know what we want. */
4313 rtx
4314 spu_gen_subreg (enum machine_mode mode, rtx x)
4315 {
4316   if (GET_CODE (x) == SUBREG)
4317     x = SUBREG_REG (x);
4318   if (GET_MODE (x) == mode)
4319     return x;
4320   return gen_rtx_SUBREG (mode, x, 0);
4321 }
4322
4323 static bool
4324 spu_return_in_memory (tree type, tree fntype ATTRIBUTE_UNUSED)
4325 {
4326   return (TYPE_MODE (type) == BLKmode
4327           && ((type) == 0
4328               || TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST
4329               || int_size_in_bytes (type) >
4330               (MAX_REGISTER_RETURN * UNITS_PER_WORD)));
4331 }
4332 \f
4333 /* Create the built-in types and functions */
4334
4335 struct spu_builtin_description spu_builtins[] = {
4336 #define DEF_BUILTIN(fcode, icode, name, type, params) \
4337   {fcode, icode, name, type, params, NULL_TREE},
4338 #include "spu-builtins.def"
4339 #undef DEF_BUILTIN
4340 };
4341
4342 static void
4343 spu_init_builtins (void)
4344 {
4345   struct spu_builtin_description *d;
4346   unsigned int i;
4347
4348   V16QI_type_node = build_vector_type (intQI_type_node, 16);
4349   V8HI_type_node = build_vector_type (intHI_type_node, 8);
4350   V4SI_type_node = build_vector_type (intSI_type_node, 4);
4351   V2DI_type_node = build_vector_type (intDI_type_node, 2);
4352   V4SF_type_node = build_vector_type (float_type_node, 4);
4353   V2DF_type_node = build_vector_type (double_type_node, 2);
4354
4355   unsigned_V16QI_type_node = build_vector_type (unsigned_intQI_type_node, 16);
4356   unsigned_V8HI_type_node = build_vector_type (unsigned_intHI_type_node, 8);
4357   unsigned_V4SI_type_node = build_vector_type (unsigned_intSI_type_node, 4);
4358   unsigned_V2DI_type_node = build_vector_type (unsigned_intDI_type_node, 2);
4359
4360   spu_builtin_types[SPU_BTI_QUADWORD] = V16QI_type_node;
4361
4362   spu_builtin_types[SPU_BTI_7] = global_trees[TI_INTSI_TYPE];
4363   spu_builtin_types[SPU_BTI_S7] = global_trees[TI_INTSI_TYPE];
4364   spu_builtin_types[SPU_BTI_U7] = global_trees[TI_INTSI_TYPE];
4365   spu_builtin_types[SPU_BTI_S10] = global_trees[TI_INTSI_TYPE];
4366   spu_builtin_types[SPU_BTI_S10_4] = global_trees[TI_INTSI_TYPE];
4367   spu_builtin_types[SPU_BTI_U14] = global_trees[TI_INTSI_TYPE];
4368   spu_builtin_types[SPU_BTI_16] = global_trees[TI_INTSI_TYPE];
4369   spu_builtin_types[SPU_BTI_S16] = global_trees[TI_INTSI_TYPE];
4370   spu_builtin_types[SPU_BTI_S16_2] = global_trees[TI_INTSI_TYPE];
4371   spu_builtin_types[SPU_BTI_U16] = global_trees[TI_INTSI_TYPE];
4372   spu_builtin_types[SPU_BTI_U16_2] = global_trees[TI_INTSI_TYPE];
4373   spu_builtin_types[SPU_BTI_U18] = global_trees[TI_INTSI_TYPE];
4374
4375   spu_builtin_types[SPU_BTI_INTQI] = global_trees[TI_INTQI_TYPE];
4376   spu_builtin_types[SPU_BTI_INTHI] = global_trees[TI_INTHI_TYPE];
4377   spu_builtin_types[SPU_BTI_INTSI] = global_trees[TI_INTSI_TYPE];
4378   spu_builtin_types[SPU_BTI_INTDI] = global_trees[TI_INTDI_TYPE];
4379   spu_builtin_types[SPU_BTI_UINTQI] = global_trees[TI_UINTQI_TYPE];
4380   spu_builtin_types[SPU_BTI_UINTHI] = global_trees[TI_UINTHI_TYPE];
4381   spu_builtin_types[SPU_BTI_UINTSI] = global_trees[TI_UINTSI_TYPE];
4382   spu_builtin_types[SPU_BTI_UINTDI] = global_trees[TI_UINTDI_TYPE];
4383
4384   spu_builtin_types[SPU_BTI_FLOAT] = global_trees[TI_FLOAT_TYPE];
4385   spu_builtin_types[SPU_BTI_DOUBLE] = global_trees[TI_DOUBLE_TYPE];
4386
4387   spu_builtin_types[SPU_BTI_VOID] = global_trees[TI_VOID_TYPE];
4388
4389   spu_builtin_types[SPU_BTI_PTR] =
4390     build_pointer_type (build_qualified_type
4391                         (void_type_node,
4392                          TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE));
4393
4394   /* For each builtin we build a new prototype.  The tree code will make
4395      sure nodes are shared. */
4396   for (i = 0, d = spu_builtins; i < NUM_SPU_BUILTINS; i++, d++)
4397     {
4398       tree p;
4399       char name[64];            /* build_function will make a copy. */
4400       int parm;
4401
4402       if (d->name == 0)
4403         continue;
4404
4405       /* find last parm */
4406       for (parm = 1; d->parm[parm] != SPU_BTI_END_OF_PARAMS; parm++)
4407         {
4408         }
4409
4410       p = void_list_node;
4411       while (parm > 1)
4412         p = tree_cons (NULL_TREE, spu_builtin_types[d->parm[--parm]], p);
4413
4414       p = build_function_type (spu_builtin_types[d->parm[0]], p);
4415
4416       sprintf (name, "__builtin_%s", d->name);
4417       d->fndecl =
4418         add_builtin_function (name, p, END_BUILTINS + i, BUILT_IN_MD,
4419                               NULL, NULL_TREE);
4420       if (d->fcode == SPU_MASK_FOR_LOAD)
4421         TREE_READONLY (d->fndecl) = 1;  
4422     }
4423 }
4424
4425 void
4426 spu_restore_stack_block (rtx op0 ATTRIBUTE_UNUSED, rtx op1)
4427 {
4428   static unsigned char arr[16] =
4429     { 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3 };
4430
4431   rtx temp = gen_reg_rtx (Pmode);
4432   rtx temp2 = gen_reg_rtx (V4SImode);
4433   rtx temp3 = gen_reg_rtx (V4SImode);
4434   rtx pat = gen_reg_rtx (TImode);
4435   rtx sp = gen_rtx_REG (V4SImode, STACK_POINTER_REGNUM);
4436
4437   emit_move_insn (pat, array_to_constant (TImode, arr));
4438
4439   /* Restore the sp.  */
4440   emit_move_insn (temp, op1);
4441   emit_move_insn (temp2, gen_frame_mem (V4SImode, stack_pointer_rtx));
4442
4443   /* Compute available stack size for sp.  */
4444   emit_insn (gen_subsi3 (temp, temp, stack_pointer_rtx));
4445   emit_insn (gen_shufb (temp3, temp, temp, pat));
4446
4447   emit_insn (gen_addv4si3 (sp, sp, temp3));
4448   emit_move_insn (gen_frame_mem (V4SImode, stack_pointer_rtx), temp2);
4449 }
4450
4451 int
4452 spu_safe_dma (HOST_WIDE_INT channel)
4453 {
4454   return (channel >= 21 && channel <= 27);
4455 }
4456
4457 void
4458 spu_builtin_splats (rtx ops[])
4459 {
4460   enum machine_mode mode = GET_MODE (ops[0]);
4461   if (GET_CODE (ops[1]) == CONST_INT || GET_CODE (ops[1]) == CONST_DOUBLE)
4462     {
4463       unsigned char arr[16];
4464       constant_to_array (GET_MODE_INNER (mode), ops[1], arr);
4465       emit_move_insn (ops[0], array_to_constant (mode, arr));
4466     }
4467   else if (!flag_pic && GET_MODE (ops[0]) == V4SImode && CONSTANT_P (ops[1]))
4468     {
4469       rtvec v = rtvec_alloc (4);
4470       RTVEC_ELT (v, 0) = ops[1];
4471       RTVEC_ELT (v, 1) = ops[1];
4472       RTVEC_ELT (v, 2) = ops[1];
4473       RTVEC_ELT (v, 3) = ops[1];
4474       emit_move_insn (ops[0], gen_rtx_CONST_VECTOR (mode, v));
4475     }
4476   else
4477     {
4478       rtx reg = gen_reg_rtx (TImode);
4479       rtx shuf;
4480       if (GET_CODE (ops[1]) != REG
4481           && GET_CODE (ops[1]) != SUBREG)
4482         ops[1] = force_reg (GET_MODE_INNER (mode), ops[1]);
4483       switch (mode)
4484         {
4485         case V2DImode:
4486         case V2DFmode:
4487           shuf =
4488             immed_double_const (0x0001020304050607ll, 0x1011121314151617ll,
4489                                 TImode);
4490           break;
4491         case V4SImode:
4492         case V4SFmode:
4493           shuf =
4494             immed_double_const (0x0001020300010203ll, 0x0001020300010203ll,
4495                                 TImode);
4496           break;
4497         case V8HImode:
4498           shuf =
4499             immed_double_const (0x0203020302030203ll, 0x0203020302030203ll,
4500                                 TImode);
4501           break;
4502         case V16QImode:
4503           shuf =
4504             immed_double_const (0x0303030303030303ll, 0x0303030303030303ll,
4505                                 TImode);
4506           break;
4507         default:
4508           abort ();
4509         }
4510       emit_move_insn (reg, shuf);
4511       emit_insn (gen_shufb (ops[0], ops[1], ops[1], reg));
4512     }
4513 }
4514
4515 void
4516 spu_builtin_extract (rtx ops[])
4517 {
4518   enum machine_mode mode;
4519   rtx rot, from, tmp;
4520
4521   mode = GET_MODE (ops[1]);
4522
4523   if (GET_CODE (ops[2]) == CONST_INT)
4524     {
4525       switch (mode)
4526         {
4527         case V16QImode:
4528           emit_insn (gen_vec_extractv16qi (ops[0], ops[1], ops[2]));
4529           break;
4530         case V8HImode:
4531           emit_insn (gen_vec_extractv8hi (ops[0], ops[1], ops[2]));
4532           break;
4533         case V4SFmode:
4534           emit_insn (gen_vec_extractv4sf (ops[0], ops[1], ops[2]));
4535           break;
4536         case V4SImode:
4537           emit_insn (gen_vec_extractv4si (ops[0], ops[1], ops[2]));
4538           break;
4539         case V2DImode:
4540           emit_insn (gen_vec_extractv2di (ops[0], ops[1], ops[2]));
4541           break;
4542         case V2DFmode:
4543           emit_insn (gen_vec_extractv2df (ops[0], ops[1], ops[2]));
4544           break;
4545         default:
4546           abort ();
4547         }
4548       return;
4549     }
4550
4551   from = spu_gen_subreg (TImode, ops[1]);
4552   rot = gen_reg_rtx (TImode);
4553   tmp = gen_reg_rtx (SImode);
4554
4555   switch (mode)
4556     {
4557     case V16QImode:
4558       emit_insn (gen_addsi3 (tmp, ops[2], GEN_INT (-3)));
4559       break;
4560     case V8HImode:
4561       emit_insn (gen_addsi3 (tmp, ops[2], ops[2]));
4562       emit_insn (gen_addsi3 (tmp, tmp, GEN_INT (-2)));
4563       break;
4564     case V4SFmode:
4565     case V4SImode:
4566       emit_insn (gen_ashlsi3 (tmp, ops[2], GEN_INT (2)));
4567       break;
4568     case V2DImode:
4569     case V2DFmode:
4570       emit_insn (gen_ashlsi3 (tmp, ops[2], GEN_INT (3)));
4571       break;
4572     default:
4573       abort ();
4574     }
4575   emit_insn (gen_rotqby_ti (rot, from, tmp));
4576
4577   emit_insn (gen_spu_convert (ops[0], rot));
4578 }
4579
4580 void
4581 spu_builtin_insert (rtx ops[])
4582 {
4583   enum machine_mode mode = GET_MODE (ops[0]);
4584   enum machine_mode imode = GET_MODE_INNER (mode);
4585   rtx mask = gen_reg_rtx (TImode);
4586   rtx offset;
4587
4588   if (GET_CODE (ops[3]) == CONST_INT)
4589     offset = GEN_INT (INTVAL (ops[3]) * GET_MODE_SIZE (imode));
4590   else
4591     {
4592       offset = gen_reg_rtx (SImode);
4593       emit_insn (gen_mulsi3
4594                  (offset, ops[3], GEN_INT (GET_MODE_SIZE (imode))));
4595     }
4596   emit_insn (gen_cpat
4597              (mask, stack_pointer_rtx, offset,
4598               GEN_INT (GET_MODE_SIZE (imode))));
4599   emit_insn (gen_shufb (ops[0], ops[1], ops[2], mask));
4600 }
4601
4602 void
4603 spu_builtin_promote (rtx ops[])
4604 {
4605   enum machine_mode mode, imode;
4606   rtx rot, from, offset;
4607   HOST_WIDE_INT pos;
4608
4609   mode = GET_MODE (ops[0]);
4610   imode = GET_MODE_INNER (mode);
4611
4612   from = gen_reg_rtx (TImode);
4613   rot = spu_gen_subreg (TImode, ops[0]);
4614
4615   emit_insn (gen_spu_convert (from, ops[1]));
4616
4617   if (GET_CODE (ops[2]) == CONST_INT)
4618     {
4619       pos = -GET_MODE_SIZE (imode) * INTVAL (ops[2]);
4620       if (GET_MODE_SIZE (imode) < 4)
4621         pos += 4 - GET_MODE_SIZE (imode);
4622       offset = GEN_INT (pos & 15);
4623     }
4624   else
4625     {
4626       offset = gen_reg_rtx (SImode);
4627       switch (mode)
4628         {
4629         case V16QImode:
4630           emit_insn (gen_subsi3 (offset, GEN_INT (3), ops[2]));
4631           break;
4632         case V8HImode:
4633           emit_insn (gen_subsi3 (offset, GEN_INT (1), ops[2]));
4634           emit_insn (gen_addsi3 (offset, offset, offset));
4635           break;
4636         case V4SFmode:
4637         case V4SImode:
4638           emit_insn (gen_subsi3 (offset, GEN_INT (0), ops[2]));
4639           emit_insn (gen_ashlsi3 (offset, offset, GEN_INT (2)));
4640           break;
4641         case V2DImode:
4642         case V2DFmode:
4643           emit_insn (gen_ashlsi3 (offset, ops[2], GEN_INT (3)));
4644           break;
4645         default:
4646           abort ();
4647         }
4648     }
4649   emit_insn (gen_rotqby_ti (rot, from, offset));
4650 }
4651
4652 void
4653 spu_initialize_trampoline (rtx tramp, rtx fnaddr, rtx cxt)
4654 {
4655   rtx shuf = gen_reg_rtx (V4SImode);
4656   rtx insn = gen_reg_rtx (V4SImode);
4657   rtx shufc;
4658   rtx insnc;
4659   rtx mem;
4660
4661   fnaddr = force_reg (SImode, fnaddr);
4662   cxt = force_reg (SImode, cxt);
4663
4664   if (TARGET_LARGE_MEM)
4665     {
4666       rtx rotl = gen_reg_rtx (V4SImode);
4667       rtx mask = gen_reg_rtx (V4SImode);
4668       rtx bi = gen_reg_rtx (SImode);
4669       unsigned char shufa[16] = {
4670         2, 3, 0, 1, 18, 19, 16, 17,
4671         0, 1, 2, 3, 16, 17, 18, 19
4672       };
4673       unsigned char insna[16] = {
4674         0x41, 0, 0, 79,
4675         0x41, 0, 0, STATIC_CHAIN_REGNUM,
4676         0x60, 0x80, 0, 79,
4677         0x60, 0x80, 0, STATIC_CHAIN_REGNUM
4678       };
4679
4680       shufc = force_reg (TImode, array_to_constant (TImode, shufa));
4681       insnc = force_reg (V4SImode, array_to_constant (V4SImode, insna));
4682
4683       emit_insn (gen_shufb (shuf, fnaddr, cxt, shufc));
4684       emit_insn (gen_rotlv4si3 (rotl, shuf, spu_const (V4SImode, 7)));
4685       emit_insn (gen_movv4si (mask, spu_const (V4SImode, 0xffff << 7)));
4686       emit_insn (gen_selb (insn, insnc, rotl, mask));
4687
4688       mem = memory_address (Pmode, tramp);
4689       emit_move_insn (gen_rtx_MEM (V4SImode, mem), insn);
4690
4691       emit_move_insn (bi, GEN_INT (0x35000000 + (79 << 7)));
4692       mem = memory_address (Pmode, plus_constant (tramp, 16));
4693       emit_move_insn (gen_rtx_MEM (Pmode, mem), bi);
4694     }
4695   else
4696     {
4697       rtx scxt = gen_reg_rtx (SImode);
4698       rtx sfnaddr = gen_reg_rtx (SImode);
4699       unsigned char insna[16] = {
4700         0x42, 0, 0, STATIC_CHAIN_REGNUM,
4701         0x30, 0, 0, 0,
4702         0, 0, 0, 0,
4703         0, 0, 0, 0
4704       };
4705
4706       shufc = gen_reg_rtx (TImode);
4707       insnc = force_reg (V4SImode, array_to_constant (V4SImode, insna));
4708
4709       /* By or'ing all of cxt with the ila opcode we are assuming cxt
4710          fits 18 bits and the last 4 are zeros.  This will be true if
4711          the stack pointer is initialized to 0x3fff0 at program start,
4712          otherwise the ila instruction will be garbage. */
4713
4714       emit_insn (gen_ashlsi3 (scxt, cxt, GEN_INT (7)));
4715       emit_insn (gen_ashlsi3 (sfnaddr, fnaddr, GEN_INT (5)));
4716       emit_insn (gen_cpat
4717                  (shufc, stack_pointer_rtx, GEN_INT (4), GEN_INT (4)));
4718       emit_insn (gen_shufb (shuf, sfnaddr, scxt, shufc));
4719       emit_insn (gen_iorv4si3 (insn, insnc, shuf));
4720
4721       mem = memory_address (Pmode, tramp);
4722       emit_move_insn (gen_rtx_MEM (V4SImode, mem), insn);
4723
4724     }
4725   emit_insn (gen_sync ());
4726 }
4727
4728 void
4729 spu_expand_sign_extend (rtx ops[])
4730 {
4731   unsigned char arr[16];
4732   rtx pat = gen_reg_rtx (TImode);
4733   rtx sign, c;
4734   int i, last;
4735   last = GET_MODE (ops[0]) == DImode ? 7 : 15;
4736   if (GET_MODE (ops[1]) == QImode)
4737     {
4738       sign = gen_reg_rtx (HImode);
4739       emit_insn (gen_extendqihi2 (sign, ops[1]));
4740       for (i = 0; i < 16; i++)
4741         arr[i] = 0x12;
4742       arr[last] = 0x13;
4743     }
4744   else
4745     {
4746       for (i = 0; i < 16; i++)
4747         arr[i] = 0x10;
4748       switch (GET_MODE (ops[1]))
4749         {
4750         case HImode:
4751           sign = gen_reg_rtx (SImode);
4752           emit_insn (gen_extendhisi2 (sign, ops[1]));
4753           arr[last] = 0x03;
4754           arr[last - 1] = 0x02;
4755           break;
4756         case SImode:
4757           sign = gen_reg_rtx (SImode);
4758           emit_insn (gen_ashrsi3 (sign, ops[1], GEN_INT (31)));
4759           for (i = 0; i < 4; i++)
4760             arr[last - i] = 3 - i;
4761           break;
4762         case DImode:
4763           sign = gen_reg_rtx (SImode);
4764           c = gen_reg_rtx (SImode);
4765           emit_insn (gen_spu_convert (c, ops[1]));
4766           emit_insn (gen_ashrsi3 (sign, c, GEN_INT (31)));
4767           for (i = 0; i < 8; i++)
4768             arr[last - i] = 7 - i;
4769           break;
4770         default:
4771           abort ();
4772         }
4773     }
4774   emit_move_insn (pat, array_to_constant (TImode, arr));
4775   emit_insn (gen_shufb (ops[0], ops[1], sign, pat));
4776 }
4777
4778 /* expand vector initialization. If there are any constant parts,
4779    load constant parts first. Then load any non-constant parts.  */
4780 void
4781 spu_expand_vector_init (rtx target, rtx vals)
4782 {
4783   enum machine_mode mode = GET_MODE (target);
4784   int n_elts = GET_MODE_NUNITS (mode);
4785   int n_var = 0;
4786   bool all_same = true;
4787   rtx first, x = NULL_RTX, first_constant = NULL_RTX;
4788   int i;
4789
4790   first = XVECEXP (vals, 0, 0); 
4791   for (i = 0; i < n_elts; ++i)
4792     {
4793       x = XVECEXP (vals, 0, i);
4794       if (!CONSTANT_P (x))
4795         ++n_var;
4796       else
4797         {
4798           if (first_constant == NULL_RTX)
4799             first_constant = x;
4800         }
4801       if (i > 0 && !rtx_equal_p (x, first))
4802         all_same = false;
4803     }
4804
4805   /* if all elements are the same, use splats to repeat elements */
4806   if (all_same)
4807     {
4808       if (!CONSTANT_P (first)
4809           && !register_operand (first, GET_MODE (x)))
4810         first = force_reg (GET_MODE (first), first);
4811       emit_insn (gen_spu_splats (target, first));
4812       return;
4813     }
4814
4815   /* load constant parts */
4816   if (n_var != n_elts)
4817     {
4818       if (n_var == 0)
4819         {
4820           emit_move_insn (target,
4821                           gen_rtx_CONST_VECTOR (mode, XVEC (vals, 0)));
4822         }
4823       else
4824         {
4825           rtx constant_parts_rtx = copy_rtx (vals);
4826
4827           gcc_assert (first_constant != NULL_RTX);
4828           /* fill empty slots with the first constant, this increases
4829              our chance of using splats in the recursive call below. */
4830           for (i = 0; i < n_elts; ++i)
4831             if (!CONSTANT_P (XVECEXP (constant_parts_rtx, 0, i)))
4832               XVECEXP (constant_parts_rtx, 0, i) = first_constant;
4833
4834           spu_expand_vector_init (target, constant_parts_rtx);
4835         }
4836     }
4837
4838   /* load variable parts */
4839   if (n_var != 0)
4840     {
4841       rtx insert_operands[4];
4842
4843       insert_operands[0] = target;
4844       insert_operands[2] = target;
4845       for (i = 0; i < n_elts; ++i)
4846         {
4847           x = XVECEXP (vals, 0, i);
4848           if (!CONSTANT_P (x))
4849             {
4850               if (!register_operand (x, GET_MODE (x)))
4851                 x = force_reg (GET_MODE (x), x);
4852               insert_operands[1] = x;
4853               insert_operands[3] = GEN_INT (i);
4854               spu_builtin_insert (insert_operands);
4855             }
4856         }
4857     }
4858 }
4859
4860 static rtx
4861 spu_force_reg (enum machine_mode mode, rtx op)
4862 {
4863   rtx x, r;
4864   if (GET_MODE (op) == VOIDmode || GET_MODE (op) == BLKmode)
4865     {
4866       if ((SCALAR_INT_MODE_P (mode) && GET_CODE (op) == CONST_INT)
4867           || GET_MODE (op) == BLKmode)
4868         return force_reg (mode, convert_to_mode (mode, op, 0));
4869       abort ();
4870     }
4871
4872   r = force_reg (GET_MODE (op), op);
4873   if (GET_MODE_SIZE (GET_MODE (op)) == GET_MODE_SIZE (mode))
4874     {
4875       x = simplify_gen_subreg (mode, r, GET_MODE (op), 0);
4876       if (x)
4877         return x;
4878     }
4879
4880   x = gen_reg_rtx (mode);
4881   emit_insn (gen_spu_convert (x, r));
4882   return x;
4883 }
4884
4885 static void
4886 spu_check_builtin_parm (struct spu_builtin_description *d, rtx op, int p)
4887 {
4888   HOST_WIDE_INT v = 0;
4889   int lsbits;
4890   /* Check the range of immediate operands. */
4891   if (p >= SPU_BTI_7 && p <= SPU_BTI_U18)
4892     {
4893       int range = p - SPU_BTI_7;
4894
4895       if (!CONSTANT_P (op))
4896         error ("%s expects an integer literal in the range [%d, %d].",
4897                d->name,
4898                spu_builtin_range[range].low, spu_builtin_range[range].high);
4899
4900       if (GET_CODE (op) == CONST
4901           && (GET_CODE (XEXP (op, 0)) == PLUS
4902               || GET_CODE (XEXP (op, 0)) == MINUS))
4903         {
4904           v = INTVAL (XEXP (XEXP (op, 0), 1));
4905           op = XEXP (XEXP (op, 0), 0);
4906         }
4907       else if (GET_CODE (op) == CONST_INT)
4908         v = INTVAL (op);
4909       else if (GET_CODE (op) == CONST_VECTOR
4910                && GET_CODE (CONST_VECTOR_ELT (op, 0)) == CONST_INT)
4911         v = INTVAL (CONST_VECTOR_ELT (op, 0));
4912
4913       /* The default for v is 0 which is valid in every range. */
4914       if (v < spu_builtin_range[range].low
4915           || v > spu_builtin_range[range].high)
4916         error ("%s expects an integer literal in the range [%d, %d]. ("
4917                HOST_WIDE_INT_PRINT_DEC ")",
4918                d->name,
4919                spu_builtin_range[range].low, spu_builtin_range[range].high,
4920                v);
4921
4922       switch (p)
4923         {
4924         case SPU_BTI_S10_4:
4925           lsbits = 4;
4926           break;
4927         case SPU_BTI_U16_2:
4928           /* This is only used in lqa, and stqa.  Even though the insns
4929              encode 16 bits of the address (all but the 2 least
4930              significant), only 14 bits are used because it is masked to
4931              be 16 byte aligned. */
4932           lsbits = 4;
4933           break;
4934         case SPU_BTI_S16_2:
4935           /* This is used for lqr and stqr. */
4936           lsbits = 2;
4937           break;
4938         default:
4939           lsbits = 0;
4940         }
4941
4942       if (GET_CODE (op) == LABEL_REF
4943           || (GET_CODE (op) == SYMBOL_REF
4944               && SYMBOL_REF_FUNCTION_P (op))
4945           || (v & ((1 << lsbits) - 1)) != 0)
4946         warning (0, "%d least significant bits of %s are ignored.", lsbits,
4947                  d->name);
4948     }
4949 }
4950
4951
4952 static void
4953 expand_builtin_args (struct spu_builtin_description *d, tree exp,
4954                      rtx target, rtx ops[])
4955 {
4956   enum insn_code icode = d->icode;
4957   int i = 0, a;
4958
4959   /* Expand the arguments into rtl. */
4960
4961   if (d->parm[0] != SPU_BTI_VOID)
4962     ops[i++] = target;
4963
4964   for (a = 0; i < insn_data[icode].n_operands; i++, a++)
4965     {
4966       tree arg = CALL_EXPR_ARG (exp, a);
4967       if (arg == 0)
4968         abort ();
4969       ops[i] = expand_expr (arg, NULL_RTX, VOIDmode, 0);
4970     }
4971 }
4972
4973 static rtx
4974 spu_expand_builtin_1 (struct spu_builtin_description *d,
4975                       tree exp, rtx target)
4976 {
4977   rtx pat;
4978   rtx ops[8];
4979   enum insn_code icode = d->icode;
4980   enum machine_mode mode, tmode;
4981   int i, p;
4982   tree return_type;
4983
4984   /* Set up ops[] with values from arglist. */
4985   expand_builtin_args (d, exp, target, ops);
4986
4987   /* Handle the target operand which must be operand 0. */
4988   i = 0;
4989   if (d->parm[0] != SPU_BTI_VOID)
4990     {
4991
4992       /* We prefer the mode specified for the match_operand otherwise
4993          use the mode from the builtin function prototype. */
4994       tmode = insn_data[d->icode].operand[0].mode;
4995       if (tmode == VOIDmode)
4996         tmode = TYPE_MODE (spu_builtin_types[d->parm[0]]);
4997
4998       /* Try to use target because not using it can lead to extra copies
4999          and when we are using all of the registers extra copies leads
5000          to extra spills.  */
5001       if (target && GET_CODE (target) == REG && GET_MODE (target) == tmode)
5002         ops[0] = target;
5003       else
5004         target = ops[0] = gen_reg_rtx (tmode);
5005
5006       if (!(*insn_data[icode].operand[0].predicate) (ops[0], tmode))
5007         abort ();
5008
5009       i++;
5010     }
5011
5012   if (d->fcode == SPU_MASK_FOR_LOAD)
5013     {
5014       enum machine_mode mode = insn_data[icode].operand[1].mode;
5015       tree arg;
5016       rtx addr, op, pat;
5017
5018       /* get addr */
5019       arg = CALL_EXPR_ARG (exp, 0);
5020       gcc_assert (TREE_CODE (TREE_TYPE (arg)) == POINTER_TYPE);
5021       op = expand_expr (arg, NULL_RTX, Pmode, EXPAND_NORMAL);
5022       addr = memory_address (mode, op);
5023
5024       /* negate addr */
5025       op = gen_reg_rtx (GET_MODE (addr));
5026       emit_insn (gen_rtx_SET (VOIDmode, op,
5027                  gen_rtx_NEG (GET_MODE (addr), addr)));
5028       op = gen_rtx_MEM (mode, op);
5029
5030       pat = GEN_FCN (icode) (target, op);
5031       if (!pat) 
5032         return 0;
5033       emit_insn (pat);
5034       return target;
5035     }   
5036
5037   /* Ignore align_hint, but still expand it's args in case they have
5038      side effects. */
5039   if (icode == CODE_FOR_spu_align_hint)
5040     return 0;
5041
5042   /* Handle the rest of the operands. */
5043   for (p = 1; i < insn_data[icode].n_operands; i++, p++)
5044     {
5045       if (insn_data[d->icode].operand[i].mode != VOIDmode)
5046         mode = insn_data[d->icode].operand[i].mode;
5047       else
5048         mode = TYPE_MODE (spu_builtin_types[d->parm[i]]);
5049
5050       /* mode can be VOIDmode here for labels */
5051
5052       /* For specific intrinsics with an immediate operand, e.g.,
5053          si_ai(), we sometimes need to convert the scalar argument to a
5054          vector argument by splatting the scalar. */
5055       if (VECTOR_MODE_P (mode)
5056           && (GET_CODE (ops[i]) == CONST_INT
5057               || GET_MODE_CLASS (GET_MODE (ops[i])) == MODE_INT
5058               || GET_MODE_CLASS (GET_MODE (ops[i])) == MODE_FLOAT))
5059         {
5060           if (GET_CODE (ops[i]) == CONST_INT)
5061             ops[i] = spu_const (mode, INTVAL (ops[i]));
5062           else
5063             {
5064               rtx reg = gen_reg_rtx (mode);
5065               enum machine_mode imode = GET_MODE_INNER (mode);
5066               if (!spu_nonmem_operand (ops[i], GET_MODE (ops[i])))
5067                 ops[i] = force_reg (GET_MODE (ops[i]), ops[i]);
5068               if (imode != GET_MODE (ops[i]))
5069                 ops[i] = convert_to_mode (imode, ops[i],
5070                                           TYPE_UNSIGNED (spu_builtin_types
5071                                                          [d->parm[i]]));
5072               emit_insn (gen_spu_splats (reg, ops[i]));
5073               ops[i] = reg;
5074             }
5075         }
5076
5077       spu_check_builtin_parm (d, ops[i], d->parm[p]);
5078
5079       if (!(*insn_data[icode].operand[i].predicate) (ops[i], mode))
5080         ops[i] = spu_force_reg (mode, ops[i]);
5081     }
5082
5083   switch (insn_data[icode].n_operands)
5084     {
5085     case 0:
5086       pat = GEN_FCN (icode) (0);
5087       break;
5088     case 1:
5089       pat = GEN_FCN (icode) (ops[0]);
5090       break;
5091     case 2:
5092       pat = GEN_FCN (icode) (ops[0], ops[1]);
5093       break;
5094     case 3:
5095       pat = GEN_FCN (icode) (ops[0], ops[1], ops[2]);
5096       break;
5097     case 4:
5098       pat = GEN_FCN (icode) (ops[0], ops[1], ops[2], ops[3]);
5099       break;
5100     case 5:
5101       pat = GEN_FCN (icode) (ops[0], ops[1], ops[2], ops[3], ops[4]);
5102       break;
5103     case 6:
5104       pat = GEN_FCN (icode) (ops[0], ops[1], ops[2], ops[3], ops[4], ops[5]);
5105       break;
5106     default:
5107       abort ();
5108     }
5109
5110   if (!pat)
5111     abort ();
5112
5113   if (d->type == B_CALL || d->type == B_BISLED)
5114     emit_call_insn (pat);
5115   else if (d->type == B_JUMP)
5116     {
5117       emit_jump_insn (pat);
5118       emit_barrier ();
5119     }
5120   else
5121     emit_insn (pat);
5122
5123   return_type = spu_builtin_types[d->parm[0]];
5124   if (d->parm[0] != SPU_BTI_VOID
5125       && GET_MODE (target) != TYPE_MODE (return_type))
5126     {
5127       /* target is the return value.  It should always be the mode of
5128          the builtin function prototype. */
5129       target = spu_force_reg (TYPE_MODE (return_type), target);
5130     }
5131
5132   return target;
5133 }
5134
5135 rtx
5136 spu_expand_builtin (tree exp,
5137                     rtx target,
5138                     rtx subtarget ATTRIBUTE_UNUSED,
5139                     enum machine_mode mode ATTRIBUTE_UNUSED,
5140                     int ignore ATTRIBUTE_UNUSED)
5141 {
5142   tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
5143   unsigned int fcode = DECL_FUNCTION_CODE (fndecl) - END_BUILTINS;
5144   struct spu_builtin_description *d;
5145
5146   if (fcode < NUM_SPU_BUILTINS)
5147     {
5148       d = &spu_builtins[fcode];
5149
5150       return spu_expand_builtin_1 (d, exp, target);
5151     }
5152   abort ();
5153 }
5154
5155 /* Implement targetm.vectorize.builtin_mul_widen_even.  */
5156 static tree
5157 spu_builtin_mul_widen_even (tree type)
5158 {
5159   switch (TYPE_MODE (type))
5160     {
5161     case V8HImode:
5162       if (TYPE_UNSIGNED (type))
5163         return spu_builtins[SPU_MULE_0].fndecl;
5164       else
5165         return spu_builtins[SPU_MULE_1].fndecl;
5166       break;
5167     default:
5168       return NULL_TREE;
5169     }
5170 }
5171
5172 /* Implement targetm.vectorize.builtin_mul_widen_odd.  */
5173 static tree
5174 spu_builtin_mul_widen_odd (tree type)
5175 {
5176   switch (TYPE_MODE (type))
5177     {
5178     case V8HImode:
5179       if (TYPE_UNSIGNED (type))
5180         return spu_builtins[SPU_MULO_1].fndecl;
5181       else
5182         return spu_builtins[SPU_MULO_0].fndecl; 
5183       break;
5184     default:
5185       return NULL_TREE;
5186     }
5187 }
5188
5189 /* Implement targetm.vectorize.builtin_mask_for_load.  */
5190 static tree
5191 spu_builtin_mask_for_load (void)
5192 {
5193   struct spu_builtin_description *d = &spu_builtins[SPU_MASK_FOR_LOAD];
5194   gcc_assert (d);
5195   return d->fndecl;
5196 }
5197
5198 /* Implement targetm.vectorize.builtin_vectorization_cost.  */
5199 static int 
5200 spu_builtin_vectorization_cost (bool runtime_test)
5201 {
5202   /* If the branch of the runtime test is taken - i.e. - the vectorized
5203      version is skipped - this incurs a misprediction cost (because the
5204      vectorized version is expected to be the fall-through).  So we subtract
5205      the latency of a mispredicted branch from the costs that are incured
5206      when the vectorized version is executed.  */
5207   if (runtime_test)
5208     return -19;
5209   else
5210     return 0;
5211 }
5212
5213 void
5214 spu_init_expanders (void)
5215 {   
5216   /* HARD_FRAME_REGISTER is only 128 bit aligned when
5217    * frame_pointer_needed is true.  We don't know that until we're
5218    * expanding the prologue. */
5219   if (cfun)
5220     REGNO_POINTER_ALIGN (HARD_FRAME_POINTER_REGNUM) = 8;
5221 }