OSDN Git Service

bbe6eddde2a9ee8d35b162a6b629b7fe69f52b6b
[pf3gnuchains/gcc-fork.git] / gcc / config / spu / spu.c
1 /* Copyright (C) 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
2
3    This file is free software; you can redistribute it and/or modify it under
4    the terms of the GNU General Public License as published by the Free
5    Software Foundation; either version 3 of the License, or (at your option) 
6    any later version.
7
8    This file is distributed in the hope that it will be useful, but WITHOUT
9    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
11    for more details.
12
13    You should have received a copy of the GNU General Public License
14    along with GCC; see the file COPYING3.  If not see
15    <http://www.gnu.org/licenses/>.  */
16
17 #include "config.h"
18 #include "system.h"
19 #include "coretypes.h"
20 #include "tm.h"
21 #include "rtl.h"
22 #include "regs.h"
23 #include "hard-reg-set.h"
24 #include "insn-config.h"
25 #include "conditions.h"
26 #include "insn-attr.h"
27 #include "flags.h"
28 #include "recog.h"
29 #include "obstack.h"
30 #include "tree.h"
31 #include "expr.h"
32 #include "optabs.h"
33 #include "except.h"
34 #include "function.h"
35 #include "output.h"
36 #include "basic-block.h"
37 #include "integrate.h"
38 #include "diagnostic-core.h"
39 #include "ggc.h"
40 #include "hashtab.h"
41 #include "tm_p.h"
42 #include "target.h"
43 #include "target-def.h"
44 #include "langhooks.h"
45 #include "reload.h"
46 #include "cfglayout.h"
47 #include "sched-int.h"
48 #include "params.h"
49 #include "machmode.h"
50 #include "gimple.h"
51 #include "tm-constrs.h"
52 #include "ddg.h"
53 #include "sbitmap.h"
54 #include "timevar.h"
55 #include "df.h"
56
57 /* Builtin types, data and prototypes. */
58
59 enum spu_builtin_type_index
60 {
61   SPU_BTI_END_OF_PARAMS,
62
63   /* We create new type nodes for these. */
64   SPU_BTI_V16QI,
65   SPU_BTI_V8HI,
66   SPU_BTI_V4SI,
67   SPU_BTI_V2DI,
68   SPU_BTI_V4SF,
69   SPU_BTI_V2DF,
70   SPU_BTI_UV16QI,
71   SPU_BTI_UV8HI,
72   SPU_BTI_UV4SI,
73   SPU_BTI_UV2DI,
74
75   /* A 16-byte type. (Implemented with V16QI_type_node) */
76   SPU_BTI_QUADWORD,
77
78   /* These all correspond to intSI_type_node */
79   SPU_BTI_7,
80   SPU_BTI_S7,
81   SPU_BTI_U7,
82   SPU_BTI_S10,
83   SPU_BTI_S10_4,
84   SPU_BTI_U14,
85   SPU_BTI_16,
86   SPU_BTI_S16,
87   SPU_BTI_S16_2,
88   SPU_BTI_U16,
89   SPU_BTI_U16_2,
90   SPU_BTI_U18,
91
92   /* These correspond to the standard types */
93   SPU_BTI_INTQI, 
94   SPU_BTI_INTHI, 
95   SPU_BTI_INTSI, 
96   SPU_BTI_INTDI, 
97
98   SPU_BTI_UINTQI,
99   SPU_BTI_UINTHI,
100   SPU_BTI_UINTSI,
101   SPU_BTI_UINTDI,
102
103   SPU_BTI_FLOAT, 
104   SPU_BTI_DOUBLE,
105
106   SPU_BTI_VOID,   
107   SPU_BTI_PTR,   
108
109   SPU_BTI_MAX
110 };
111
112 #define V16QI_type_node               (spu_builtin_types[SPU_BTI_V16QI])
113 #define V8HI_type_node                (spu_builtin_types[SPU_BTI_V8HI])
114 #define V4SI_type_node                (spu_builtin_types[SPU_BTI_V4SI])
115 #define V2DI_type_node                (spu_builtin_types[SPU_BTI_V2DI])
116 #define V4SF_type_node                (spu_builtin_types[SPU_BTI_V4SF])
117 #define V2DF_type_node                (spu_builtin_types[SPU_BTI_V2DF])
118 #define unsigned_V16QI_type_node      (spu_builtin_types[SPU_BTI_UV16QI])
119 #define unsigned_V8HI_type_node       (spu_builtin_types[SPU_BTI_UV8HI])
120 #define unsigned_V4SI_type_node       (spu_builtin_types[SPU_BTI_UV4SI])
121 #define unsigned_V2DI_type_node       (spu_builtin_types[SPU_BTI_UV2DI])
122
123 static GTY(()) tree spu_builtin_types[SPU_BTI_MAX];
124
125 struct spu_builtin_range
126 {
127   int low, high;
128 };
129
130 static struct spu_builtin_range spu_builtin_range[] = {
131   {-0x40ll, 0x7fll},            /* SPU_BTI_7     */
132   {-0x40ll, 0x3fll},            /* SPU_BTI_S7    */
133   {0ll, 0x7fll},                /* SPU_BTI_U7    */
134   {-0x200ll, 0x1ffll},          /* SPU_BTI_S10   */
135   {-0x2000ll, 0x1fffll},        /* SPU_BTI_S10_4 */
136   {0ll, 0x3fffll},              /* SPU_BTI_U14   */
137   {-0x8000ll, 0xffffll},        /* SPU_BTI_16    */
138   {-0x8000ll, 0x7fffll},        /* SPU_BTI_S16   */
139   {-0x20000ll, 0x1ffffll},      /* SPU_BTI_S16_2 */
140   {0ll, 0xffffll},              /* SPU_BTI_U16   */
141   {0ll, 0x3ffffll},             /* SPU_BTI_U16_2 */
142   {0ll, 0x3ffffll},             /* SPU_BTI_U18   */
143 };
144
145 \f
146 /*  Target specific attribute specifications.  */
147 char regs_ever_allocated[FIRST_PSEUDO_REGISTER];
148
149 /*  Prototypes and external defs.  */
150 static void spu_option_override (void);
151 static void spu_option_init_struct (struct gcc_options *opts);
152 static void spu_option_default_params (void);
153 static void spu_init_builtins (void);
154 static tree spu_builtin_decl (unsigned, bool);
155 static bool spu_scalar_mode_supported_p (enum machine_mode mode);
156 static bool spu_vector_mode_supported_p (enum machine_mode mode);
157 static bool spu_legitimate_address_p (enum machine_mode, rtx, bool);
158 static bool spu_addr_space_legitimate_address_p (enum machine_mode, rtx,
159                                                  bool, addr_space_t);
160 static rtx adjust_operand (rtx op, HOST_WIDE_INT * start);
161 static rtx get_pic_reg (void);
162 static int need_to_save_reg (int regno, int saving);
163 static rtx frame_emit_store (int regno, rtx addr, HOST_WIDE_INT offset);
164 static rtx frame_emit_load (int regno, rtx addr, HOST_WIDE_INT offset);
165 static rtx frame_emit_add_imm (rtx dst, rtx src, HOST_WIDE_INT imm,
166                                rtx scratch);
167 static void emit_nop_for_insn (rtx insn);
168 static bool insn_clobbers_hbr (rtx insn);
169 static void spu_emit_branch_hint (rtx before, rtx branch, rtx target,
170                                   int distance, sbitmap blocks);
171 static rtx spu_emit_vector_compare (enum rtx_code rcode, rtx op0, rtx op1,
172                                     enum machine_mode dmode);
173 static rtx get_branch_target (rtx branch);
174 static void spu_machine_dependent_reorg (void);
175 static int spu_sched_issue_rate (void);
176 static int spu_sched_variable_issue (FILE * dump, int verbose, rtx insn,
177                                      int can_issue_more);
178 static int get_pipe (rtx insn);
179 static int spu_sched_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost);
180 static void spu_sched_init_global (FILE *, int, int);
181 static void spu_sched_init (FILE *, int, int);
182 static int spu_sched_reorder (FILE *, int, rtx *, int *, int);
183 static tree spu_handle_fndecl_attribute (tree * node, tree name, tree args,
184                                          int flags,
185                                          bool *no_add_attrs);
186 static tree spu_handle_vector_attribute (tree * node, tree name, tree args,
187                                          int flags,
188                                          bool *no_add_attrs);
189 static int spu_naked_function_p (tree func);
190 static bool spu_pass_by_reference (CUMULATIVE_ARGS *cum, enum machine_mode mode,
191                                    const_tree type, bool named);
192 static rtx spu_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
193                              const_tree type, bool named);
194 static void spu_function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
195                                       const_tree type, bool named);
196 static tree spu_build_builtin_va_list (void);
197 static void spu_va_start (tree, rtx);
198 static tree spu_gimplify_va_arg_expr (tree valist, tree type,
199                                       gimple_seq * pre_p, gimple_seq * post_p);
200 static int store_with_one_insn_p (rtx mem);
201 static int mem_is_padded_component_ref (rtx x);
202 static int reg_aligned_for_addr (rtx x);
203 static bool spu_assemble_integer (rtx x, unsigned int size, int aligned_p);
204 static void spu_asm_globalize_label (FILE * file, const char *name);
205 static bool spu_rtx_costs (rtx x, int code, int outer_code,
206                            int *total, bool speed);
207 static bool spu_function_ok_for_sibcall (tree decl, tree exp);
208 static void spu_init_libfuncs (void);
209 static bool spu_return_in_memory (const_tree type, const_tree fntype);
210 static void fix_range (const char *);
211 static void spu_encode_section_info (tree, rtx, int);
212 static rtx spu_legitimize_address (rtx, rtx, enum machine_mode);
213 static rtx spu_addr_space_legitimize_address (rtx, rtx, enum machine_mode,
214                                               addr_space_t);
215 static tree spu_builtin_mul_widen_even (tree);
216 static tree spu_builtin_mul_widen_odd (tree);
217 static tree spu_builtin_mask_for_load (void);
218 static int spu_builtin_vectorization_cost (enum vect_cost_for_stmt, tree, int);
219 static bool spu_vector_alignment_reachable (const_tree, bool);
220 static tree spu_builtin_vec_perm (tree, tree *);
221 static enum machine_mode spu_addr_space_pointer_mode (addr_space_t);
222 static enum machine_mode spu_addr_space_address_mode (addr_space_t);
223 static bool spu_addr_space_subset_p (addr_space_t, addr_space_t);
224 static rtx spu_addr_space_convert (rtx, tree, tree);
225 static int spu_sms_res_mii (struct ddg *g);
226 static void asm_file_start (void);
227 static unsigned int spu_section_type_flags (tree, const char *, int);
228 static section *spu_select_section (tree, int, unsigned HOST_WIDE_INT);
229 static void spu_unique_section (tree, int);
230 static rtx spu_expand_load (rtx, rtx, rtx, int);
231 static void spu_trampoline_init (rtx, tree, rtx);
232 static void spu_conditional_register_usage (void);
233
234 /* Which instruction set architecture to use.  */
235 int spu_arch;
236 /* Which cpu are we tuning for.  */
237 int spu_tune;
238
239 /* The hardware requires 8 insns between a hint and the branch it
240    effects.  This variable describes how many rtl instructions the
241    compiler needs to see before inserting a hint, and then the compiler
242    will insert enough nops to make it at least 8 insns.  The default is
243    for the compiler to allow up to 2 nops be emitted.  The nops are
244    inserted in pairs, so we round down. */
245 int spu_hint_dist = (8*4) - (2*4);
246
247 /* Determines whether we run variable tracking in machine dependent
248    reorganization.  */
249 static int spu_flag_var_tracking;
250
251 enum spu_immediate {
252   SPU_NONE,
253   SPU_IL,
254   SPU_ILA,
255   SPU_ILH,
256   SPU_ILHU,
257   SPU_ORI,
258   SPU_ORHI,
259   SPU_ORBI,
260   SPU_IOHL
261 };
262 enum immediate_class
263 {
264   IC_POOL,                      /* constant pool */
265   IC_IL1,                       /* one il* instruction */
266   IC_IL2,                       /* both ilhu and iohl instructions */
267   IC_IL1s,                      /* one il* instruction */
268   IC_IL2s,                      /* both ilhu and iohl instructions */
269   IC_FSMBI,                     /* the fsmbi instruction */
270   IC_CPAT,                      /* one of the c*d instructions */
271   IC_FSMBI2                     /* fsmbi plus 1 other instruction */
272 };
273
274 static enum spu_immediate which_immediate_load (HOST_WIDE_INT val);
275 static enum spu_immediate which_logical_immediate (HOST_WIDE_INT val);
276 static int cpat_info(unsigned char *arr, int size, int *prun, int *pstart);
277 static enum immediate_class classify_immediate (rtx op,
278                                                 enum machine_mode mode);
279
280 static enum machine_mode spu_unwind_word_mode (void);
281
282 static enum machine_mode
283 spu_libgcc_cmp_return_mode (void);
284
285 static enum machine_mode
286 spu_libgcc_shift_count_mode (void);
287
288 /* Pointer mode for __ea references.  */
289 #define EAmode (spu_ea_model != 32 ? DImode : SImode)
290
291 \f
292 /*  Table of machine attributes.  */
293 static const struct attribute_spec spu_attribute_table[] =
294 {
295   /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
296   { "naked",          0, 0, true,  false, false, spu_handle_fndecl_attribute },
297   { "spu_vector",     0, 0, false, true,  false, spu_handle_vector_attribute },
298   { NULL,             0, 0, false, false, false, NULL }
299 };
300 \f
301 /*  TARGET overrides.  */
302
303 #undef TARGET_ADDR_SPACE_POINTER_MODE
304 #define TARGET_ADDR_SPACE_POINTER_MODE spu_addr_space_pointer_mode
305
306 #undef TARGET_ADDR_SPACE_ADDRESS_MODE
307 #define TARGET_ADDR_SPACE_ADDRESS_MODE spu_addr_space_address_mode
308
309 #undef TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P
310 #define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P \
311   spu_addr_space_legitimate_address_p
312
313 #undef TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS
314 #define TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS spu_addr_space_legitimize_address
315
316 #undef TARGET_ADDR_SPACE_SUBSET_P
317 #define TARGET_ADDR_SPACE_SUBSET_P spu_addr_space_subset_p
318
319 #undef TARGET_ADDR_SPACE_CONVERT
320 #define TARGET_ADDR_SPACE_CONVERT spu_addr_space_convert
321
322 #undef TARGET_INIT_BUILTINS
323 #define TARGET_INIT_BUILTINS spu_init_builtins
324 #undef TARGET_BUILTIN_DECL
325 #define TARGET_BUILTIN_DECL spu_builtin_decl
326
327 #undef TARGET_EXPAND_BUILTIN
328 #define TARGET_EXPAND_BUILTIN spu_expand_builtin
329
330 #undef TARGET_UNWIND_WORD_MODE
331 #define TARGET_UNWIND_WORD_MODE spu_unwind_word_mode
332
333 #undef TARGET_LEGITIMIZE_ADDRESS
334 #define TARGET_LEGITIMIZE_ADDRESS spu_legitimize_address
335
336 /* The current assembler doesn't like .4byte foo@ppu, so use the normal .long
337    and .quad for the debugger.  When it is known that the assembler is fixed,
338    these can be removed.  */
339 #undef TARGET_ASM_UNALIGNED_SI_OP
340 #define TARGET_ASM_UNALIGNED_SI_OP      "\t.long\t"
341
342 #undef TARGET_ASM_ALIGNED_DI_OP
343 #define TARGET_ASM_ALIGNED_DI_OP        "\t.quad\t"
344
345 /* The .8byte directive doesn't seem to work well for a 32 bit
346    architecture. */
347 #undef TARGET_ASM_UNALIGNED_DI_OP
348 #define TARGET_ASM_UNALIGNED_DI_OP NULL
349
350 #undef TARGET_RTX_COSTS
351 #define TARGET_RTX_COSTS spu_rtx_costs
352
353 #undef TARGET_ADDRESS_COST
354 #define TARGET_ADDRESS_COST hook_int_rtx_bool_0
355
356 #undef TARGET_SCHED_ISSUE_RATE
357 #define TARGET_SCHED_ISSUE_RATE spu_sched_issue_rate
358
359 #undef TARGET_SCHED_INIT_GLOBAL
360 #define TARGET_SCHED_INIT_GLOBAL spu_sched_init_global
361
362 #undef TARGET_SCHED_INIT
363 #define TARGET_SCHED_INIT spu_sched_init
364
365 #undef TARGET_SCHED_VARIABLE_ISSUE
366 #define TARGET_SCHED_VARIABLE_ISSUE spu_sched_variable_issue
367
368 #undef TARGET_SCHED_REORDER
369 #define TARGET_SCHED_REORDER spu_sched_reorder
370
371 #undef TARGET_SCHED_REORDER2
372 #define TARGET_SCHED_REORDER2 spu_sched_reorder
373
374 #undef TARGET_SCHED_ADJUST_COST
375 #define TARGET_SCHED_ADJUST_COST spu_sched_adjust_cost
376
377 #undef  TARGET_ATTRIBUTE_TABLE
378 #define TARGET_ATTRIBUTE_TABLE spu_attribute_table
379
380 #undef TARGET_ASM_INTEGER
381 #define TARGET_ASM_INTEGER spu_assemble_integer
382
383 #undef TARGET_SCALAR_MODE_SUPPORTED_P
384 #define TARGET_SCALAR_MODE_SUPPORTED_P  spu_scalar_mode_supported_p
385
386 #undef TARGET_VECTOR_MODE_SUPPORTED_P
387 #define TARGET_VECTOR_MODE_SUPPORTED_P  spu_vector_mode_supported_p
388
389 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
390 #define TARGET_FUNCTION_OK_FOR_SIBCALL spu_function_ok_for_sibcall
391
392 #undef TARGET_ASM_GLOBALIZE_LABEL
393 #define TARGET_ASM_GLOBALIZE_LABEL spu_asm_globalize_label
394
395 #undef TARGET_PASS_BY_REFERENCE
396 #define TARGET_PASS_BY_REFERENCE spu_pass_by_reference
397
398 #undef TARGET_FUNCTION_ARG
399 #define TARGET_FUNCTION_ARG spu_function_arg
400
401 #undef TARGET_FUNCTION_ARG_ADVANCE
402 #define TARGET_FUNCTION_ARG_ADVANCE spu_function_arg_advance
403
404 #undef TARGET_MUST_PASS_IN_STACK
405 #define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size
406
407 #undef TARGET_BUILD_BUILTIN_VA_LIST
408 #define TARGET_BUILD_BUILTIN_VA_LIST spu_build_builtin_va_list
409
410 #undef TARGET_EXPAND_BUILTIN_VA_START
411 #define TARGET_EXPAND_BUILTIN_VA_START spu_va_start
412
413 #undef TARGET_SETUP_INCOMING_VARARGS
414 #define TARGET_SETUP_INCOMING_VARARGS spu_setup_incoming_varargs
415
416 #undef TARGET_MACHINE_DEPENDENT_REORG
417 #define TARGET_MACHINE_DEPENDENT_REORG spu_machine_dependent_reorg
418
419 #undef TARGET_GIMPLIFY_VA_ARG_EXPR
420 #define TARGET_GIMPLIFY_VA_ARG_EXPR spu_gimplify_va_arg_expr
421
422 #undef TARGET_DEFAULT_TARGET_FLAGS
423 #define TARGET_DEFAULT_TARGET_FLAGS (TARGET_DEFAULT)
424
425 #undef TARGET_INIT_LIBFUNCS
426 #define TARGET_INIT_LIBFUNCS spu_init_libfuncs
427
428 #undef TARGET_RETURN_IN_MEMORY
429 #define TARGET_RETURN_IN_MEMORY spu_return_in_memory
430
431 #undef  TARGET_ENCODE_SECTION_INFO
432 #define TARGET_ENCODE_SECTION_INFO spu_encode_section_info
433
434 #undef TARGET_VECTORIZE_BUILTIN_MUL_WIDEN_EVEN
435 #define TARGET_VECTORIZE_BUILTIN_MUL_WIDEN_EVEN spu_builtin_mul_widen_even
436
437 #undef TARGET_VECTORIZE_BUILTIN_MUL_WIDEN_ODD
438 #define TARGET_VECTORIZE_BUILTIN_MUL_WIDEN_ODD spu_builtin_mul_widen_odd
439
440 #undef TARGET_VECTORIZE_BUILTIN_MASK_FOR_LOAD
441 #define TARGET_VECTORIZE_BUILTIN_MASK_FOR_LOAD spu_builtin_mask_for_load
442
443 #undef TARGET_VECTORIZE_BUILTIN_VECTORIZATION_COST
444 #define TARGET_VECTORIZE_BUILTIN_VECTORIZATION_COST spu_builtin_vectorization_cost
445
446 #undef TARGET_VECTORIZE_VECTOR_ALIGNMENT_REACHABLE
447 #define TARGET_VECTORIZE_VECTOR_ALIGNMENT_REACHABLE spu_vector_alignment_reachable
448
449 #undef TARGET_VECTORIZE_BUILTIN_VEC_PERM
450 #define TARGET_VECTORIZE_BUILTIN_VEC_PERM spu_builtin_vec_perm
451
452 #undef TARGET_LIBGCC_CMP_RETURN_MODE
453 #define TARGET_LIBGCC_CMP_RETURN_MODE spu_libgcc_cmp_return_mode
454
455 #undef TARGET_LIBGCC_SHIFT_COUNT_MODE
456 #define TARGET_LIBGCC_SHIFT_COUNT_MODE spu_libgcc_shift_count_mode
457
458 #undef TARGET_SCHED_SMS_RES_MII
459 #define TARGET_SCHED_SMS_RES_MII spu_sms_res_mii
460
461 #undef TARGET_ASM_FILE_START
462 #define TARGET_ASM_FILE_START asm_file_start
463
464 #undef TARGET_SECTION_TYPE_FLAGS
465 #define TARGET_SECTION_TYPE_FLAGS spu_section_type_flags
466
467 #undef TARGET_ASM_SELECT_SECTION
468 #define TARGET_ASM_SELECT_SECTION  spu_select_section
469
470 #undef TARGET_ASM_UNIQUE_SECTION
471 #define TARGET_ASM_UNIQUE_SECTION  spu_unique_section
472
473 #undef TARGET_LEGITIMATE_ADDRESS_P
474 #define TARGET_LEGITIMATE_ADDRESS_P spu_legitimate_address_p
475
476 #undef TARGET_TRAMPOLINE_INIT
477 #define TARGET_TRAMPOLINE_INIT spu_trampoline_init
478
479 #undef TARGET_OPTION_OVERRIDE
480 #define TARGET_OPTION_OVERRIDE spu_option_override
481
482 #undef TARGET_OPTION_INIT_STRUCT
483 #define TARGET_OPTION_INIT_STRUCT spu_option_init_struct
484
485 #undef TARGET_OPTION_DEFAULT_PARAMS
486 #define TARGET_OPTION_DEFAULT_PARAMS spu_option_default_params
487
488 #undef TARGET_EXCEPT_UNWIND_INFO
489 #define TARGET_EXCEPT_UNWIND_INFO  sjlj_except_unwind_info
490
491 #undef TARGET_CONDITIONAL_REGISTER_USAGE
492 #define TARGET_CONDITIONAL_REGISTER_USAGE spu_conditional_register_usage
493
494 struct gcc_target targetm = TARGET_INITIALIZER;
495
496 static void
497 spu_option_init_struct (struct gcc_options *opts)
498 {
499   /* With so many registers this is better on by default. */
500   opts->x_flag_rename_registers = 1;
501 }
502
503 /* Implement TARGET_OPTION_DEFAULT_PARAMS.  */
504 static void
505 spu_option_default_params (void)
506 {
507   /* Override some of the default param values.  With so many registers
508      larger values are better for these params.  */
509   set_default_param_value (PARAM_MAX_PENDING_LIST_LENGTH, 128);
510 }
511
512 /* Implement TARGET_OPTION_OVERRIDE.  */
513 static void
514 spu_option_override (void)
515 {
516   /* Small loops will be unpeeled at -O3.  For SPU it is more important
517      to keep code small by default.  */
518   if (!flag_unroll_loops && !flag_peel_loops)
519     maybe_set_param_value (PARAM_MAX_COMPLETELY_PEEL_TIMES, 1,
520                            global_options.x_param_values,
521                            global_options_set.x_param_values);
522
523   flag_omit_frame_pointer = 1;
524
525   /* Functions must be 8 byte aligned so we correctly handle dual issue */
526   if (align_functions < 8)
527     align_functions = 8;
528
529   spu_hint_dist = 8*4 - spu_max_nops*4;
530   if (spu_hint_dist < 0) 
531     spu_hint_dist = 0;
532
533   if (spu_fixed_range_string)
534     fix_range (spu_fixed_range_string);
535
536   /* Determine processor architectural level.  */
537   if (spu_arch_string)
538     {
539       if (strcmp (&spu_arch_string[0], "cell") == 0)
540         spu_arch = PROCESSOR_CELL;
541       else if (strcmp (&spu_arch_string[0], "celledp") == 0)
542         spu_arch = PROCESSOR_CELLEDP;
543       else
544         error ("unknown architecture %qs", &spu_arch_string[0]);
545     }
546
547   /* Determine processor to tune for.  */
548   if (spu_tune_string)
549     {
550       if (strcmp (&spu_tune_string[0], "cell") == 0)
551         spu_tune = PROCESSOR_CELL;
552       else if (strcmp (&spu_tune_string[0], "celledp") == 0)
553         spu_tune = PROCESSOR_CELLEDP;
554       else
555         error ("unknown architecture %qs", &spu_tune_string[0]);
556     }
557
558   /* Change defaults according to the processor architecture.  */
559   if (spu_arch == PROCESSOR_CELLEDP)
560     {
561       /* If no command line option has been otherwise specified, change
562          the default to -mno-safe-hints on celledp -- only the original
563          Cell/B.E. processors require this workaround.  */
564       if (!(target_flags_explicit & MASK_SAFE_HINTS))
565         target_flags &= ~MASK_SAFE_HINTS;
566     }
567
568   REAL_MODE_FORMAT (SFmode) = &spu_single_format;
569 }
570 \f
571 /* Handle an attribute requiring a FUNCTION_DECL; arguments as in
572    struct attribute_spec.handler.  */
573
574 /* True if MODE is valid for the target.  By "valid", we mean able to
575    be manipulated in non-trivial ways.  In particular, this means all
576    the arithmetic is supported.  */
577 static bool
578 spu_scalar_mode_supported_p (enum machine_mode mode)
579 {
580   switch (mode)
581     {
582     case QImode:
583     case HImode:
584     case SImode:
585     case SFmode:
586     case DImode:
587     case TImode:
588     case DFmode:
589       return true;
590
591     default:
592       return false;
593     }
594 }
595
596 /* Similarly for vector modes.  "Supported" here is less strict.  At
597    least some operations are supported; need to check optabs or builtins
598    for further details.  */
599 static bool
600 spu_vector_mode_supported_p (enum machine_mode mode)
601 {
602   switch (mode)
603     {
604     case V16QImode:
605     case V8HImode:
606     case V4SImode:
607     case V2DImode:
608     case V4SFmode:
609     case V2DFmode:
610       return true;
611
612     default:
613       return false;
614     }
615 }
616
617 /* GCC assumes that in a paradoxical SUBREG the inner mode occupies the
618    least significant bytes of the outer mode.  This function returns
619    TRUE for the SUBREG's where this is correct.  */
620 int
621 valid_subreg (rtx op)
622 {
623   enum machine_mode om = GET_MODE (op);
624   enum machine_mode im = GET_MODE (SUBREG_REG (op));
625   return om != VOIDmode && im != VOIDmode
626     && (GET_MODE_SIZE (im) == GET_MODE_SIZE (om)
627         || (GET_MODE_SIZE (im) <= 4 && GET_MODE_SIZE (om) <= 4)
628         || (GET_MODE_SIZE (im) >= 16 && GET_MODE_SIZE (om) >= 16));
629 }
630
631 /* When insv and ext[sz]v ar passed a TI SUBREG, we want to strip it off
632    and adjust the start offset.  */
633 static rtx
634 adjust_operand (rtx op, HOST_WIDE_INT * start)
635 {
636   enum machine_mode mode;
637   int op_size;
638   /* Strip any paradoxical SUBREG.  */
639   if (GET_CODE (op) == SUBREG
640       && (GET_MODE_BITSIZE (GET_MODE (op))
641           > GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (op)))))
642     {
643       if (start)
644         *start -=
645           GET_MODE_BITSIZE (GET_MODE (op)) -
646           GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (op)));
647       op = SUBREG_REG (op);
648     }
649   /* If it is smaller than SI, assure a SUBREG */
650   op_size = GET_MODE_BITSIZE (GET_MODE (op));
651   if (op_size < 32)
652     {
653       if (start)
654         *start += 32 - op_size;
655       op_size = 32;
656     }
657   /* If it is not a MODE_INT (and/or it is smaller than SI) add a SUBREG. */
658   mode = mode_for_size (op_size, MODE_INT, 0);
659   if (mode != GET_MODE (op))
660     op = gen_rtx_SUBREG (mode, op, 0);
661   return op;
662 }
663
664 void
665 spu_expand_extv (rtx ops[], int unsignedp)
666 {
667   rtx dst = ops[0], src = ops[1];
668   HOST_WIDE_INT width = INTVAL (ops[2]);
669   HOST_WIDE_INT start = INTVAL (ops[3]);
670   HOST_WIDE_INT align_mask;
671   rtx s0, s1, mask, r0;
672
673   gcc_assert (REG_P (dst) && GET_MODE (dst) == TImode);
674
675   if (MEM_P (src))
676     {
677       /* First, determine if we need 1 TImode load or 2.  We need only 1
678          if the bits being extracted do not cross the alignment boundary
679          as determined by the MEM and its address. */
680
681       align_mask = -MEM_ALIGN (src);
682       if ((start & align_mask) == ((start + width - 1) & align_mask))
683         {
684           /* Alignment is sufficient for 1 load. */
685           s0 = gen_reg_rtx (TImode);
686           r0 = spu_expand_load (s0, 0, src, start / 8);
687           start &= 7;
688           if (r0)
689             emit_insn (gen_rotqby_ti (s0, s0, r0));
690         }
691       else
692         {
693           /* Need 2 loads. */
694           s0 = gen_reg_rtx (TImode);
695           s1 = gen_reg_rtx (TImode);
696           r0 = spu_expand_load (s0, s1, src, start / 8);
697           start &= 7;
698
699           gcc_assert (start + width <= 128);
700           if (r0)
701             {
702               rtx r1 = gen_reg_rtx (SImode);
703               mask = gen_reg_rtx (TImode);
704               emit_move_insn (mask, GEN_INT (-1));
705               emit_insn (gen_rotqby_ti (s0, s0, r0));
706               emit_insn (gen_rotqby_ti (s1, s1, r0));
707               if (GET_CODE (r0) == CONST_INT)
708                 r1 = GEN_INT (INTVAL (r0) & 15);
709               else
710                 emit_insn (gen_andsi3 (r1, r0, GEN_INT (15)));
711               emit_insn (gen_shlqby_ti (mask, mask, r1));
712               emit_insn (gen_selb (s0, s1, s0, mask));
713             }
714         }
715
716     }
717   else if (GET_CODE (src) == SUBREG)
718     {
719       rtx r = SUBREG_REG (src);
720       gcc_assert (REG_P (r) && SCALAR_INT_MODE_P (GET_MODE (r)));
721       s0 = gen_reg_rtx (TImode);
722       if (GET_MODE_SIZE (GET_MODE (r)) < GET_MODE_SIZE (TImode))
723         emit_insn (gen_rtx_SET (VOIDmode, s0, gen_rtx_ZERO_EXTEND (TImode, r)));
724       else
725         emit_move_insn (s0, src);
726     }
727   else 
728     {
729       gcc_assert (REG_P (src) && GET_MODE (src) == TImode);
730       s0 = gen_reg_rtx (TImode);
731       emit_move_insn (s0, src);
732     }
733
734   /* Now s0 is TImode and contains the bits to extract at start. */
735
736   if (start)
737     emit_insn (gen_rotlti3 (s0, s0, GEN_INT (start)));
738
739   if (128 - width)
740     {
741       tree c = build_int_cst (NULL_TREE, 128 - width);
742       s0 = expand_shift (RSHIFT_EXPR, TImode, s0, c, s0, unsignedp);
743     }
744
745   emit_move_insn (dst, s0);
746 }
747
748 void
749 spu_expand_insv (rtx ops[])
750 {
751   HOST_WIDE_INT width = INTVAL (ops[1]);
752   HOST_WIDE_INT start = INTVAL (ops[2]);
753   HOST_WIDE_INT maskbits;
754   enum machine_mode dst_mode;
755   rtx dst = ops[0], src = ops[3];
756   int dst_size;
757   rtx mask;
758   rtx shift_reg;
759   int shift;
760
761
762   if (GET_CODE (ops[0]) == MEM)
763     dst = gen_reg_rtx (TImode);
764   else
765     dst = adjust_operand (dst, &start);
766   dst_mode = GET_MODE (dst);
767   dst_size = GET_MODE_BITSIZE (GET_MODE (dst));
768
769   if (CONSTANT_P (src))
770     {
771       enum machine_mode m =
772         (width <= 32 ? SImode : width <= 64 ? DImode : TImode);
773       src = force_reg (m, convert_to_mode (m, src, 0));
774     }
775   src = adjust_operand (src, 0);
776
777   mask = gen_reg_rtx (dst_mode);
778   shift_reg = gen_reg_rtx (dst_mode);
779   shift = dst_size - start - width;
780
781   /* It's not safe to use subreg here because the compiler assumes
782      that the SUBREG_REG is right justified in the SUBREG. */
783   convert_move (shift_reg, src, 1);
784
785   if (shift > 0)
786     {
787       switch (dst_mode)
788         {
789         case SImode:
790           emit_insn (gen_ashlsi3 (shift_reg, shift_reg, GEN_INT (shift)));
791           break;
792         case DImode:
793           emit_insn (gen_ashldi3 (shift_reg, shift_reg, GEN_INT (shift)));
794           break;
795         case TImode:
796           emit_insn (gen_ashlti3 (shift_reg, shift_reg, GEN_INT (shift)));
797           break;
798         default:
799           abort ();
800         }
801     }
802   else if (shift < 0)
803     abort ();
804
805   switch (dst_size)
806     {
807     case 32:
808       maskbits = (-1ll << (32 - width - start));
809       if (start)
810         maskbits += (1ll << (32 - start));
811       emit_move_insn (mask, GEN_INT (maskbits));
812       break;
813     case 64:
814       maskbits = (-1ll << (64 - width - start));
815       if (start)
816         maskbits += (1ll << (64 - start));
817       emit_move_insn (mask, GEN_INT (maskbits));
818       break;
819     case 128:
820       {
821         unsigned char arr[16];
822         int i = start / 8;
823         memset (arr, 0, sizeof (arr));
824         arr[i] = 0xff >> (start & 7);
825         for (i++; i <= (start + width - 1) / 8; i++)
826           arr[i] = 0xff;
827         arr[i - 1] &= 0xff << (7 - ((start + width - 1) & 7));
828         emit_move_insn (mask, array_to_constant (TImode, arr));
829       }
830       break;
831     default:
832       abort ();
833     }
834   if (GET_CODE (ops[0]) == MEM)
835     {
836       rtx low = gen_reg_rtx (SImode);
837       rtx rotl = gen_reg_rtx (SImode);
838       rtx mask0 = gen_reg_rtx (TImode);
839       rtx addr;
840       rtx addr0;
841       rtx addr1;
842       rtx mem;
843
844       addr = force_reg (Pmode, XEXP (ops[0], 0));
845       addr0 = gen_rtx_AND (Pmode, addr, GEN_INT (-16));
846       emit_insn (gen_andsi3 (low, addr, GEN_INT (15)));
847       emit_insn (gen_negsi2 (rotl, low));
848       emit_insn (gen_rotqby_ti (shift_reg, shift_reg, rotl));
849       emit_insn (gen_rotqmby_ti (mask0, mask, rotl));
850       mem = change_address (ops[0], TImode, addr0);
851       set_mem_alias_set (mem, 0);
852       emit_move_insn (dst, mem);
853       emit_insn (gen_selb (dst, dst, shift_reg, mask0));
854       if (start + width > MEM_ALIGN (ops[0]))
855         {
856           rtx shl = gen_reg_rtx (SImode);
857           rtx mask1 = gen_reg_rtx (TImode);
858           rtx dst1 = gen_reg_rtx (TImode);
859           rtx mem1;
860           addr1 = plus_constant (addr, 16);
861           addr1 = gen_rtx_AND (Pmode, addr1, GEN_INT (-16));
862           emit_insn (gen_subsi3 (shl, GEN_INT (16), low));
863           emit_insn (gen_shlqby_ti (mask1, mask, shl));
864           mem1 = change_address (ops[0], TImode, addr1);
865           set_mem_alias_set (mem1, 0);
866           emit_move_insn (dst1, mem1);
867           emit_insn (gen_selb (dst1, dst1, shift_reg, mask1));
868           emit_move_insn (mem1, dst1);
869         }
870       emit_move_insn (mem, dst);
871     }
872   else
873     emit_insn (gen_selb (dst, copy_rtx (dst), shift_reg, mask));
874 }
875
876
877 int
878 spu_expand_block_move (rtx ops[])
879 {
880   HOST_WIDE_INT bytes, align, offset;
881   rtx src, dst, sreg, dreg, target;
882   int i;
883   if (GET_CODE (ops[2]) != CONST_INT
884       || GET_CODE (ops[3]) != CONST_INT
885       || INTVAL (ops[2]) > (HOST_WIDE_INT) (MOVE_RATIO (optimize_insn_for_speed_p ()) * 8))
886     return 0;
887
888   bytes = INTVAL (ops[2]);
889   align = INTVAL (ops[3]);
890
891   if (bytes <= 0)
892     return 1;
893
894   dst = ops[0];
895   src = ops[1];
896
897   if (align == 16)
898     {
899       for (offset = 0; offset + 16 <= bytes; offset += 16)
900         {
901           dst = adjust_address (ops[0], V16QImode, offset);
902           src = adjust_address (ops[1], V16QImode, offset);
903           emit_move_insn (dst, src);
904         }
905       if (offset < bytes)
906         {
907           rtx mask;
908           unsigned char arr[16] = { 0 };
909           for (i = 0; i < bytes - offset; i++)
910             arr[i] = 0xff;
911           dst = adjust_address (ops[0], V16QImode, offset);
912           src = adjust_address (ops[1], V16QImode, offset);
913           mask = gen_reg_rtx (V16QImode);
914           sreg = gen_reg_rtx (V16QImode);
915           dreg = gen_reg_rtx (V16QImode);
916           target = gen_reg_rtx (V16QImode);
917           emit_move_insn (mask, array_to_constant (V16QImode, arr));
918           emit_move_insn (dreg, dst);
919           emit_move_insn (sreg, src);
920           emit_insn (gen_selb (target, dreg, sreg, mask));
921           emit_move_insn (dst, target);
922         }
923       return 1;
924     }
925   return 0;
926 }
927
928 enum spu_comp_code
929 { SPU_EQ, SPU_GT, SPU_GTU };
930
931 int spu_comp_icode[12][3] = {
932  {CODE_FOR_ceq_qi, CODE_FOR_cgt_qi, CODE_FOR_clgt_qi},
933  {CODE_FOR_ceq_hi, CODE_FOR_cgt_hi, CODE_FOR_clgt_hi},
934  {CODE_FOR_ceq_si, CODE_FOR_cgt_si, CODE_FOR_clgt_si},
935  {CODE_FOR_ceq_di, CODE_FOR_cgt_di, CODE_FOR_clgt_di},
936  {CODE_FOR_ceq_ti, CODE_FOR_cgt_ti, CODE_FOR_clgt_ti},
937  {CODE_FOR_ceq_sf, CODE_FOR_cgt_sf, 0},
938  {CODE_FOR_ceq_df, CODE_FOR_cgt_df, 0},
939  {CODE_FOR_ceq_v16qi, CODE_FOR_cgt_v16qi, CODE_FOR_clgt_v16qi},
940  {CODE_FOR_ceq_v8hi,  CODE_FOR_cgt_v8hi,  CODE_FOR_clgt_v8hi},
941  {CODE_FOR_ceq_v4si,  CODE_FOR_cgt_v4si,  CODE_FOR_clgt_v4si},
942  {CODE_FOR_ceq_v4sf,  CODE_FOR_cgt_v4sf, 0},
943  {CODE_FOR_ceq_v2df,  CODE_FOR_cgt_v2df, 0},
944 };
945
946 /* Generate a compare for CODE.  Return a brand-new rtx that represents
947    the result of the compare.   GCC can figure this out too if we don't
948    provide all variations of compares, but GCC always wants to use
949    WORD_MODE, we can generate better code in most cases if we do it
950    ourselves.  */
951 void
952 spu_emit_branch_or_set (int is_set, rtx cmp, rtx operands[])
953 {
954   int reverse_compare = 0;
955   int reverse_test = 0;
956   rtx compare_result, eq_result;
957   rtx comp_rtx, eq_rtx;
958   enum machine_mode comp_mode;
959   enum machine_mode op_mode;
960   enum spu_comp_code scode, eq_code;
961   enum insn_code ior_code;
962   enum rtx_code code = GET_CODE (cmp);
963   rtx op0 = XEXP (cmp, 0);
964   rtx op1 = XEXP (cmp, 1);
965   int index;
966   int eq_test = 0;
967
968   /* When op1 is a CONST_INT change (X >= C) to (X > C-1),
969      and so on, to keep the constant in operand 1. */
970   if (GET_CODE (op1) == CONST_INT)
971     {
972       HOST_WIDE_INT val = INTVAL (op1) - 1;
973       if (trunc_int_for_mode (val, GET_MODE (op0)) == val)
974         switch (code)
975           {
976           case GE:
977             op1 = GEN_INT (val);
978             code = GT;
979             break;
980           case LT:
981             op1 = GEN_INT (val);
982             code = LE;
983             break;
984           case GEU:
985             op1 = GEN_INT (val);
986             code = GTU;
987             break;
988           case LTU:
989             op1 = GEN_INT (val);
990             code = LEU;
991             break;
992           default:
993             break;
994           }
995     }
996
997   comp_mode = SImode;
998   op_mode = GET_MODE (op0);
999
1000   switch (code)
1001     {
1002     case GE:
1003       scode = SPU_GT;
1004       if (HONOR_NANS (op_mode))
1005         {
1006           reverse_compare = 0;
1007           reverse_test = 0;
1008           eq_test = 1;
1009           eq_code = SPU_EQ;
1010         }
1011       else
1012         {
1013           reverse_compare = 1;
1014           reverse_test = 1;
1015         }
1016       break;
1017     case LE:
1018       scode = SPU_GT;
1019       if (HONOR_NANS (op_mode))
1020         {
1021           reverse_compare = 1;
1022           reverse_test = 0;
1023           eq_test = 1;
1024           eq_code = SPU_EQ;
1025         }
1026       else
1027         {
1028           reverse_compare = 0;
1029           reverse_test = 1;
1030         }
1031       break;
1032     case LT:
1033       reverse_compare = 1;
1034       reverse_test = 0;
1035       scode = SPU_GT;
1036       break;
1037     case GEU:
1038       reverse_compare = 1;
1039       reverse_test = 1;
1040       scode = SPU_GTU;
1041       break;
1042     case LEU:
1043       reverse_compare = 0;
1044       reverse_test = 1;
1045       scode = SPU_GTU;
1046       break;
1047     case LTU:
1048       reverse_compare = 1;
1049       reverse_test = 0;
1050       scode = SPU_GTU;
1051       break;
1052     case NE:
1053       reverse_compare = 0;
1054       reverse_test = 1;
1055       scode = SPU_EQ;
1056       break;
1057
1058     case EQ:
1059       scode = SPU_EQ;
1060       break;
1061     case GT:
1062       scode = SPU_GT;
1063       break;
1064     case GTU:
1065       scode = SPU_GTU;
1066       break;
1067     default:
1068       scode = SPU_EQ;
1069       break;
1070     }
1071
1072   switch (op_mode)
1073     {
1074     case QImode:
1075       index = 0;
1076       comp_mode = QImode;
1077       break;
1078     case HImode:
1079       index = 1;
1080       comp_mode = HImode;
1081       break;
1082     case SImode:
1083       index = 2;
1084       break;
1085     case DImode:
1086       index = 3;
1087       break;
1088     case TImode:
1089       index = 4;
1090       break;
1091     case SFmode:
1092       index = 5;
1093       break;
1094     case DFmode:
1095       index = 6;
1096       break;
1097     case V16QImode:
1098       index = 7;
1099       comp_mode = op_mode;
1100       break;
1101     case V8HImode:
1102       index = 8;
1103       comp_mode = op_mode;
1104       break;
1105     case V4SImode:
1106       index = 9;
1107       comp_mode = op_mode;
1108       break;
1109     case V4SFmode:
1110       index = 10;
1111       comp_mode = V4SImode;
1112       break;
1113     case V2DFmode:
1114       index = 11;
1115       comp_mode = V2DImode;
1116       break;
1117     case V2DImode:
1118     default:
1119       abort ();
1120     }
1121
1122   if (GET_MODE (op1) == DFmode
1123       && (scode != SPU_GT && scode != SPU_EQ))
1124     abort ();
1125
1126   if (is_set == 0 && op1 == const0_rtx
1127       && (GET_MODE (op0) == SImode
1128           || GET_MODE (op0) == HImode) && scode == SPU_EQ)
1129     {
1130       /* Don't need to set a register with the result when we are 
1131          comparing against zero and branching. */
1132       reverse_test = !reverse_test;
1133       compare_result = op0;
1134     }
1135   else
1136     {
1137       compare_result = gen_reg_rtx (comp_mode);
1138
1139       if (reverse_compare)
1140         {
1141           rtx t = op1;
1142           op1 = op0;
1143           op0 = t;
1144         }
1145
1146       if (spu_comp_icode[index][scode] == 0)
1147         abort ();
1148
1149       if (!(*insn_data[spu_comp_icode[index][scode]].operand[1].predicate)
1150           (op0, op_mode))
1151         op0 = force_reg (op_mode, op0);
1152       if (!(*insn_data[spu_comp_icode[index][scode]].operand[2].predicate)
1153           (op1, op_mode))
1154         op1 = force_reg (op_mode, op1);
1155       comp_rtx = GEN_FCN (spu_comp_icode[index][scode]) (compare_result,
1156                                                          op0, op1);
1157       if (comp_rtx == 0)
1158         abort ();
1159       emit_insn (comp_rtx);
1160
1161       if (eq_test)
1162         {
1163           eq_result = gen_reg_rtx (comp_mode);
1164           eq_rtx = GEN_FCN (spu_comp_icode[index][eq_code]) (eq_result,
1165                                                              op0, op1);
1166           if (eq_rtx == 0)
1167             abort ();
1168           emit_insn (eq_rtx);
1169           ior_code = optab_handler (ior_optab, comp_mode);
1170           gcc_assert (ior_code != CODE_FOR_nothing);
1171           emit_insn (GEN_FCN (ior_code)
1172                      (compare_result, compare_result, eq_result));
1173         }
1174     }
1175
1176   if (is_set == 0)
1177     {
1178       rtx bcomp;
1179       rtx loc_ref;
1180
1181       /* We don't have branch on QI compare insns, so we convert the
1182          QI compare result to a HI result. */
1183       if (comp_mode == QImode)
1184         {
1185           rtx old_res = compare_result;
1186           compare_result = gen_reg_rtx (HImode);
1187           comp_mode = HImode;
1188           emit_insn (gen_extendqihi2 (compare_result, old_res));
1189         }
1190
1191       if (reverse_test)
1192         bcomp = gen_rtx_EQ (comp_mode, compare_result, const0_rtx);
1193       else
1194         bcomp = gen_rtx_NE (comp_mode, compare_result, const0_rtx);
1195
1196       loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands[3]);
1197       emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx,
1198                                    gen_rtx_IF_THEN_ELSE (VOIDmode, bcomp,
1199                                                          loc_ref, pc_rtx)));
1200     }
1201   else if (is_set == 2)
1202     {
1203       rtx target = operands[0];
1204       int compare_size = GET_MODE_BITSIZE (comp_mode);
1205       int target_size = GET_MODE_BITSIZE (GET_MODE (target));
1206       enum machine_mode mode = mode_for_size (target_size, MODE_INT, 0);
1207       rtx select_mask;
1208       rtx op_t = operands[2];
1209       rtx op_f = operands[3];
1210
1211       /* The result of the comparison can be SI, HI or QI mode.  Create a
1212          mask based on that result. */
1213       if (target_size > compare_size)
1214         {
1215           select_mask = gen_reg_rtx (mode);
1216           emit_insn (gen_extend_compare (select_mask, compare_result));
1217         }
1218       else if (target_size < compare_size)
1219         select_mask =
1220           gen_rtx_SUBREG (mode, compare_result,
1221                           (compare_size - target_size) / BITS_PER_UNIT);
1222       else if (comp_mode != mode)
1223         select_mask = gen_rtx_SUBREG (mode, compare_result, 0);
1224       else
1225         select_mask = compare_result;
1226
1227       if (GET_MODE (target) != GET_MODE (op_t)
1228           || GET_MODE (target) != GET_MODE (op_f))
1229         abort ();
1230
1231       if (reverse_test)
1232         emit_insn (gen_selb (target, op_t, op_f, select_mask));
1233       else
1234         emit_insn (gen_selb (target, op_f, op_t, select_mask));
1235     }
1236   else
1237     {
1238       rtx target = operands[0];
1239       if (reverse_test)
1240         emit_insn (gen_rtx_SET (VOIDmode, compare_result,
1241                                 gen_rtx_NOT (comp_mode, compare_result)));
1242       if (GET_MODE (target) == SImode && GET_MODE (compare_result) == HImode)
1243         emit_insn (gen_extendhisi2 (target, compare_result));
1244       else if (GET_MODE (target) == SImode
1245                && GET_MODE (compare_result) == QImode)
1246         emit_insn (gen_extend_compare (target, compare_result));
1247       else
1248         emit_move_insn (target, compare_result);
1249     }
1250 }
1251
1252 HOST_WIDE_INT
1253 const_double_to_hwint (rtx x)
1254 {
1255   HOST_WIDE_INT val;
1256   REAL_VALUE_TYPE rv;
1257   if (GET_MODE (x) == SFmode)
1258     {
1259       REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
1260       REAL_VALUE_TO_TARGET_SINGLE (rv, val);
1261     }
1262   else if (GET_MODE (x) == DFmode)
1263     {
1264       long l[2];
1265       REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
1266       REAL_VALUE_TO_TARGET_DOUBLE (rv, l);
1267       val = l[0];
1268       val = (val << 32) | (l[1] & 0xffffffff);
1269     }
1270   else
1271     abort ();
1272   return val;
1273 }
1274
1275 rtx
1276 hwint_to_const_double (enum machine_mode mode, HOST_WIDE_INT v)
1277 {
1278   long tv[2];
1279   REAL_VALUE_TYPE rv;
1280   gcc_assert (mode == SFmode || mode == DFmode);
1281
1282   if (mode == SFmode)
1283     tv[0] = (v << 32) >> 32;
1284   else if (mode == DFmode)
1285     {
1286       tv[1] = (v << 32) >> 32;
1287       tv[0] = v >> 32;
1288     }
1289   real_from_target (&rv, tv, mode);
1290   return CONST_DOUBLE_FROM_REAL_VALUE (rv, mode);
1291 }
1292
1293 void
1294 print_operand_address (FILE * file, register rtx addr)
1295 {
1296   rtx reg;
1297   rtx offset;
1298
1299   if (GET_CODE (addr) == AND
1300       && GET_CODE (XEXP (addr, 1)) == CONST_INT
1301       && INTVAL (XEXP (addr, 1)) == -16)
1302     addr = XEXP (addr, 0);
1303
1304   switch (GET_CODE (addr))
1305     {
1306     case REG:
1307       fprintf (file, "0(%s)", reg_names[REGNO (addr)]);
1308       break;
1309
1310     case PLUS:
1311       reg = XEXP (addr, 0);
1312       offset = XEXP (addr, 1);
1313       if (GET_CODE (offset) == REG)
1314         {
1315           fprintf (file, "%s,%s", reg_names[REGNO (reg)],
1316                    reg_names[REGNO (offset)]);
1317         }
1318       else if (GET_CODE (offset) == CONST_INT)
1319         {
1320           fprintf (file, HOST_WIDE_INT_PRINT_DEC "(%s)",
1321                    INTVAL (offset), reg_names[REGNO (reg)]);
1322         }
1323       else
1324         abort ();
1325       break;
1326
1327     case CONST:
1328     case LABEL_REF:
1329     case SYMBOL_REF:
1330     case CONST_INT:
1331       output_addr_const (file, addr);
1332       break;
1333
1334     default:
1335       debug_rtx (addr);
1336       abort ();
1337     }
1338 }
1339
1340 void
1341 print_operand (FILE * file, rtx x, int code)
1342 {
1343   enum machine_mode mode = GET_MODE (x);
1344   HOST_WIDE_INT val;
1345   unsigned char arr[16];
1346   int xcode = GET_CODE (x);
1347   int i, info;
1348   if (GET_MODE (x) == VOIDmode)
1349     switch (code)
1350       {
1351       case 'L':                 /* 128 bits, signed */
1352       case 'm':                 /* 128 bits, signed */
1353       case 'T':                 /* 128 bits, signed */
1354       case 't':                 /* 128 bits, signed */
1355         mode = TImode;
1356         break;
1357       case 'K':                 /* 64 bits, signed */
1358       case 'k':                 /* 64 bits, signed */
1359       case 'D':                 /* 64 bits, signed */
1360       case 'd':                 /* 64 bits, signed */
1361         mode = DImode;
1362         break;
1363       case 'J':                 /* 32 bits, signed */
1364       case 'j':                 /* 32 bits, signed */
1365       case 's':                 /* 32 bits, signed */
1366       case 'S':                 /* 32 bits, signed */
1367         mode = SImode;
1368         break;
1369       }
1370   switch (code)
1371     {
1372
1373     case 'j':                   /* 32 bits, signed */
1374     case 'k':                   /* 64 bits, signed */
1375     case 'm':                   /* 128 bits, signed */
1376       if (xcode == CONST_INT
1377           || xcode == CONST_DOUBLE || xcode == CONST_VECTOR)
1378         {
1379           gcc_assert (logical_immediate_p (x, mode));
1380           constant_to_array (mode, x, arr);
1381           val = (arr[0] << 24) | (arr[1] << 16) | (arr[2] << 8) | arr[3];
1382           val = trunc_int_for_mode (val, SImode);
1383           switch (which_logical_immediate (val))
1384           {
1385           case SPU_ORI:
1386             break;
1387           case SPU_ORHI:
1388             fprintf (file, "h");
1389             break;
1390           case SPU_ORBI:
1391             fprintf (file, "b");
1392             break;
1393           default:
1394             gcc_unreachable();
1395           }
1396         }
1397       else
1398         gcc_unreachable();
1399       return;
1400
1401     case 'J':                   /* 32 bits, signed */
1402     case 'K':                   /* 64 bits, signed */
1403     case 'L':                   /* 128 bits, signed */
1404       if (xcode == CONST_INT
1405           || xcode == CONST_DOUBLE || xcode == CONST_VECTOR)
1406         {
1407           gcc_assert (logical_immediate_p (x, mode)
1408                       || iohl_immediate_p (x, mode));
1409           constant_to_array (mode, x, arr);
1410           val = (arr[0] << 24) | (arr[1] << 16) | (arr[2] << 8) | arr[3];
1411           val = trunc_int_for_mode (val, SImode);
1412           switch (which_logical_immediate (val))
1413           {
1414           case SPU_ORI:
1415           case SPU_IOHL:
1416             break;
1417           case SPU_ORHI:
1418             val = trunc_int_for_mode (val, HImode);
1419             break;
1420           case SPU_ORBI:
1421             val = trunc_int_for_mode (val, QImode);
1422             break;
1423           default:
1424             gcc_unreachable();
1425           }
1426           fprintf (file, HOST_WIDE_INT_PRINT_DEC, val);
1427         }
1428       else
1429         gcc_unreachable();
1430       return;
1431
1432     case 't':                   /* 128 bits, signed */
1433     case 'd':                   /* 64 bits, signed */
1434     case 's':                   /* 32 bits, signed */
1435       if (CONSTANT_P (x))
1436         {
1437           enum immediate_class c = classify_immediate (x, mode);
1438           switch (c)
1439             {
1440             case IC_IL1:
1441               constant_to_array (mode, x, arr);
1442               val = (arr[0] << 24) | (arr[1] << 16) | (arr[2] << 8) | arr[3];
1443               val = trunc_int_for_mode (val, SImode);
1444               switch (which_immediate_load (val))
1445                 {
1446                 case SPU_IL:
1447                   break;
1448                 case SPU_ILA:
1449                   fprintf (file, "a");
1450                   break;
1451                 case SPU_ILH:
1452                   fprintf (file, "h");
1453                   break;
1454                 case SPU_ILHU:
1455                   fprintf (file, "hu");
1456                   break;
1457                 default:
1458                   gcc_unreachable ();
1459                 }
1460               break;
1461             case IC_CPAT:
1462               constant_to_array (mode, x, arr);
1463               cpat_info (arr, GET_MODE_SIZE (mode), &info, 0);
1464               if (info == 1)
1465                 fprintf (file, "b");
1466               else if (info == 2)
1467                 fprintf (file, "h");
1468               else if (info == 4)
1469                 fprintf (file, "w");
1470               else if (info == 8)
1471                 fprintf (file, "d");
1472               break;
1473             case IC_IL1s:
1474               if (xcode == CONST_VECTOR)
1475                 {
1476                   x = CONST_VECTOR_ELT (x, 0);
1477                   xcode = GET_CODE (x);
1478                 }
1479               if (xcode == SYMBOL_REF || xcode == LABEL_REF || xcode == CONST)
1480                 fprintf (file, "a");
1481               else if (xcode == HIGH)
1482                 fprintf (file, "hu");
1483               break;
1484             case IC_FSMBI:
1485             case IC_FSMBI2:
1486             case IC_IL2:
1487             case IC_IL2s:
1488             case IC_POOL:
1489               abort ();
1490             }
1491         }
1492       else
1493         gcc_unreachable ();
1494       return;
1495
1496     case 'T':                   /* 128 bits, signed */
1497     case 'D':                   /* 64 bits, signed */
1498     case 'S':                   /* 32 bits, signed */
1499       if (CONSTANT_P (x))
1500         {
1501           enum immediate_class c = classify_immediate (x, mode);
1502           switch (c)
1503             {
1504             case IC_IL1:
1505               constant_to_array (mode, x, arr);
1506               val = (arr[0] << 24) | (arr[1] << 16) | (arr[2] << 8) | arr[3];
1507               val = trunc_int_for_mode (val, SImode);
1508               switch (which_immediate_load (val))
1509                 {
1510                 case SPU_IL:
1511                 case SPU_ILA:
1512                   break;
1513                 case SPU_ILH:
1514                 case SPU_ILHU:
1515                   val = trunc_int_for_mode (((arr[0] << 8) | arr[1]), HImode);
1516                   break;
1517                 default:
1518                   gcc_unreachable ();
1519                 }
1520               fprintf (file, HOST_WIDE_INT_PRINT_DEC, val);
1521               break;
1522             case IC_FSMBI:
1523               constant_to_array (mode, x, arr);
1524               val = 0;
1525               for (i = 0; i < 16; i++)
1526                 {
1527                   val <<= 1;
1528                   val |= arr[i] & 1;
1529                 }
1530               print_operand (file, GEN_INT (val), 0);
1531               break;
1532             case IC_CPAT:
1533               constant_to_array (mode, x, arr);
1534               cpat_info (arr, GET_MODE_SIZE (mode), 0, &info);
1535               fprintf (file, HOST_WIDE_INT_PRINT_DEC, (HOST_WIDE_INT)info);
1536               break;
1537             case IC_IL1s:
1538               if (xcode == HIGH)
1539                 x = XEXP (x, 0);
1540               if (GET_CODE (x) == CONST_VECTOR)
1541                 x = CONST_VECTOR_ELT (x, 0);
1542               output_addr_const (file, x);
1543               if (xcode == HIGH)
1544                 fprintf (file, "@h");
1545               break;
1546             case IC_IL2:
1547             case IC_IL2s:
1548             case IC_FSMBI2:
1549             case IC_POOL:
1550               abort ();
1551             }
1552         }
1553       else
1554         gcc_unreachable ();
1555       return;
1556
1557     case 'C':
1558       if (xcode == CONST_INT)
1559         {
1560           /* Only 4 least significant bits are relevant for generate
1561              control word instructions. */
1562           fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x) & 15);
1563           return;
1564         }
1565       break;
1566
1567     case 'M':                   /* print code for c*d */
1568       if (GET_CODE (x) == CONST_INT)
1569         switch (INTVAL (x))
1570           {
1571           case 1:
1572             fprintf (file, "b");
1573             break;
1574           case 2:
1575             fprintf (file, "h");
1576             break;
1577           case 4:
1578             fprintf (file, "w");
1579             break;
1580           case 8:
1581             fprintf (file, "d");
1582             break;
1583           default:
1584             gcc_unreachable();
1585           }
1586       else
1587         gcc_unreachable();
1588       return;
1589
1590     case 'N':                   /* Negate the operand */
1591       if (xcode == CONST_INT)
1592         fprintf (file, HOST_WIDE_INT_PRINT_DEC, -INTVAL (x));
1593       else if (xcode == CONST_VECTOR)
1594         fprintf (file, HOST_WIDE_INT_PRINT_DEC,
1595                  -INTVAL (CONST_VECTOR_ELT (x, 0)));
1596       return;
1597
1598     case 'I':                   /* enable/disable interrupts */
1599       if (xcode == CONST_INT)
1600         fprintf (file, "%s",  INTVAL (x) == 0 ? "d" : "e");
1601       return;
1602
1603     case 'b':                   /* branch modifiers */
1604       if (xcode == REG)
1605         fprintf (file, "%s", GET_MODE (x) == HImode ? "h" : "");
1606       else if (COMPARISON_P (x))
1607         fprintf (file, "%s", xcode == NE ? "n" : "");
1608       return;
1609
1610     case 'i':                   /* indirect call */
1611       if (xcode == MEM)
1612         {
1613           if (GET_CODE (XEXP (x, 0)) == REG)
1614             /* Used in indirect function calls. */
1615             fprintf (file, "%s", reg_names[REGNO (XEXP (x, 0))]);
1616           else
1617             output_address (XEXP (x, 0));
1618         }
1619       return;
1620
1621     case 'p':                   /* load/store */
1622       if (xcode == MEM)
1623         {
1624           x = XEXP (x, 0);
1625           xcode = GET_CODE (x);
1626         }
1627       if (xcode == AND)
1628         {
1629           x = XEXP (x, 0);
1630           xcode = GET_CODE (x);
1631         }
1632       if (xcode == REG)
1633         fprintf (file, "d");
1634       else if (xcode == CONST_INT)
1635         fprintf (file, "a");
1636       else if (xcode == CONST || xcode == SYMBOL_REF || xcode == LABEL_REF)
1637         fprintf (file, "r");
1638       else if (xcode == PLUS || xcode == LO_SUM)
1639         {
1640           if (GET_CODE (XEXP (x, 1)) == REG)
1641             fprintf (file, "x");
1642           else
1643             fprintf (file, "d");
1644         }
1645       return;
1646
1647     case 'e':
1648       val = xcode == CONST_INT ? INTVAL (x) : INTVAL (CONST_VECTOR_ELT (x, 0));
1649       val &= 0x7;
1650       output_addr_const (file, GEN_INT (val));
1651       return;
1652
1653     case 'f':
1654       val = xcode == CONST_INT ? INTVAL (x) : INTVAL (CONST_VECTOR_ELT (x, 0));
1655       val &= 0x1f;
1656       output_addr_const (file, GEN_INT (val));
1657       return;
1658
1659     case 'g':
1660       val = xcode == CONST_INT ? INTVAL (x) : INTVAL (CONST_VECTOR_ELT (x, 0));
1661       val &= 0x3f;
1662       output_addr_const (file, GEN_INT (val));
1663       return;
1664
1665     case 'h':
1666       val = xcode == CONST_INT ? INTVAL (x) : INTVAL (CONST_VECTOR_ELT (x, 0));
1667       val = (val >> 3) & 0x1f;
1668       output_addr_const (file, GEN_INT (val));
1669       return;
1670
1671     case 'E':
1672       val = xcode == CONST_INT ? INTVAL (x) : INTVAL (CONST_VECTOR_ELT (x, 0));
1673       val = -val;
1674       val &= 0x7;
1675       output_addr_const (file, GEN_INT (val));
1676       return;
1677
1678     case 'F':
1679       val = xcode == CONST_INT ? INTVAL (x) : INTVAL (CONST_VECTOR_ELT (x, 0));
1680       val = -val;
1681       val &= 0x1f;
1682       output_addr_const (file, GEN_INT (val));
1683       return;
1684
1685     case 'G':
1686       val = xcode == CONST_INT ? INTVAL (x) : INTVAL (CONST_VECTOR_ELT (x, 0));
1687       val = -val;
1688       val &= 0x3f;
1689       output_addr_const (file, GEN_INT (val));
1690       return;
1691
1692     case 'H':
1693       val = xcode == CONST_INT ? INTVAL (x) : INTVAL (CONST_VECTOR_ELT (x, 0));
1694       val = -(val & -8ll);
1695       val = (val >> 3) & 0x1f;
1696       output_addr_const (file, GEN_INT (val));
1697       return;
1698
1699     case 'v':
1700     case 'w':
1701       constant_to_array (mode, x, arr);
1702       val = (((arr[0] << 1) + (arr[1] >> 7)) & 0xff) - 127;
1703       output_addr_const (file, GEN_INT (code == 'w' ? -val : val));
1704       return;
1705
1706     case 0:
1707       if (xcode == REG)
1708         fprintf (file, "%s", reg_names[REGNO (x)]);
1709       else if (xcode == MEM)
1710         output_address (XEXP (x, 0));
1711       else if (xcode == CONST_VECTOR)
1712         print_operand (file, CONST_VECTOR_ELT (x, 0), 0);
1713       else
1714         output_addr_const (file, x);
1715       return;
1716
1717       /* unused letters
1718                       o qr  u   yz
1719         AB            OPQR  UVWXYZ */
1720     default:
1721       output_operand_lossage ("invalid %%xn code");
1722     }
1723   gcc_unreachable ();
1724 }
1725
1726 /* For PIC mode we've reserved PIC_OFFSET_TABLE_REGNUM, which is a
1727    caller saved register.  For leaf functions it is more efficient to
1728    use a volatile register because we won't need to save and restore the
1729    pic register.  This routine is only valid after register allocation
1730    is completed, so we can pick an unused register.  */
1731 static rtx
1732 get_pic_reg (void)
1733 {
1734   rtx pic_reg = pic_offset_table_rtx;
1735   if (!reload_completed && !reload_in_progress)
1736     abort ();
1737   if (current_function_is_leaf && !df_regs_ever_live_p (LAST_ARG_REGNUM))
1738     pic_reg = gen_rtx_REG (SImode, LAST_ARG_REGNUM);
1739   return pic_reg;
1740 }
1741
1742 /* Split constant addresses to handle cases that are too large. 
1743    Add in the pic register when in PIC mode.
1744    Split immediates that require more than 1 instruction. */
1745 int
1746 spu_split_immediate (rtx * ops)
1747 {
1748   enum machine_mode mode = GET_MODE (ops[0]);
1749   enum immediate_class c = classify_immediate (ops[1], mode);
1750
1751   switch (c)
1752     {
1753     case IC_IL2:
1754       {
1755         unsigned char arrhi[16];
1756         unsigned char arrlo[16];
1757         rtx to, temp, hi, lo;
1758         int i;
1759         enum machine_mode imode = mode;
1760         /* We need to do reals as ints because the constant used in the
1761            IOR might not be a legitimate real constant. */
1762         imode = int_mode_for_mode (mode);
1763         constant_to_array (mode, ops[1], arrhi);
1764         if (imode != mode)
1765           to = simplify_gen_subreg (imode, ops[0], mode, 0);
1766         else
1767           to = ops[0];
1768         temp = !can_create_pseudo_p () ? to : gen_reg_rtx (imode);
1769         for (i = 0; i < 16; i += 4)
1770           {
1771             arrlo[i + 2] = arrhi[i + 2];
1772             arrlo[i + 3] = arrhi[i + 3];
1773             arrlo[i + 0] = arrlo[i + 1] = 0;
1774             arrhi[i + 2] = arrhi[i + 3] = 0;
1775           }
1776         hi = array_to_constant (imode, arrhi);
1777         lo = array_to_constant (imode, arrlo);
1778         emit_move_insn (temp, hi);
1779         emit_insn (gen_rtx_SET
1780                    (VOIDmode, to, gen_rtx_IOR (imode, temp, lo)));
1781         return 1;
1782       }
1783     case IC_FSMBI2:
1784       {
1785         unsigned char arr_fsmbi[16];
1786         unsigned char arr_andbi[16];
1787         rtx to, reg_fsmbi, reg_and;
1788         int i;
1789         enum machine_mode imode = mode;
1790         /* We need to do reals as ints because the constant used in the
1791          * AND might not be a legitimate real constant. */
1792         imode = int_mode_for_mode (mode);
1793         constant_to_array (mode, ops[1], arr_fsmbi);
1794         if (imode != mode)
1795           to = simplify_gen_subreg(imode, ops[0], GET_MODE (ops[0]), 0);
1796         else
1797           to = ops[0];
1798         for (i = 0; i < 16; i++)
1799           if (arr_fsmbi[i] != 0)
1800             {
1801               arr_andbi[0] = arr_fsmbi[i];
1802               arr_fsmbi[i] = 0xff;
1803             }
1804         for (i = 1; i < 16; i++)
1805           arr_andbi[i] = arr_andbi[0];
1806         reg_fsmbi = array_to_constant (imode, arr_fsmbi);
1807         reg_and = array_to_constant (imode, arr_andbi);
1808         emit_move_insn (to, reg_fsmbi);
1809         emit_insn (gen_rtx_SET
1810                    (VOIDmode, to, gen_rtx_AND (imode, to, reg_and)));
1811         return 1;
1812       }
1813     case IC_POOL:
1814       if (reload_in_progress || reload_completed)
1815         {
1816           rtx mem = force_const_mem (mode, ops[1]);
1817           if (TARGET_LARGE_MEM)
1818             {
1819               rtx addr = gen_rtx_REG (Pmode, REGNO (ops[0]));
1820               emit_move_insn (addr, XEXP (mem, 0));
1821               mem = replace_equiv_address (mem, addr);
1822             }
1823           emit_move_insn (ops[0], mem);
1824           return 1;
1825         }
1826       break;
1827     case IC_IL1s:
1828     case IC_IL2s:
1829       if (reload_completed && GET_CODE (ops[1]) != HIGH)
1830         {
1831           if (c == IC_IL2s)
1832             {
1833               emit_move_insn (ops[0], gen_rtx_HIGH (mode, ops[1]));
1834               emit_move_insn (ops[0], gen_rtx_LO_SUM (mode, ops[0], ops[1]));
1835             }
1836           else if (flag_pic)
1837             emit_insn (gen_pic (ops[0], ops[1]));
1838           if (flag_pic)
1839             {
1840               rtx pic_reg = get_pic_reg ();
1841               emit_insn (gen_addsi3 (ops[0], ops[0], pic_reg));
1842               crtl->uses_pic_offset_table = 1;
1843             }
1844           return flag_pic || c == IC_IL2s;
1845         }
1846       break;
1847     case IC_IL1:
1848     case IC_FSMBI:
1849     case IC_CPAT:
1850       break;
1851     }
1852   return 0;
1853 }
1854
1855 /* SAVING is TRUE when we are generating the actual load and store
1856    instructions for REGNO.  When determining the size of the stack
1857    needed for saving register we must allocate enough space for the
1858    worst case, because we don't always have the information early enough
1859    to not allocate it.  But we can at least eliminate the actual loads
1860    and stores during the prologue/epilogue.  */
1861 static int
1862 need_to_save_reg (int regno, int saving)
1863 {
1864   if (df_regs_ever_live_p (regno) && !call_used_regs[regno])
1865     return 1;
1866   if (flag_pic
1867       && regno == PIC_OFFSET_TABLE_REGNUM
1868       && (!saving || crtl->uses_pic_offset_table)
1869       && (!saving
1870           || !current_function_is_leaf || df_regs_ever_live_p (LAST_ARG_REGNUM)))
1871     return 1;
1872   return 0;
1873 }
1874
1875 /* This function is only correct starting with local register
1876    allocation */
1877 int
1878 spu_saved_regs_size (void)
1879 {
1880   int reg_save_size = 0;
1881   int regno;
1882
1883   for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; --regno)
1884     if (need_to_save_reg (regno, 0))
1885       reg_save_size += 0x10;
1886   return reg_save_size;
1887 }
1888
1889 static rtx
1890 frame_emit_store (int regno, rtx addr, HOST_WIDE_INT offset)
1891 {
1892   rtx reg = gen_rtx_REG (V4SImode, regno);
1893   rtx mem =
1894     gen_frame_mem (V4SImode, gen_rtx_PLUS (Pmode, addr, GEN_INT (offset)));
1895   return emit_insn (gen_movv4si (mem, reg));
1896 }
1897
1898 static rtx
1899 frame_emit_load (int regno, rtx addr, HOST_WIDE_INT offset)
1900 {
1901   rtx reg = gen_rtx_REG (V4SImode, regno);
1902   rtx mem =
1903     gen_frame_mem (V4SImode, gen_rtx_PLUS (Pmode, addr, GEN_INT (offset)));
1904   return emit_insn (gen_movv4si (reg, mem));
1905 }
1906
1907 /* This happens after reload, so we need to expand it.  */
1908 static rtx
1909 frame_emit_add_imm (rtx dst, rtx src, HOST_WIDE_INT imm, rtx scratch)
1910 {
1911   rtx insn;
1912   if (satisfies_constraint_K (GEN_INT (imm)))
1913     {
1914       insn = emit_insn (gen_addsi3 (dst, src, GEN_INT (imm)));
1915     }
1916   else
1917     {
1918       emit_insn (gen_movsi (scratch, gen_int_mode (imm, SImode)));
1919       insn = emit_insn (gen_addsi3 (dst, src, scratch));
1920       if (REGNO (src) == REGNO (scratch))
1921         abort ();
1922     }
1923   return insn;
1924 }
1925
1926 /* Return nonzero if this function is known to have a null epilogue.  */
1927
1928 int
1929 direct_return (void)
1930 {
1931   if (reload_completed)
1932     {
1933       if (cfun->static_chain_decl == 0
1934           && (spu_saved_regs_size ()
1935               + get_frame_size ()
1936               + crtl->outgoing_args_size
1937               + crtl->args.pretend_args_size == 0)
1938           && current_function_is_leaf)
1939         return 1;
1940     }
1941   return 0;
1942 }
1943
1944 /*
1945    The stack frame looks like this:
1946          +-------------+
1947          |  incoming   | 
1948          |    args     | 
1949    AP -> +-------------+
1950          | $lr save    |
1951          +-------------+
1952  prev SP | back chain  | 
1953          +-------------+
1954          |  var args   | 
1955          |  reg save   | crtl->args.pretend_args_size bytes
1956          +-------------+
1957          |    ...      | 
1958          | saved regs  | spu_saved_regs_size() bytes
1959    FP -> +-------------+
1960          |    ...      | 
1961          |   vars      | get_frame_size()  bytes
1962   HFP -> +-------------+
1963          |    ...      | 
1964          |  outgoing   | 
1965          |    args     | crtl->outgoing_args_size bytes
1966          +-------------+
1967          | $lr of next |
1968          |   frame     | 
1969          +-------------+
1970          | back chain  | 
1971    SP -> +-------------+
1972
1973 */
1974 void
1975 spu_expand_prologue (void)
1976 {
1977   HOST_WIDE_INT size = get_frame_size (), offset, regno;
1978   HOST_WIDE_INT total_size;
1979   HOST_WIDE_INT saved_regs_size;
1980   rtx sp_reg = gen_rtx_REG (Pmode, STACK_POINTER_REGNUM);
1981   rtx scratch_reg_0, scratch_reg_1;
1982   rtx insn, real;
1983
1984   if (flag_pic && optimize == 0)
1985     crtl->uses_pic_offset_table = 1;
1986
1987   if (spu_naked_function_p (current_function_decl))
1988     return;
1989
1990   scratch_reg_0 = gen_rtx_REG (SImode, LAST_ARG_REGNUM + 1);
1991   scratch_reg_1 = gen_rtx_REG (SImode, LAST_ARG_REGNUM + 2);
1992
1993   saved_regs_size = spu_saved_regs_size ();
1994   total_size = size + saved_regs_size
1995     + crtl->outgoing_args_size
1996     + crtl->args.pretend_args_size;
1997
1998   if (!current_function_is_leaf
1999       || cfun->calls_alloca || total_size > 0)
2000     total_size += STACK_POINTER_OFFSET;
2001
2002   /* Save this first because code after this might use the link
2003      register as a scratch register. */
2004   if (!current_function_is_leaf)
2005     {
2006       insn = frame_emit_store (LINK_REGISTER_REGNUM, sp_reg, 16);
2007       RTX_FRAME_RELATED_P (insn) = 1;
2008     }
2009
2010   if (total_size > 0)
2011     {
2012       offset = -crtl->args.pretend_args_size;
2013       for (regno = 0; regno < FIRST_PSEUDO_REGISTER; ++regno)
2014         if (need_to_save_reg (regno, 1))
2015           {
2016             offset -= 16;
2017             insn = frame_emit_store (regno, sp_reg, offset);
2018             RTX_FRAME_RELATED_P (insn) = 1;
2019           }
2020     }
2021
2022   if (flag_pic && crtl->uses_pic_offset_table)
2023     {
2024       rtx pic_reg = get_pic_reg ();
2025       insn = emit_insn (gen_load_pic_offset (pic_reg, scratch_reg_0));
2026       insn = emit_insn (gen_subsi3 (pic_reg, pic_reg, scratch_reg_0));
2027     }
2028
2029   if (total_size > 0)
2030     {
2031       if (flag_stack_check)
2032         {
2033           /* We compare against total_size-1 because
2034              ($sp >= total_size) <=> ($sp > total_size-1) */
2035           rtx scratch_v4si = gen_rtx_REG (V4SImode, REGNO (scratch_reg_0));
2036           rtx sp_v4si = gen_rtx_REG (V4SImode, STACK_POINTER_REGNUM);
2037           rtx size_v4si = spu_const (V4SImode, total_size - 1);
2038           if (!satisfies_constraint_K (GEN_INT (total_size - 1)))
2039             {
2040               emit_move_insn (scratch_v4si, size_v4si);
2041               size_v4si = scratch_v4si;
2042             }
2043           emit_insn (gen_cgt_v4si (scratch_v4si, sp_v4si, size_v4si));
2044           emit_insn (gen_vec_extractv4si
2045                      (scratch_reg_0, scratch_v4si, GEN_INT (1)));
2046           emit_insn (gen_spu_heq (scratch_reg_0, GEN_INT (0)));
2047         }
2048
2049       /* Adjust the stack pointer, and make sure scratch_reg_0 contains
2050          the value of the previous $sp because we save it as the back
2051          chain. */
2052       if (total_size <= 2000)
2053         {
2054           /* In this case we save the back chain first. */
2055           insn = frame_emit_store (STACK_POINTER_REGNUM, sp_reg, -total_size);
2056           insn =
2057             frame_emit_add_imm (sp_reg, sp_reg, -total_size, scratch_reg_0);
2058         }
2059       else
2060         {
2061           insn = emit_move_insn (scratch_reg_0, sp_reg);
2062           insn =
2063             frame_emit_add_imm (sp_reg, sp_reg, -total_size, scratch_reg_1);
2064         }
2065       RTX_FRAME_RELATED_P (insn) = 1;
2066       real = gen_addsi3 (sp_reg, sp_reg, GEN_INT (-total_size));
2067       add_reg_note (insn, REG_FRAME_RELATED_EXPR, real);
2068
2069       if (total_size > 2000)
2070         {
2071           /* Save the back chain ptr */
2072           insn = frame_emit_store (REGNO (scratch_reg_0), sp_reg, 0);
2073         }
2074
2075       if (frame_pointer_needed)
2076         {
2077           rtx fp_reg = gen_rtx_REG (Pmode, HARD_FRAME_POINTER_REGNUM);
2078           HOST_WIDE_INT fp_offset = STACK_POINTER_OFFSET
2079             + crtl->outgoing_args_size;
2080           /* Set the new frame_pointer */
2081           insn = frame_emit_add_imm (fp_reg, sp_reg, fp_offset, scratch_reg_0);
2082           RTX_FRAME_RELATED_P (insn) = 1;
2083           real = gen_addsi3 (fp_reg, sp_reg, GEN_INT (fp_offset));
2084           add_reg_note (insn, REG_FRAME_RELATED_EXPR, real);
2085           REGNO_POINTER_ALIGN (HARD_FRAME_POINTER_REGNUM) = STACK_BOUNDARY;
2086         }
2087     }
2088
2089 }
2090
2091 void
2092 spu_expand_epilogue (bool sibcall_p)
2093 {
2094   int size = get_frame_size (), offset, regno;
2095   HOST_WIDE_INT saved_regs_size, total_size;
2096   rtx sp_reg = gen_rtx_REG (Pmode, STACK_POINTER_REGNUM);
2097   rtx jump, scratch_reg_0;
2098
2099   if (spu_naked_function_p (current_function_decl))
2100     return;
2101
2102   scratch_reg_0 = gen_rtx_REG (SImode, LAST_ARG_REGNUM + 1);
2103
2104   saved_regs_size = spu_saved_regs_size ();
2105   total_size = size + saved_regs_size
2106     + crtl->outgoing_args_size
2107     + crtl->args.pretend_args_size;
2108
2109   if (!current_function_is_leaf
2110       || cfun->calls_alloca || total_size > 0)
2111     total_size += STACK_POINTER_OFFSET;
2112
2113   if (total_size > 0)
2114     {
2115       if (cfun->calls_alloca)
2116         frame_emit_load (STACK_POINTER_REGNUM, sp_reg, 0);
2117       else
2118         frame_emit_add_imm (sp_reg, sp_reg, total_size, scratch_reg_0);
2119
2120
2121       if (saved_regs_size > 0)
2122         {
2123           offset = -crtl->args.pretend_args_size;
2124           for (regno = 0; regno < FIRST_PSEUDO_REGISTER; ++regno)
2125             if (need_to_save_reg (regno, 1))
2126               {
2127                 offset -= 0x10;
2128                 frame_emit_load (regno, sp_reg, offset);
2129               }
2130         }
2131     }
2132
2133   if (!current_function_is_leaf)
2134     frame_emit_load (LINK_REGISTER_REGNUM, sp_reg, 16);
2135
2136   if (!sibcall_p)
2137     {
2138       emit_use (gen_rtx_REG (SImode, LINK_REGISTER_REGNUM));
2139       jump = emit_jump_insn (gen__return ());
2140       emit_barrier_after (jump);
2141     }
2142
2143 }
2144
2145 rtx
2146 spu_return_addr (int count, rtx frame ATTRIBUTE_UNUSED)
2147 {
2148   if (count != 0)
2149     return 0;
2150   /* This is inefficient because it ends up copying to a save-register
2151      which then gets saved even though $lr has already been saved.  But
2152      it does generate better code for leaf functions and we don't need
2153      to use RETURN_ADDRESS_POINTER_REGNUM to get it working.  It's only
2154      used for __builtin_return_address anyway, so maybe we don't care if
2155      it's inefficient. */
2156   return get_hard_reg_initial_val (Pmode, LINK_REGISTER_REGNUM);
2157 }
2158 \f
2159
2160 /* Given VAL, generate a constant appropriate for MODE.
2161    If MODE is a vector mode, every element will be VAL.
2162    For TImode, VAL will be zero extended to 128 bits. */
2163 rtx
2164 spu_const (enum machine_mode mode, HOST_WIDE_INT val)
2165 {
2166   rtx inner;
2167   rtvec v;
2168   int units, i;
2169
2170   gcc_assert (GET_MODE_CLASS (mode) == MODE_INT
2171               || GET_MODE_CLASS (mode) == MODE_FLOAT
2172               || GET_MODE_CLASS (mode) == MODE_VECTOR_INT
2173               || GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT);
2174
2175   if (GET_MODE_CLASS (mode) == MODE_INT)
2176     return immed_double_const (val, 0, mode);
2177
2178   /* val is the bit representation of the float */
2179   if (GET_MODE_CLASS (mode) == MODE_FLOAT)
2180     return hwint_to_const_double (mode, val);
2181
2182   if (GET_MODE_CLASS (mode) == MODE_VECTOR_INT)
2183     inner = immed_double_const (val, 0, GET_MODE_INNER (mode));
2184   else 
2185     inner = hwint_to_const_double (GET_MODE_INNER (mode), val);
2186
2187   units = GET_MODE_NUNITS (mode);
2188
2189   v = rtvec_alloc (units);
2190
2191   for (i = 0; i < units; ++i)
2192     RTVEC_ELT (v, i) = inner;
2193
2194   return gen_rtx_CONST_VECTOR (mode, v);
2195 }
2196
2197 /* Create a MODE vector constant from 4 ints. */
2198 rtx
2199 spu_const_from_ints(enum machine_mode mode, int a, int b, int c, int d)
2200 {
2201   unsigned char arr[16];
2202   arr[0] = (a >> 24) & 0xff;
2203   arr[1] = (a >> 16) & 0xff;
2204   arr[2] = (a >> 8) & 0xff;
2205   arr[3] = (a >> 0) & 0xff;
2206   arr[4] = (b >> 24) & 0xff;
2207   arr[5] = (b >> 16) & 0xff;
2208   arr[6] = (b >> 8) & 0xff;
2209   arr[7] = (b >> 0) & 0xff;
2210   arr[8] = (c >> 24) & 0xff;
2211   arr[9] = (c >> 16) & 0xff;
2212   arr[10] = (c >> 8) & 0xff;
2213   arr[11] = (c >> 0) & 0xff;
2214   arr[12] = (d >> 24) & 0xff;
2215   arr[13] = (d >> 16) & 0xff;
2216   arr[14] = (d >> 8) & 0xff;
2217   arr[15] = (d >> 0) & 0xff;
2218   return array_to_constant(mode, arr);
2219 }
2220 \f
2221 /* branch hint stuff */
2222
2223 /* An array of these is used to propagate hints to predecessor blocks. */
2224 struct spu_bb_info
2225 {
2226   rtx prop_jump; /* propagated from another block */
2227   int bb_index;  /* the original block. */
2228 };
2229 static struct spu_bb_info *spu_bb_info;
2230
2231 #define STOP_HINT_P(INSN) \
2232                 (GET_CODE(INSN) == CALL_INSN \
2233                  || INSN_CODE(INSN) == CODE_FOR_divmodsi4 \
2234                  || INSN_CODE(INSN) == CODE_FOR_udivmodsi4)
2235
2236 /* 1 when RTX is a hinted branch or its target.  We keep track of
2237    what has been hinted so the safe-hint code can test it easily.  */
2238 #define HINTED_P(RTX)                                           \
2239   (RTL_FLAG_CHECK3("HINTED_P", (RTX), CODE_LABEL, JUMP_INSN, CALL_INSN)->unchanging)
2240
2241 /* 1 when RTX is an insn that must be scheduled on an even boundary. */
2242 #define SCHED_ON_EVEN_P(RTX)                                            \
2243   (RTL_FLAG_CHECK2("SCHED_ON_EVEN_P", (RTX), JUMP_INSN, CALL_INSN)->in_struct)
2244
2245 /* Emit a nop for INSN such that the two will dual issue.  This assumes
2246    INSN is 8-byte aligned.  When INSN is inline asm we emit an lnop.
2247    We check for TImode to handle a MULTI1 insn which has dual issued its
2248    first instruction.  get_pipe returns -1 for MULTI0, inline asm, or
2249    ADDR_VEC insns. */
2250 static void
2251 emit_nop_for_insn (rtx insn)
2252 {
2253   int p;
2254   rtx new_insn;
2255   p = get_pipe (insn);
2256   if ((CALL_P (insn) || JUMP_P (insn)) && SCHED_ON_EVEN_P (insn))
2257     new_insn = emit_insn_after (gen_lnop (), insn);
2258   else if (p == 1 && GET_MODE (insn) == TImode)
2259     {
2260       new_insn = emit_insn_before (gen_nopn (GEN_INT (127)), insn);
2261       PUT_MODE (new_insn, TImode);
2262       PUT_MODE (insn, VOIDmode);
2263     }
2264   else
2265     new_insn = emit_insn_after (gen_lnop (), insn);
2266   recog_memoized (new_insn);
2267 }
2268
2269 /* Insert nops in basic blocks to meet dual issue alignment
2270    requirements.  Also make sure hbrp and hint instructions are at least
2271    one cycle apart, possibly inserting a nop.  */
2272 static void
2273 pad_bb(void)
2274 {
2275   rtx insn, next_insn, prev_insn, hbr_insn = 0;
2276   int length;
2277   int addr;
2278
2279   /* This sets up INSN_ADDRESSES. */
2280   shorten_branches (get_insns ());
2281
2282   /* Keep track of length added by nops. */
2283   length = 0;
2284
2285   prev_insn = 0;
2286   insn = get_insns ();
2287   if (!active_insn_p (insn))
2288     insn = next_active_insn (insn);
2289   for (; insn; insn = next_insn)
2290     {
2291       next_insn = next_active_insn (insn);
2292       if (INSN_CODE (insn) == CODE_FOR_iprefetch
2293           || INSN_CODE (insn) == CODE_FOR_hbr)
2294         {
2295           if (hbr_insn)
2296             {
2297               int a0 = INSN_ADDRESSES (INSN_UID (hbr_insn));
2298               int a1 = INSN_ADDRESSES (INSN_UID (insn));
2299               if ((a1 - a0 == 8 && GET_MODE (insn) != TImode)
2300                   || (a1 - a0 == 4))
2301                 {
2302                   prev_insn = emit_insn_before (gen_lnop (), insn);
2303                   PUT_MODE (prev_insn, GET_MODE (insn));
2304                   PUT_MODE (insn, TImode);
2305                   length += 4;
2306                 }
2307             }
2308           hbr_insn = insn;
2309         }
2310       if (INSN_CODE (insn) == CODE_FOR_blockage)
2311         {
2312           if (GET_MODE (insn) == TImode)
2313             PUT_MODE (next_insn, TImode);
2314           insn = next_insn;
2315           next_insn = next_active_insn (insn);
2316         }
2317       addr = INSN_ADDRESSES (INSN_UID (insn));
2318       if ((CALL_P (insn) || JUMP_P (insn)) && SCHED_ON_EVEN_P (insn))
2319         {
2320           if (((addr + length) & 7) != 0)
2321             {
2322               emit_nop_for_insn (prev_insn);
2323               length += 4;
2324             }
2325         }
2326       else if (GET_MODE (insn) == TImode
2327                && ((next_insn && GET_MODE (next_insn) != TImode)
2328                    || get_attr_type (insn) == TYPE_MULTI0)
2329                && ((addr + length) & 7) != 0)
2330         {
2331           /* prev_insn will always be set because the first insn is
2332              always 8-byte aligned. */
2333           emit_nop_for_insn (prev_insn);
2334           length += 4;
2335         }
2336       prev_insn = insn;
2337     }
2338 }
2339
2340 \f
2341 /* Routines for branch hints. */
2342
2343 static void
2344 spu_emit_branch_hint (rtx before, rtx branch, rtx target,
2345                       int distance, sbitmap blocks)
2346 {
2347   rtx branch_label = 0;
2348   rtx hint;
2349   rtx insn;
2350   rtx table;
2351
2352   if (before == 0 || branch == 0 || target == 0)
2353     return;
2354
2355   /* While scheduling we require hints to be no further than 600, so
2356      we need to enforce that here too */
2357   if (distance > 600)
2358     return;
2359
2360   /* If we have a Basic block note, emit it after the basic block note.  */
2361   if (NOTE_INSN_BASIC_BLOCK_P (before))
2362     before = NEXT_INSN (before);
2363
2364   branch_label = gen_label_rtx ();
2365   LABEL_NUSES (branch_label)++;
2366   LABEL_PRESERVE_P (branch_label) = 1;
2367   insn = emit_label_before (branch_label, branch);
2368   branch_label = gen_rtx_LABEL_REF (VOIDmode, branch_label);
2369   SET_BIT (blocks, BLOCK_FOR_INSN (branch)->index);
2370
2371   hint = emit_insn_before (gen_hbr (branch_label, target), before);
2372   recog_memoized (hint);
2373   HINTED_P (branch) = 1;
2374
2375   if (GET_CODE (target) == LABEL_REF)
2376     HINTED_P (XEXP (target, 0)) = 1;
2377   else if (tablejump_p (branch, 0, &table))
2378     {
2379       rtvec vec;
2380       int j;
2381       if (GET_CODE (PATTERN (table)) == ADDR_VEC)
2382         vec = XVEC (PATTERN (table), 0);
2383       else
2384         vec = XVEC (PATTERN (table), 1);
2385       for (j = GET_NUM_ELEM (vec) - 1; j >= 0; --j)
2386         HINTED_P (XEXP (RTVEC_ELT (vec, j), 0)) = 1;
2387     }
2388
2389   if (distance >= 588)
2390     {
2391       /* Make sure the hint isn't scheduled any earlier than this point,
2392          which could make it too far for the branch offest to fit */
2393       recog_memoized (emit_insn_before (gen_blockage (), hint));
2394     }
2395   else if (distance <= 8 * 4)
2396     {
2397       /* To guarantee at least 8 insns between the hint and branch we
2398          insert nops. */
2399       int d;
2400       for (d = distance; d < 8 * 4; d += 4)
2401         {
2402           insn =
2403             emit_insn_after (gen_nopn_nv (gen_rtx_REG (SImode, 127)), hint);
2404           recog_memoized (insn);
2405         }
2406
2407       /* Make sure any nops inserted aren't scheduled before the hint. */
2408       recog_memoized (emit_insn_after (gen_blockage (), hint));
2409
2410       /* Make sure any nops inserted aren't scheduled after the call. */
2411       if (CALL_P (branch) && distance < 8 * 4)
2412         recog_memoized (emit_insn_before (gen_blockage (), branch));
2413     }
2414 }
2415
2416 /* Returns 0 if we don't want a hint for this branch.  Otherwise return
2417    the rtx for the branch target. */
2418 static rtx
2419 get_branch_target (rtx branch)
2420 {
2421   if (GET_CODE (branch) == JUMP_INSN)
2422     {
2423       rtx set, src;
2424
2425       /* Return statements */
2426       if (GET_CODE (PATTERN (branch)) == RETURN)
2427         return gen_rtx_REG (SImode, LINK_REGISTER_REGNUM);
2428
2429       /* jump table */
2430       if (GET_CODE (PATTERN (branch)) == ADDR_VEC
2431           || GET_CODE (PATTERN (branch)) == ADDR_DIFF_VEC)
2432         return 0;
2433
2434      /* ASM GOTOs. */
2435      if (extract_asm_operands (PATTERN (branch)) != NULL)
2436         return NULL;
2437
2438       set = single_set (branch);
2439       src = SET_SRC (set);
2440       if (GET_CODE (SET_DEST (set)) != PC)
2441         abort ();
2442
2443       if (GET_CODE (src) == IF_THEN_ELSE)
2444         {
2445           rtx lab = 0;
2446           rtx note = find_reg_note (branch, REG_BR_PROB, 0);
2447           if (note)
2448             {
2449               /* If the more probable case is not a fall through, then
2450                  try a branch hint.  */
2451               HOST_WIDE_INT prob = INTVAL (XEXP (note, 0));
2452               if (prob > (REG_BR_PROB_BASE * 6 / 10)
2453                   && GET_CODE (XEXP (src, 1)) != PC)
2454                 lab = XEXP (src, 1);
2455               else if (prob < (REG_BR_PROB_BASE * 4 / 10)
2456                        && GET_CODE (XEXP (src, 2)) != PC)
2457                 lab = XEXP (src, 2);
2458             }
2459           if (lab)
2460             {
2461               if (GET_CODE (lab) == RETURN)
2462                 return gen_rtx_REG (SImode, LINK_REGISTER_REGNUM);
2463               return lab;
2464             }
2465           return 0;
2466         }
2467
2468       return src;
2469     }
2470   else if (GET_CODE (branch) == CALL_INSN)
2471     {
2472       rtx call;
2473       /* All of our call patterns are in a PARALLEL and the CALL is
2474          the first pattern in the PARALLEL. */
2475       if (GET_CODE (PATTERN (branch)) != PARALLEL)
2476         abort ();
2477       call = XVECEXP (PATTERN (branch), 0, 0);
2478       if (GET_CODE (call) == SET)
2479         call = SET_SRC (call);
2480       if (GET_CODE (call) != CALL)
2481         abort ();
2482       return XEXP (XEXP (call, 0), 0);
2483     }
2484   return 0;
2485 }
2486
2487 /* The special $hbr register is used to prevent the insn scheduler from
2488    moving hbr insns across instructions which invalidate them.  It
2489    should only be used in a clobber, and this function searches for
2490    insns which clobber it.  */
2491 static bool
2492 insn_clobbers_hbr (rtx insn)
2493 {
2494   if (INSN_P (insn)
2495       && GET_CODE (PATTERN (insn)) == PARALLEL)
2496     {
2497       rtx parallel = PATTERN (insn);
2498       rtx clobber;
2499       int j;
2500       for (j = XVECLEN (parallel, 0) - 1; j >= 0; j--)
2501         {
2502           clobber = XVECEXP (parallel, 0, j);
2503           if (GET_CODE (clobber) == CLOBBER
2504               && GET_CODE (XEXP (clobber, 0)) == REG
2505               && REGNO (XEXP (clobber, 0)) == HBR_REGNUM)
2506             return 1;
2507         }
2508     }
2509   return 0;
2510 }
2511
2512 /* Search up to 32 insns starting at FIRST:
2513    - at any kind of hinted branch, just return
2514    - at any unconditional branch in the first 15 insns, just return
2515    - at a call or indirect branch, after the first 15 insns, force it to
2516      an even address and return
2517    - at any unconditional branch, after the first 15 insns, force it to
2518      an even address. 
2519    At then end of the search, insert an hbrp within 4 insns of FIRST,
2520    and an hbrp within 16 instructions of FIRST.
2521  */
2522 static void
2523 insert_hbrp_for_ilb_runout (rtx first)
2524 {
2525   rtx insn, before_4 = 0, before_16 = 0;
2526   int addr = 0, length, first_addr = -1;
2527   int hbrp_addr0 = 128 * 4, hbrp_addr1 = 128 * 4;
2528   int insert_lnop_after = 0;
2529   for (insn = first; insn; insn = NEXT_INSN (insn))
2530     if (INSN_P (insn))
2531       {
2532         if (first_addr == -1)
2533           first_addr = INSN_ADDRESSES (INSN_UID (insn));
2534         addr = INSN_ADDRESSES (INSN_UID (insn)) - first_addr;
2535         length = get_attr_length (insn);
2536
2537         if (before_4 == 0 && addr + length >= 4 * 4)
2538           before_4 = insn;
2539         /* We test for 14 instructions because the first hbrp will add
2540            up to 2 instructions. */
2541         if (before_16 == 0 && addr + length >= 14 * 4)
2542           before_16 = insn;
2543
2544         if (INSN_CODE (insn) == CODE_FOR_hbr)
2545           {
2546             /* Make sure an hbrp is at least 2 cycles away from a hint. 
2547                Insert an lnop after the hbrp when necessary. */
2548             if (before_4 == 0 && addr > 0)
2549               {
2550                 before_4 = insn;
2551                 insert_lnop_after |= 1;
2552               }
2553             else if (before_4 && addr <= 4 * 4)
2554               insert_lnop_after |= 1;
2555             if (before_16 == 0 && addr > 10 * 4)
2556               {
2557                 before_16 = insn;
2558                 insert_lnop_after |= 2;
2559               }
2560             else if (before_16 && addr <= 14 * 4)
2561               insert_lnop_after |= 2;
2562           }
2563
2564         if (INSN_CODE (insn) == CODE_FOR_iprefetch)
2565           {
2566             if (addr < hbrp_addr0)
2567               hbrp_addr0 = addr;
2568             else if (addr < hbrp_addr1)
2569               hbrp_addr1 = addr;
2570           }
2571
2572         if (CALL_P (insn) || JUMP_P (insn))
2573           {
2574             if (HINTED_P (insn))
2575               return;
2576
2577             /* Any branch after the first 15 insns should be on an even
2578                address to avoid a special case branch.  There might be
2579                some nops and/or hbrps inserted, so we test after 10
2580                insns. */
2581             if (addr > 10 * 4)
2582               SCHED_ON_EVEN_P (insn) = 1;
2583           }
2584
2585         if (CALL_P (insn) || tablejump_p (insn, 0, 0))
2586           return;
2587
2588
2589         if (addr + length >= 32 * 4)
2590           {
2591             gcc_assert (before_4 && before_16);
2592             if (hbrp_addr0 > 4 * 4)
2593               {
2594                 insn =
2595                   emit_insn_before (gen_iprefetch (GEN_INT (1)), before_4);
2596                 recog_memoized (insn);
2597                 INSN_ADDRESSES_NEW (insn,
2598                                     INSN_ADDRESSES (INSN_UID (before_4)));
2599                 PUT_MODE (insn, GET_MODE (before_4));
2600                 PUT_MODE (before_4, TImode);
2601                 if (insert_lnop_after & 1)
2602                   {
2603                     insn = emit_insn_before (gen_lnop (), before_4);
2604                     recog_memoized (insn);
2605                     INSN_ADDRESSES_NEW (insn,
2606                                         INSN_ADDRESSES (INSN_UID (before_4)));
2607                     PUT_MODE (insn, TImode);
2608                   }
2609               }
2610             if ((hbrp_addr0 <= 4 * 4 || hbrp_addr0 > 16 * 4)
2611                 && hbrp_addr1 > 16 * 4)
2612               {
2613                 insn =
2614                   emit_insn_before (gen_iprefetch (GEN_INT (2)), before_16);
2615                 recog_memoized (insn);
2616                 INSN_ADDRESSES_NEW (insn,
2617                                     INSN_ADDRESSES (INSN_UID (before_16)));
2618                 PUT_MODE (insn, GET_MODE (before_16));
2619                 PUT_MODE (before_16, TImode);
2620                 if (insert_lnop_after & 2)
2621                   {
2622                     insn = emit_insn_before (gen_lnop (), before_16);
2623                     recog_memoized (insn);
2624                     INSN_ADDRESSES_NEW (insn,
2625                                         INSN_ADDRESSES (INSN_UID
2626                                                         (before_16)));
2627                     PUT_MODE (insn, TImode);
2628                   }
2629               }
2630             return;
2631           }
2632       }
2633     else if (BARRIER_P (insn))
2634       return;
2635
2636 }
2637
2638 /* The SPU might hang when it executes 48 inline instructions after a
2639    hinted branch jumps to its hinted target.  The beginning of a
2640    function and the return from a call might have been hinted, and must
2641    be handled as well.  To prevent a hang we insert 2 hbrps.  The first
2642    should be within 6 insns of the branch target.  The second should be
2643    within 22 insns of the branch target.  When determining if hbrps are
2644    necessary, we look for only 32 inline instructions, because up to to
2645    12 nops and 4 hbrps could be inserted.  Similarily, when inserting
2646    new hbrps, we insert them within 4 and 16 insns of the target.  */
2647 static void
2648 insert_hbrp (void)
2649 {
2650   rtx insn;
2651   if (TARGET_SAFE_HINTS)
2652     {
2653       shorten_branches (get_insns ());
2654       /* Insert hbrp at beginning of function */
2655       insn = next_active_insn (get_insns ());
2656       if (insn)
2657         insert_hbrp_for_ilb_runout (insn);
2658       /* Insert hbrp after hinted targets. */
2659       for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
2660         if ((LABEL_P (insn) && HINTED_P (insn)) || CALL_P (insn))
2661           insert_hbrp_for_ilb_runout (next_active_insn (insn));
2662     }
2663 }
2664
2665 static int in_spu_reorg;
2666
2667 /* Insert branch hints.  There are no branch optimizations after this
2668    pass, so it's safe to set our branch hints now. */
2669 static void
2670 spu_machine_dependent_reorg (void)
2671 {
2672   sbitmap blocks;
2673   basic_block bb;
2674   rtx branch, insn;
2675   rtx branch_target = 0;
2676   int branch_addr = 0, insn_addr, required_dist = 0;
2677   int i;
2678   unsigned int j;
2679
2680   if (!TARGET_BRANCH_HINTS || optimize == 0)
2681     {
2682       /* We still do it for unoptimized code because an external
2683          function might have hinted a call or return. */
2684       insert_hbrp ();
2685       pad_bb ();
2686       return;
2687     }
2688
2689   blocks = sbitmap_alloc (last_basic_block);
2690   sbitmap_zero (blocks);
2691
2692   in_spu_reorg = 1;
2693   compute_bb_for_insn ();
2694
2695   compact_blocks ();
2696
2697   spu_bb_info =
2698     (struct spu_bb_info *) xcalloc (n_basic_blocks,
2699                                     sizeof (struct spu_bb_info));
2700
2701   /* We need exact insn addresses and lengths.  */
2702   shorten_branches (get_insns ());
2703
2704   for (i = n_basic_blocks - 1; i >= 0; i--)
2705     {
2706       bb = BASIC_BLOCK (i);
2707       branch = 0;
2708       if (spu_bb_info[i].prop_jump)
2709         {
2710           branch = spu_bb_info[i].prop_jump;
2711           branch_target = get_branch_target (branch);
2712           branch_addr = INSN_ADDRESSES (INSN_UID (branch));
2713           required_dist = spu_hint_dist;
2714         }
2715       /* Search from end of a block to beginning.   In this loop, find
2716          jumps which need a branch and emit them only when:
2717          - it's an indirect branch and we're at the insn which sets
2718          the register  
2719          - we're at an insn that will invalidate the hint. e.g., a
2720          call, another hint insn, inline asm that clobbers $hbr, and
2721          some inlined operations (divmodsi4).  Don't consider jumps
2722          because they are only at the end of a block and are
2723          considered when we are deciding whether to propagate
2724          - we're getting too far away from the branch.  The hbr insns
2725          only have a signed 10 bit offset
2726          We go back as far as possible so the branch will be considered
2727          for propagation when we get to the beginning of the block.  */
2728       for (insn = BB_END (bb); insn; insn = PREV_INSN (insn))
2729         {
2730           if (INSN_P (insn))
2731             {
2732               insn_addr = INSN_ADDRESSES (INSN_UID (insn));
2733               if (branch
2734                   && ((GET_CODE (branch_target) == REG
2735                        && set_of (branch_target, insn) != NULL_RTX)
2736                       || insn_clobbers_hbr (insn)
2737                       || branch_addr - insn_addr > 600))
2738                 {
2739                   rtx next = NEXT_INSN (insn);
2740                   int next_addr = INSN_ADDRESSES (INSN_UID (next));
2741                   if (insn != BB_END (bb)
2742                       && branch_addr - next_addr >= required_dist)
2743                     {
2744                       if (dump_file)
2745                         fprintf (dump_file,
2746                                  "hint for %i in block %i before %i\n",
2747                                  INSN_UID (branch), bb->index,
2748                                  INSN_UID (next));
2749                       spu_emit_branch_hint (next, branch, branch_target,
2750                                             branch_addr - next_addr, blocks);
2751                     }
2752                   branch = 0;
2753                 }
2754
2755               /* JUMP_P will only be true at the end of a block.  When
2756                  branch is already set it means we've previously decided
2757                  to propagate a hint for that branch into this block. */
2758               if (CALL_P (insn) || (JUMP_P (insn) && !branch))
2759                 {
2760                   branch = 0;
2761                   if ((branch_target = get_branch_target (insn)))
2762                     {
2763                       branch = insn;
2764                       branch_addr = insn_addr;
2765                       required_dist = spu_hint_dist;
2766                     }
2767                 }
2768             }
2769           if (insn == BB_HEAD (bb))
2770             break;
2771         }
2772
2773       if (branch)
2774         {
2775           /* If we haven't emitted a hint for this branch yet, it might
2776              be profitable to emit it in one of the predecessor blocks,
2777              especially for loops.  */
2778           rtx bbend;
2779           basic_block prev = 0, prop = 0, prev2 = 0;
2780           int loop_exit = 0, simple_loop = 0;
2781           int next_addr = INSN_ADDRESSES (INSN_UID (NEXT_INSN (insn)));
2782
2783           for (j = 0; j < EDGE_COUNT (bb->preds); j++)
2784             if (EDGE_PRED (bb, j)->flags & EDGE_FALLTHRU)
2785               prev = EDGE_PRED (bb, j)->src;
2786             else
2787               prev2 = EDGE_PRED (bb, j)->src;
2788
2789           for (j = 0; j < EDGE_COUNT (bb->succs); j++)
2790             if (EDGE_SUCC (bb, j)->flags & EDGE_LOOP_EXIT)
2791               loop_exit = 1;
2792             else if (EDGE_SUCC (bb, j)->dest == bb)
2793               simple_loop = 1;
2794
2795           /* If this branch is a loop exit then propagate to previous
2796              fallthru block. This catches the cases when it is a simple
2797              loop or when there is an initial branch into the loop. */
2798           if (prev && (loop_exit || simple_loop)
2799               && prev->loop_depth <= bb->loop_depth)
2800             prop = prev;
2801
2802           /* If there is only one adjacent predecessor.  Don't propagate
2803              outside this loop.  This loop_depth test isn't perfect, but
2804              I'm not sure the loop_father member is valid at this point.  */
2805           else if (prev && single_pred_p (bb)
2806                    && prev->loop_depth == bb->loop_depth)
2807             prop = prev;
2808
2809           /* If this is the JOIN block of a simple IF-THEN then
2810              propogate the hint to the HEADER block. */
2811           else if (prev && prev2
2812                    && EDGE_COUNT (bb->preds) == 2
2813                    && EDGE_COUNT (prev->preds) == 1
2814                    && EDGE_PRED (prev, 0)->src == prev2
2815                    && prev2->loop_depth == bb->loop_depth
2816                    && GET_CODE (branch_target) != REG)
2817             prop = prev;
2818
2819           /* Don't propagate when:
2820              - this is a simple loop and the hint would be too far
2821              - this is not a simple loop and there are 16 insns in
2822              this block already
2823              - the predecessor block ends in a branch that will be
2824              hinted
2825              - the predecessor block ends in an insn that invalidates
2826              the hint */
2827           if (prop
2828               && prop->index >= 0
2829               && (bbend = BB_END (prop))
2830               && branch_addr - INSN_ADDRESSES (INSN_UID (bbend)) <
2831               (simple_loop ? 600 : 16 * 4) && get_branch_target (bbend) == 0
2832               && (JUMP_P (bbend) || !insn_clobbers_hbr (bbend)))
2833             {
2834               if (dump_file)
2835                 fprintf (dump_file, "propagate from %i to %i (loop depth %i) "
2836                          "for %i (loop_exit %i simple_loop %i dist %i)\n",
2837                          bb->index, prop->index, bb->loop_depth,
2838                          INSN_UID (branch), loop_exit, simple_loop,
2839                          branch_addr - INSN_ADDRESSES (INSN_UID (bbend)));
2840
2841               spu_bb_info[prop->index].prop_jump = branch;
2842               spu_bb_info[prop->index].bb_index = i;
2843             }
2844           else if (branch_addr - next_addr >= required_dist)
2845             {
2846               if (dump_file)
2847                 fprintf (dump_file, "hint for %i in block %i before %i\n",
2848                          INSN_UID (branch), bb->index,
2849                          INSN_UID (NEXT_INSN (insn)));
2850               spu_emit_branch_hint (NEXT_INSN (insn), branch, branch_target,
2851                                     branch_addr - next_addr, blocks);
2852             }
2853           branch = 0;
2854         }
2855     }
2856   free (spu_bb_info);
2857
2858   if (!sbitmap_empty_p (blocks))
2859     find_many_sub_basic_blocks (blocks);
2860
2861   /* We have to schedule to make sure alignment is ok. */
2862   FOR_EACH_BB (bb) bb->flags &= ~BB_DISABLE_SCHEDULE;
2863
2864   /* The hints need to be scheduled, so call it again. */
2865   schedule_insns ();
2866
2867   insert_hbrp ();
2868
2869   pad_bb ();
2870
2871   for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
2872     if (NONJUMP_INSN_P (insn) && INSN_CODE (insn) == CODE_FOR_hbr)
2873       {
2874         /* Adjust the LABEL_REF in a hint when we have inserted a nop
2875            between its branch label and the branch .  We don't move the
2876            label because GCC expects it at the beginning of the block. */
2877         rtx unspec = SET_SRC (XVECEXP (PATTERN (insn), 0, 0));
2878         rtx label_ref = XVECEXP (unspec, 0, 0);
2879         rtx label = XEXP (label_ref, 0);
2880         rtx branch;
2881         int offset = 0;
2882         for (branch = NEXT_INSN (label);
2883              !JUMP_P (branch) && !CALL_P (branch);
2884              branch = NEXT_INSN (branch))
2885           if (NONJUMP_INSN_P (branch))
2886             offset += get_attr_length (branch);
2887         if (offset > 0)
2888           XVECEXP (unspec, 0, 0) = plus_constant (label_ref, offset);
2889       }
2890
2891   if (spu_flag_var_tracking)
2892     {
2893       df_analyze ();
2894       timevar_push (TV_VAR_TRACKING);
2895       variable_tracking_main ();
2896       timevar_pop (TV_VAR_TRACKING);
2897       df_finish_pass (false);
2898     }
2899
2900   free_bb_for_insn ();
2901
2902   in_spu_reorg = 0;
2903 }
2904 \f
2905
2906 /* Insn scheduling routines, primarily for dual issue. */
2907 static int
2908 spu_sched_issue_rate (void)
2909 {
2910   return 2;
2911 }
2912
2913 static int
2914 uses_ls_unit(rtx insn)
2915 {
2916   rtx set = single_set (insn);
2917   if (set != 0
2918       && (GET_CODE (SET_DEST (set)) == MEM
2919           || GET_CODE (SET_SRC (set)) == MEM))
2920     return 1;
2921   return 0;
2922 }
2923
2924 static int
2925 get_pipe (rtx insn)
2926 {
2927   enum attr_type t;
2928   /* Handle inline asm */
2929   if (INSN_CODE (insn) == -1)
2930     return -1;
2931   t = get_attr_type (insn);
2932   switch (t)
2933     {
2934     case TYPE_CONVERT:
2935       return -2;
2936     case TYPE_MULTI0:
2937       return -1;
2938
2939     case TYPE_FX2:
2940     case TYPE_FX3:
2941     case TYPE_SPR:
2942     case TYPE_NOP:
2943     case TYPE_FXB:
2944     case TYPE_FPD:
2945     case TYPE_FP6:
2946     case TYPE_FP7:
2947       return 0;
2948
2949     case TYPE_LNOP:
2950     case TYPE_SHUF:
2951     case TYPE_LOAD:
2952     case TYPE_STORE:
2953     case TYPE_BR:
2954     case TYPE_MULTI1:
2955     case TYPE_HBR:
2956     case TYPE_IPREFETCH:
2957       return 1;
2958     default:
2959       abort ();
2960     }
2961 }
2962
2963
2964 /* haifa-sched.c has a static variable that keeps track of the current
2965    cycle.  It is passed to spu_sched_reorder, and we record it here for
2966    use by spu_sched_variable_issue.  It won't be accurate if the
2967    scheduler updates it's clock_var between the two calls. */
2968 static int clock_var;
2969
2970 /* This is used to keep track of insn alignment.  Set to 0 at the
2971    beginning of each block and increased by the "length" attr of each
2972    insn scheduled. */
2973 static int spu_sched_length;
2974
2975 /* Record when we've issued pipe0 and pipe1 insns so we can reorder the
2976    ready list appropriately in spu_sched_reorder(). */
2977 static int pipe0_clock;
2978 static int pipe1_clock;
2979
2980 static int prev_clock_var;
2981
2982 static int prev_priority;
2983
2984 /* The SPU needs to load the next ilb sometime during the execution of
2985    the previous ilb.  There is a potential conflict if every cycle has a
2986    load or store.  To avoid the conflict we make sure the load/store
2987    unit is free for at least one cycle during the execution of insns in
2988    the previous ilb. */
2989 static int spu_ls_first;
2990 static int prev_ls_clock;
2991
2992 static void
2993 spu_sched_init_global (FILE *file ATTRIBUTE_UNUSED, int verbose ATTRIBUTE_UNUSED,
2994                        int max_ready ATTRIBUTE_UNUSED)
2995 {
2996   spu_sched_length = 0;
2997 }
2998
2999 static void
3000 spu_sched_init (FILE *file ATTRIBUTE_UNUSED, int verbose ATTRIBUTE_UNUSED,
3001                 int max_ready ATTRIBUTE_UNUSED)
3002 {
3003   if (align_labels > 4 || align_loops > 4 || align_jumps > 4)
3004     {
3005       /* When any block might be at least 8-byte aligned, assume they
3006          will all be at least 8-byte aligned to make sure dual issue
3007          works out correctly. */
3008       spu_sched_length = 0;
3009     }
3010   spu_ls_first = INT_MAX;
3011   clock_var = -1;
3012   prev_ls_clock = -1;
3013   pipe0_clock = -1;
3014   pipe1_clock = -1;
3015   prev_clock_var = -1;
3016   prev_priority = -1;
3017 }
3018
3019 static int
3020 spu_sched_variable_issue (FILE *file ATTRIBUTE_UNUSED,
3021                           int verbose ATTRIBUTE_UNUSED, rtx insn, int more)
3022 {
3023   int len;
3024   int p;
3025   if (GET_CODE (PATTERN (insn)) == USE
3026       || GET_CODE (PATTERN (insn)) == CLOBBER
3027       || (len = get_attr_length (insn)) == 0)
3028     return more;
3029
3030   spu_sched_length += len;
3031
3032   /* Reset on inline asm */
3033   if (INSN_CODE (insn) == -1)
3034     {
3035       spu_ls_first = INT_MAX;
3036       pipe0_clock = -1;
3037       pipe1_clock = -1;
3038       return 0;
3039     }
3040   p = get_pipe (insn);
3041   if (p == 0)
3042     pipe0_clock = clock_var;
3043   else
3044     pipe1_clock = clock_var;
3045
3046   if (in_spu_reorg)
3047     {
3048       if (clock_var - prev_ls_clock > 1
3049           || INSN_CODE (insn) == CODE_FOR_iprefetch)
3050         spu_ls_first = INT_MAX;
3051       if (uses_ls_unit (insn))
3052         {
3053           if (spu_ls_first == INT_MAX)
3054             spu_ls_first = spu_sched_length;
3055           prev_ls_clock = clock_var;
3056         }
3057
3058       /* The scheduler hasn't inserted the nop, but we will later on.
3059          Include those nops in spu_sched_length. */
3060       if (prev_clock_var == clock_var && (spu_sched_length & 7))
3061         spu_sched_length += 4;
3062       prev_clock_var = clock_var;
3063
3064       /* more is -1 when called from spu_sched_reorder for new insns
3065          that don't have INSN_PRIORITY */
3066       if (more >= 0)
3067         prev_priority = INSN_PRIORITY (insn);
3068     }
3069
3070   /* Always try issueing more insns.  spu_sched_reorder will decide 
3071      when the cycle should be advanced. */
3072   return 1;
3073 }
3074
3075 /* This function is called for both TARGET_SCHED_REORDER and
3076    TARGET_SCHED_REORDER2.  */
3077 static int
3078 spu_sched_reorder (FILE *file ATTRIBUTE_UNUSED, int verbose ATTRIBUTE_UNUSED,
3079                    rtx *ready, int *nreadyp, int clock)
3080 {
3081   int i, nready = *nreadyp;
3082   int pipe_0, pipe_1, pipe_hbrp, pipe_ls, schedule_i;
3083   rtx insn;
3084
3085   clock_var = clock;
3086
3087   if (nready <= 0 || pipe1_clock >= clock)
3088     return 0;
3089
3090   /* Find any rtl insns that don't generate assembly insns and schedule
3091      them first. */
3092   for (i = nready - 1; i >= 0; i--)
3093     {
3094       insn = ready[i];
3095       if (INSN_CODE (insn) == -1
3096           || INSN_CODE (insn) == CODE_FOR_blockage
3097           || (INSN_P (insn) && get_attr_length (insn) == 0))
3098         {
3099           ready[i] = ready[nready - 1];
3100           ready[nready - 1] = insn;
3101           return 1;
3102         }
3103     }
3104
3105   pipe_0 = pipe_1 = pipe_hbrp = pipe_ls = schedule_i = -1;
3106   for (i = 0; i < nready; i++)
3107     if (INSN_CODE (ready[i]) != -1)
3108       {
3109         insn = ready[i];
3110         switch (get_attr_type (insn))
3111           {
3112           default:
3113           case TYPE_MULTI0:
3114           case TYPE_CONVERT:
3115           case TYPE_FX2:
3116           case TYPE_FX3:
3117           case TYPE_SPR:
3118           case TYPE_NOP:
3119           case TYPE_FXB:
3120           case TYPE_FPD:
3121           case TYPE_FP6:
3122           case TYPE_FP7:
3123             pipe_0 = i;
3124             break;
3125           case TYPE_LOAD:
3126           case TYPE_STORE:
3127             pipe_ls = i;
3128           case TYPE_LNOP:
3129           case TYPE_SHUF:
3130           case TYPE_BR:
3131           case TYPE_MULTI1:
3132           case TYPE_HBR:
3133             pipe_1 = i;
3134             break;
3135           case TYPE_IPREFETCH:
3136             pipe_hbrp = i;
3137             break;
3138           }
3139       }
3140
3141   /* In the first scheduling phase, schedule loads and stores together
3142      to increase the chance they will get merged during postreload CSE. */
3143   if (!reload_completed && pipe_ls >= 0)
3144     {
3145       insn = ready[pipe_ls];
3146       ready[pipe_ls] = ready[nready - 1];
3147       ready[nready - 1] = insn;
3148       return 1;
3149     }
3150
3151   /* If there is an hbrp ready, prefer it over other pipe 1 insns. */
3152   if (pipe_hbrp >= 0)
3153     pipe_1 = pipe_hbrp;
3154
3155   /* When we have loads/stores in every cycle of the last 15 insns and
3156      we are about to schedule another load/store, emit an hbrp insn
3157      instead. */
3158   if (in_spu_reorg
3159       && spu_sched_length - spu_ls_first >= 4 * 15
3160       && !(pipe0_clock < clock && pipe_0 >= 0) && pipe_1 == pipe_ls)
3161     {
3162       insn = sched_emit_insn (gen_iprefetch (GEN_INT (3)));
3163       recog_memoized (insn);
3164       if (pipe0_clock < clock)
3165         PUT_MODE (insn, TImode);
3166       spu_sched_variable_issue (file, verbose, insn, -1);
3167       return 0;
3168     }
3169
3170   /* In general, we want to emit nops to increase dual issue, but dual
3171      issue isn't faster when one of the insns could be scheduled later
3172      without effecting the critical path.  We look at INSN_PRIORITY to
3173      make a good guess, but it isn't perfect so -mdual-nops=n can be
3174      used to effect it. */
3175   if (in_spu_reorg && spu_dual_nops < 10)
3176     {
3177       /* When we are at an even address and we are not issueing nops to
3178          improve scheduling then we need to advance the cycle.  */
3179       if ((spu_sched_length & 7) == 0 && prev_clock_var == clock
3180           && (spu_dual_nops == 0
3181               || (pipe_1 != -1
3182                   && prev_priority >
3183                   INSN_PRIORITY (ready[pipe_1]) + spu_dual_nops)))
3184         return 0;
3185
3186       /* When at an odd address, schedule the highest priority insn
3187          without considering pipeline. */
3188       if ((spu_sched_length & 7) == 4 && prev_clock_var != clock
3189           && (spu_dual_nops == 0
3190               || (prev_priority >
3191                   INSN_PRIORITY (ready[nready - 1]) + spu_dual_nops)))
3192         return 1;
3193     }
3194
3195
3196   /* We haven't issued a pipe0 insn yet this cycle, if there is a
3197      pipe0 insn in the ready list, schedule it. */
3198   if (pipe0_clock < clock && pipe_0 >= 0)
3199     schedule_i = pipe_0;
3200
3201   /* Either we've scheduled a pipe0 insn already or there is no pipe0
3202      insn to schedule.  Put a pipe1 insn at the front of the ready list. */
3203   else
3204     schedule_i = pipe_1;
3205
3206   if (schedule_i > -1)
3207     {
3208       insn = ready[schedule_i];
3209       ready[schedule_i] = ready[nready - 1];
3210       ready[nready - 1] = insn;
3211       return 1;
3212     }
3213   return 0;
3214 }
3215
3216 /* INSN is dependent on DEP_INSN. */
3217 static int
3218 spu_sched_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost)
3219 {
3220   rtx set;
3221
3222   /* The blockage pattern is used to prevent instructions from being
3223      moved across it and has no cost. */
3224   if (INSN_CODE (insn) == CODE_FOR_blockage
3225       || INSN_CODE (dep_insn) == CODE_FOR_blockage)
3226     return 0;
3227
3228   if ((INSN_P (insn) && get_attr_length (insn) == 0)
3229       || (INSN_P (dep_insn) && get_attr_length (dep_insn) == 0))
3230     return 0;
3231
3232   /* Make sure hbrps are spread out. */
3233   if (INSN_CODE (insn) == CODE_FOR_iprefetch
3234       && INSN_CODE (dep_insn) == CODE_FOR_iprefetch)
3235     return 8;
3236
3237   /* Make sure hints and hbrps are 2 cycles apart. */
3238   if ((INSN_CODE (insn) == CODE_FOR_iprefetch
3239        || INSN_CODE (insn) == CODE_FOR_hbr)
3240        && (INSN_CODE (dep_insn) == CODE_FOR_iprefetch
3241            || INSN_CODE (dep_insn) == CODE_FOR_hbr))
3242     return 2;
3243
3244   /* An hbrp has no real dependency on other insns. */
3245   if (INSN_CODE (insn) == CODE_FOR_iprefetch
3246       || INSN_CODE (dep_insn) == CODE_FOR_iprefetch)
3247     return 0;
3248
3249   /* Assuming that it is unlikely an argument register will be used in
3250      the first cycle of the called function, we reduce the cost for
3251      slightly better scheduling of dep_insn.  When not hinted, the
3252      mispredicted branch would hide the cost as well.  */
3253   if (CALL_P (insn))
3254   {
3255     rtx target = get_branch_target (insn);
3256     if (GET_CODE (target) != REG || !set_of (target, insn))
3257       return cost - 2;
3258     return cost;
3259   }
3260
3261   /* And when returning from a function, let's assume the return values
3262      are completed sooner too. */
3263   if (CALL_P (dep_insn))
3264     return cost - 2;
3265
3266   /* Make sure an instruction that loads from the back chain is schedule
3267      away from the return instruction so a hint is more likely to get
3268      issued. */
3269   if (INSN_CODE (insn) == CODE_FOR__return
3270       && (set = single_set (dep_insn))
3271       && GET_CODE (SET_DEST (set)) == REG
3272       && REGNO (SET_DEST (set)) == LINK_REGISTER_REGNUM)
3273     return 20;
3274
3275   /* The dfa scheduler sets cost to 0 for all anti-dependencies and the
3276      scheduler makes every insn in a block anti-dependent on the final
3277      jump_insn.  We adjust here so higher cost insns will get scheduled
3278      earlier. */
3279   if (JUMP_P (insn) && REG_NOTE_KIND (link) == REG_DEP_ANTI)
3280     return insn_cost (dep_insn) - 3;
3281
3282   return cost;
3283 }
3284 \f
3285 /* Create a CONST_DOUBLE from a string.  */
3286 struct rtx_def *
3287 spu_float_const (const char *string, enum machine_mode mode)
3288 {
3289   REAL_VALUE_TYPE value;
3290   value = REAL_VALUE_ATOF (string, mode);
3291   return CONST_DOUBLE_FROM_REAL_VALUE (value, mode);
3292 }
3293
3294 int
3295 spu_constant_address_p (rtx x)
3296 {
3297   return (GET_CODE (x) == LABEL_REF || GET_CODE (x) == SYMBOL_REF
3298           || GET_CODE (x) == CONST_INT || GET_CODE (x) == CONST
3299           || GET_CODE (x) == HIGH);
3300 }
3301
3302 static enum spu_immediate
3303 which_immediate_load (HOST_WIDE_INT val)
3304 {
3305   gcc_assert (val == trunc_int_for_mode (val, SImode));
3306
3307   if (val >= -0x8000 && val <= 0x7fff)
3308     return SPU_IL;
3309   if (val >= 0 && val <= 0x3ffff)
3310     return SPU_ILA;
3311   if ((val & 0xffff) == ((val >> 16) & 0xffff))
3312     return SPU_ILH;
3313   if ((val & 0xffff) == 0)
3314     return SPU_ILHU;
3315
3316   return SPU_NONE;
3317 }
3318
3319 /* Return true when OP can be loaded by one of the il instructions, or
3320    when flow2 is not completed and OP can be loaded using ilhu and iohl. */
3321 int
3322 immediate_load_p (rtx op, enum machine_mode mode)
3323 {
3324   if (CONSTANT_P (op))
3325     {
3326       enum immediate_class c = classify_immediate (op, mode);
3327       return c == IC_IL1 || c == IC_IL1s
3328              || (!epilogue_completed && (c == IC_IL2 || c == IC_IL2s));
3329     }
3330   return 0;
3331 }
3332
3333 /* Return true if the first SIZE bytes of arr is a constant that can be
3334    generated with cbd, chd, cwd or cdd.  When non-NULL, PRUN and PSTART
3335    represent the size and offset of the instruction to use. */
3336 static int
3337 cpat_info(unsigned char *arr, int size, int *prun, int *pstart)
3338 {
3339   int cpat, run, i, start;
3340   cpat = 1;
3341   run = 0;
3342   start = -1;
3343   for (i = 0; i < size && cpat; i++)
3344     if (arr[i] != i+16)
3345       { 
3346         if (!run)
3347           {
3348             start = i;
3349             if (arr[i] == 3)
3350               run = 1;
3351             else if (arr[i] == 2 && arr[i+1] == 3)
3352               run = 2;
3353             else if (arr[i] == 0)
3354               {
3355                 while (arr[i+run] == run && i+run < 16)
3356                   run++;
3357                 if (run != 4 && run != 8)
3358                   cpat = 0;
3359               }
3360             else
3361               cpat = 0;
3362             if ((i & (run-1)) != 0)
3363               cpat = 0;
3364             i += run;
3365           }
3366         else
3367           cpat = 0;
3368       }
3369   if (cpat && (run || size < 16))
3370     {
3371       if (run == 0)
3372         run = 1;
3373       if (prun)
3374         *prun = run;
3375       if (pstart)
3376         *pstart = start == -1 ? 16-run : start;
3377       return 1;
3378     }
3379   return 0;
3380 }
3381
3382 /* OP is a CONSTANT_P.  Determine what instructions can be used to load
3383    it into a register.  MODE is only valid when OP is a CONST_INT. */
3384 static enum immediate_class
3385 classify_immediate (rtx op, enum machine_mode mode)
3386 {
3387   HOST_WIDE_INT val;
3388   unsigned char arr[16];
3389   int i, j, repeated, fsmbi, repeat;
3390
3391   gcc_assert (CONSTANT_P (op));
3392
3393   if (GET_MODE (op) != VOIDmode)
3394     mode = GET_MODE (op);
3395
3396   /* A V4SI const_vector with all identical symbols is ok. */
3397   if (!flag_pic
3398       && mode == V4SImode
3399       && GET_CODE (op) == CONST_VECTOR
3400       && GET_CODE (CONST_VECTOR_ELT (op, 0)) != CONST_INT
3401       && GET_CODE (CONST_VECTOR_ELT (op, 0)) != CONST_DOUBLE
3402       && CONST_VECTOR_ELT (op, 0) == CONST_VECTOR_ELT (op, 1)
3403       && CONST_VECTOR_ELT (op, 1) == CONST_VECTOR_ELT (op, 2)
3404       && CONST_VECTOR_ELT (op, 2) == CONST_VECTOR_ELT (op, 3))
3405     op = CONST_VECTOR_ELT (op, 0);
3406
3407   switch (GET_CODE (op))
3408     {
3409     case SYMBOL_REF:
3410     case LABEL_REF:
3411       return TARGET_LARGE_MEM ? IC_IL2s : IC_IL1s;
3412
3413     case CONST:
3414       /* We can never know if the resulting address fits in 18 bits and can be
3415          loaded with ila.  For now, assume the address will not overflow if
3416          the displacement is "small" (fits 'K' constraint).  */
3417       if (!TARGET_LARGE_MEM && GET_CODE (XEXP (op, 0)) == PLUS)
3418         {
3419           rtx sym = XEXP (XEXP (op, 0), 0);
3420           rtx cst = XEXP (XEXP (op, 0), 1);
3421
3422           if (GET_CODE (sym) == SYMBOL_REF
3423               && GET_CODE (cst) == CONST_INT
3424               && satisfies_constraint_K (cst))
3425             return IC_IL1s;
3426         }
3427       return IC_IL2s;
3428
3429     case HIGH:
3430       return IC_IL1s;
3431
3432     case CONST_VECTOR:
3433       for (i = 0; i < GET_MODE_NUNITS (mode); i++)
3434         if (GET_CODE (CONST_VECTOR_ELT (op, i)) != CONST_INT
3435             && GET_CODE (CONST_VECTOR_ELT (op, i)) != CONST_DOUBLE)
3436           return IC_POOL;
3437       /* Fall through. */
3438
3439     case CONST_INT:
3440     case CONST_DOUBLE:
3441       constant_to_array (mode, op, arr);
3442
3443       /* Check that each 4-byte slot is identical. */
3444       repeated = 1;
3445       for (i = 4; i < 16; i += 4)
3446         for (j = 0; j < 4; j++)
3447           if (arr[j] != arr[i + j])
3448             repeated = 0;
3449
3450       if (repeated)
3451         {
3452           val = (arr[0] << 24) | (arr[1] << 16) | (arr[2] << 8) | arr[3];
3453           val = trunc_int_for_mode (val, SImode);
3454
3455           if (which_immediate_load (val) != SPU_NONE)
3456             return IC_IL1;
3457         }
3458
3459       /* Any mode of 2 bytes or smaller can be loaded with an il
3460          instruction. */
3461       gcc_assert (GET_MODE_SIZE (mode) > 2);
3462
3463       fsmbi = 1;
3464       repeat = 0;
3465       for (i = 0; i < 16 && fsmbi; i++)
3466         if (arr[i] != 0 && repeat == 0)
3467           repeat = arr[i];
3468         else if (arr[i] != 0 && arr[i] != repeat)
3469           fsmbi = 0;
3470       if (fsmbi)
3471         return repeat == 0xff ? IC_FSMBI : IC_FSMBI2;
3472
3473       if (cpat_info (arr, GET_MODE_SIZE (mode), 0, 0))
3474         return IC_CPAT;
3475
3476       if (repeated)
3477         return IC_IL2;
3478
3479       return IC_POOL;
3480     default:
3481       break;
3482     }
3483   gcc_unreachable ();
3484 }
3485
3486 static enum spu_immediate
3487 which_logical_immediate (HOST_WIDE_INT val)
3488 {
3489   gcc_assert (val == trunc_int_for_mode (val, SImode));
3490
3491   if (val >= -0x200 && val <= 0x1ff)
3492     return SPU_ORI;
3493   if (val >= 0 && val <= 0xffff)
3494     return SPU_IOHL;
3495   if ((val & 0xffff) == ((val >> 16) & 0xffff))
3496     {
3497       val = trunc_int_for_mode (val, HImode);
3498       if (val >= -0x200 && val <= 0x1ff)
3499         return SPU_ORHI;
3500       if ((val & 0xff) == ((val >> 8) & 0xff))
3501         {
3502           val = trunc_int_for_mode (val, QImode);
3503           if (val >= -0x200 && val <= 0x1ff)
3504             return SPU_ORBI;
3505         }
3506     }
3507   return SPU_NONE;
3508 }
3509
3510 /* Return TRUE when X, a CONST_VECTOR, only contains CONST_INTs or
3511    CONST_DOUBLEs. */
3512 static int
3513 const_vector_immediate_p (rtx x)
3514 {
3515   int i;
3516   gcc_assert (GET_CODE (x) == CONST_VECTOR);
3517   for (i = 0; i < GET_MODE_NUNITS (GET_MODE (x)); i++)
3518     if (GET_CODE (CONST_VECTOR_ELT (x, i)) != CONST_INT
3519         && GET_CODE (CONST_VECTOR_ELT (x, i)) != CONST_DOUBLE)
3520       return 0;
3521   return 1;
3522 }
3523
3524 int
3525 logical_immediate_p (rtx op, enum machine_mode mode)
3526 {
3527   HOST_WIDE_INT val;
3528   unsigned char arr[16];
3529   int i, j;
3530
3531   gcc_assert (GET_CODE (op) == CONST_INT || GET_CODE (op) == CONST_DOUBLE
3532               || GET_CODE (op) == CONST_VECTOR);
3533
3534   if (GET_CODE (op) == CONST_VECTOR
3535       && !const_vector_immediate_p (op))
3536     return 0;
3537
3538   if (GET_MODE (op) != VOIDmode)
3539     mode = GET_MODE (op);
3540
3541   constant_to_array (mode, op, arr);
3542
3543   /* Check that bytes are repeated. */
3544   for (i = 4; i < 16; i += 4)
3545     for (j = 0; j < 4; j++)
3546       if (arr[j] != arr[i + j])
3547         return 0;
3548
3549   val = (arr[0] << 24) | (arr[1] << 16) | (arr[2] << 8) | arr[3];
3550   val = trunc_int_for_mode (val, SImode);
3551
3552   i = which_logical_immediate (val);
3553   return i != SPU_NONE && i != SPU_IOHL;
3554 }
3555
3556 int
3557 iohl_immediate_p (rtx op, enum machine_mode mode)
3558 {
3559   HOST_WIDE_INT val;
3560   unsigned char arr[16];
3561   int i, j;
3562
3563   gcc_assert (GET_CODE (op) == CONST_INT || GET_CODE (op) == CONST_DOUBLE
3564               || GET_CODE (op) == CONST_VECTOR);
3565
3566   if (GET_CODE (op) == CONST_VECTOR
3567       && !const_vector_immediate_p (op))
3568     return 0;
3569
3570   if (GET_MODE (op) != VOIDmode)
3571     mode = GET_MODE (op);
3572
3573   constant_to_array (mode, op, arr);
3574
3575   /* Check that bytes are repeated. */
3576   for (i = 4; i < 16; i += 4)
3577     for (j = 0; j < 4; j++)
3578       if (arr[j] != arr[i + j])
3579         return 0;
3580
3581   val = (arr[0] << 24) | (arr[1] << 16) | (arr[2] << 8) | arr[3];
3582   val = trunc_int_for_mode (val, SImode);
3583
3584   return val >= 0 && val <= 0xffff;
3585 }
3586
3587 int
3588 arith_immediate_p (rtx op, enum machine_mode mode,
3589                    HOST_WIDE_INT low, HOST_WIDE_INT high)
3590 {
3591   HOST_WIDE_INT val;
3592   unsigned char arr[16];
3593   int bytes, i, j;
3594
3595   gcc_assert (GET_CODE (op) == CONST_INT || GET_CODE (op) == CONST_DOUBLE
3596               || GET_CODE (op) == CONST_VECTOR);
3597
3598   if (GET_CODE (op) == CONST_VECTOR
3599       && !const_vector_immediate_p (op))
3600     return 0;
3601
3602   if (GET_MODE (op) != VOIDmode)
3603     mode = GET_MODE (op);
3604
3605   constant_to_array (mode, op, arr);
3606
3607   if (VECTOR_MODE_P (mode))
3608     mode = GET_MODE_INNER (mode);
3609
3610   bytes = GET_MODE_SIZE (mode);
3611   mode = mode_for_size (GET_MODE_BITSIZE (mode), MODE_INT, 0);
3612
3613   /* Check that bytes are repeated. */
3614   for (i = bytes; i < 16; i += bytes)
3615     for (j = 0; j < bytes; j++)
3616       if (arr[j] != arr[i + j])
3617         return 0;
3618
3619   val = arr[0];
3620   for (j = 1; j < bytes; j++)
3621     val = (val << 8) | arr[j];
3622
3623   val = trunc_int_for_mode (val, mode);
3624
3625   return val >= low && val <= high;
3626 }
3627
3628 /* TRUE when op is an immediate and an exact power of 2, and given that
3629    OP is 2^scale, scale >= LOW && scale <= HIGH.  When OP is a vector,
3630    all entries must be the same. */
3631 bool
3632 exp2_immediate_p (rtx op, enum machine_mode mode, int low, int high)
3633 {
3634   enum machine_mode int_mode;
3635   HOST_WIDE_INT val;
3636   unsigned char arr[16];
3637   int bytes, i, j;
3638
3639   gcc_assert (GET_CODE (op) == CONST_INT || GET_CODE (op) == CONST_DOUBLE
3640               || GET_CODE (op) == CONST_VECTOR);
3641
3642   if (GET_CODE (op) == CONST_VECTOR
3643       && !const_vector_immediate_p (op))
3644     return 0;
3645
3646   if (GET_MODE (op) != VOIDmode)
3647     mode = GET_MODE (op);
3648
3649   constant_to_array (mode, op, arr);
3650
3651   if (VECTOR_MODE_P (mode))
3652     mode = GET_MODE_INNER (mode);
3653
3654   bytes = GET_MODE_SIZE (mode);
3655   int_mode = mode_for_size (GET_MODE_BITSIZE (mode), MODE_INT, 0);
3656
3657   /* Check that bytes are repeated. */
3658   for (i = bytes; i < 16; i += bytes)
3659     for (j = 0; j < bytes; j++)
3660       if (arr[j] != arr[i + j])
3661         return 0;
3662
3663   val = arr[0];
3664   for (j = 1; j < bytes; j++)
3665     val = (val << 8) | arr[j];
3666
3667   val = trunc_int_for_mode (val, int_mode);
3668
3669   /* Currently, we only handle SFmode */
3670   gcc_assert (mode == SFmode);
3671   if (mode == SFmode)
3672     {
3673       int exp = (val >> 23) - 127;
3674       return val > 0 && (val & 0x007fffff) == 0
3675              &&  exp >= low && exp <= high;
3676     }
3677   return FALSE;
3678 }
3679
3680 /* Return true if X is a SYMBOL_REF to an __ea qualified variable.  */
3681
3682 static int
3683 ea_symbol_ref (rtx *px, void *data ATTRIBUTE_UNUSED)
3684 {
3685   rtx x = *px;
3686   tree decl;
3687
3688   if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == PLUS)
3689     {
3690       rtx plus = XEXP (x, 0);
3691       rtx op0 = XEXP (plus, 0);
3692       rtx op1 = XEXP (plus, 1);
3693       if (GET_CODE (op1) == CONST_INT)
3694         x = op0;
3695     }
3696
3697   return (GET_CODE (x) == SYMBOL_REF
3698           && (decl = SYMBOL_REF_DECL (x)) != 0
3699           && TREE_CODE (decl) == VAR_DECL
3700           && TYPE_ADDR_SPACE (TREE_TYPE (decl)));
3701 }
3702
3703 /* We accept:
3704    - any 32-bit constant (SImode, SFmode)
3705    - any constant that can be generated with fsmbi (any mode)
3706    - a 64-bit constant where the high and low bits are identical
3707      (DImode, DFmode)
3708    - a 128-bit constant where the four 32-bit words match.  */
3709 int
3710 spu_legitimate_constant_p (rtx x)
3711 {
3712   if (GET_CODE (x) == HIGH)
3713     x = XEXP (x, 0);
3714
3715   /* Reject any __ea qualified reference.  These can't appear in
3716      instructions but must be forced to the constant pool.  */
3717   if (for_each_rtx (&x, ea_symbol_ref, 0))
3718     return 0;
3719
3720   /* V4SI with all identical symbols is valid. */
3721   if (!flag_pic
3722       && GET_MODE (x) == V4SImode
3723       && (GET_CODE (CONST_VECTOR_ELT (x, 0)) == SYMBOL_REF
3724           || GET_CODE (CONST_VECTOR_ELT (x, 0)) == LABEL_REF
3725           || GET_CODE (CONST_VECTOR_ELT (x, 0)) == CONST))
3726     return CONST_VECTOR_ELT (x, 0) == CONST_VECTOR_ELT (x, 1)
3727            && CONST_VECTOR_ELT (x, 1) == CONST_VECTOR_ELT (x, 2)
3728            && CONST_VECTOR_ELT (x, 2) == CONST_VECTOR_ELT (x, 3);
3729
3730   if (GET_CODE (x) == CONST_VECTOR
3731       && !const_vector_immediate_p (x))
3732     return 0;
3733   return 1;
3734 }
3735
3736 /* Valid address are:
3737    - symbol_ref, label_ref, const
3738    - reg
3739    - reg + const_int, where const_int is 16 byte aligned
3740    - reg + reg, alignment doesn't matter
3741   The alignment matters in the reg+const case because lqd and stqd
3742   ignore the 4 least significant bits of the const.  We only care about
3743   16 byte modes because the expand phase will change all smaller MEM
3744   references to TImode.  */
3745 static bool
3746 spu_legitimate_address_p (enum machine_mode mode,
3747                           rtx x, bool reg_ok_strict)
3748 {
3749   int aligned = GET_MODE_SIZE (mode) >= 16;
3750   if (aligned
3751       && GET_CODE (x) == AND
3752       && GET_CODE (XEXP (x, 1)) == CONST_INT
3753       && INTVAL (XEXP (x, 1)) == (HOST_WIDE_INT) - 16)
3754     x = XEXP (x, 0);
3755   switch (GET_CODE (x))
3756     {
3757     case LABEL_REF:
3758       return !TARGET_LARGE_MEM;
3759
3760     case SYMBOL_REF:
3761     case CONST:
3762       /* Keep __ea references until reload so that spu_expand_mov can see them
3763          in MEMs.  */
3764       if (ea_symbol_ref (&x, 0))
3765         return !reload_in_progress && !reload_completed;
3766       return !TARGET_LARGE_MEM;
3767
3768     case CONST_INT:
3769       return INTVAL (x) >= 0 && INTVAL (x) <= 0x3ffff;
3770
3771     case SUBREG:
3772       x = XEXP (x, 0);
3773       if (REG_P (x))
3774         return 0;
3775
3776     case REG:
3777       return INT_REG_OK_FOR_BASE_P (x, reg_ok_strict);
3778
3779     case PLUS:
3780     case LO_SUM:
3781       {
3782         rtx op0 = XEXP (x, 0);
3783         rtx op1 = XEXP (x, 1);
3784         if (GET_CODE (op0) == SUBREG)
3785           op0 = XEXP (op0, 0);
3786         if (GET_CODE (op1) == SUBREG)
3787           op1 = XEXP (op1, 0);
3788         if (GET_CODE (op0) == REG
3789             && INT_REG_OK_FOR_BASE_P (op0, reg_ok_strict)
3790             && GET_CODE (op1) == CONST_INT
3791             && INTVAL (op1) >= -0x2000
3792             && INTVAL (op1) <= 0x1fff
3793             && (!aligned || (INTVAL (op1) & 15) == 0))
3794           return TRUE;
3795         if (GET_CODE (op0) == REG
3796             && INT_REG_OK_FOR_BASE_P (op0, reg_ok_strict)
3797             && GET_CODE (op1) == REG
3798             && INT_REG_OK_FOR_INDEX_P (op1, reg_ok_strict))
3799           return TRUE;
3800       }
3801       break;
3802
3803     default:
3804       break;
3805     }
3806   return FALSE;
3807 }
3808
3809 /* Like spu_legitimate_address_p, except with named addresses.  */
3810 static bool
3811 spu_addr_space_legitimate_address_p (enum machine_mode mode, rtx x,
3812                                      bool reg_ok_strict, addr_space_t as)
3813 {
3814   if (as == ADDR_SPACE_EA)
3815     return (REG_P (x) && (GET_MODE (x) == EAmode));
3816
3817   else if (as != ADDR_SPACE_GENERIC)
3818     gcc_unreachable ();
3819
3820   return spu_legitimate_address_p (mode, x, reg_ok_strict);
3821 }
3822
3823 /* When the address is reg + const_int, force the const_int into a
3824    register.  */
3825 rtx
3826 spu_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
3827                         enum machine_mode mode ATTRIBUTE_UNUSED)
3828 {
3829   rtx op0, op1;
3830   /* Make sure both operands are registers.  */
3831   if (GET_CODE (x) == PLUS)
3832     {
3833       op0 = XEXP (x, 0);
3834       op1 = XEXP (x, 1);
3835       if (ALIGNED_SYMBOL_REF_P (op0))
3836         {
3837           op0 = force_reg (Pmode, op0);
3838           mark_reg_pointer (op0, 128);
3839         }
3840       else if (GET_CODE (op0) != REG)
3841         op0 = force_reg (Pmode, op0);
3842       if (ALIGNED_SYMBOL_REF_P (op1))
3843         {
3844           op1 = force_reg (Pmode, op1);
3845           mark_reg_pointer (op1, 128);
3846         }
3847       else if (GET_CODE (op1) != REG)
3848         op1 = force_reg (Pmode, op1);
3849       x = gen_rtx_PLUS (Pmode, op0, op1);
3850     }
3851   return x;
3852 }
3853
3854 /* Like spu_legitimate_address, except with named address support.  */
3855 static rtx
3856 spu_addr_space_legitimize_address (rtx x, rtx oldx, enum machine_mode mode,
3857                                    addr_space_t as)
3858 {
3859   if (as != ADDR_SPACE_GENERIC)
3860     return x;
3861
3862   return spu_legitimize_address (x, oldx, mode);
3863 }
3864
3865 /* Handle an attribute requiring a FUNCTION_DECL; arguments as in
3866    struct attribute_spec.handler.  */
3867 static tree
3868 spu_handle_fndecl_attribute (tree * node,
3869                              tree name,
3870                              tree args ATTRIBUTE_UNUSED,
3871                              int flags ATTRIBUTE_UNUSED, bool * no_add_attrs)
3872 {
3873   if (TREE_CODE (*node) != FUNCTION_DECL)
3874     {
3875       warning (0, "%qE attribute only applies to functions",
3876                name);
3877       *no_add_attrs = true;
3878     }
3879
3880   return NULL_TREE;
3881 }
3882
3883 /* Handle the "vector" attribute.  */
3884 static tree
3885 spu_handle_vector_attribute (tree * node, tree name,
3886                              tree args ATTRIBUTE_UNUSED,
3887                              int flags ATTRIBUTE_UNUSED, bool * no_add_attrs)
3888 {
3889   tree type = *node, result = NULL_TREE;
3890   enum machine_mode mode;
3891   int unsigned_p;
3892
3893   while (POINTER_TYPE_P (type)
3894          || TREE_CODE (type) == FUNCTION_TYPE
3895          || TREE_CODE (type) == METHOD_TYPE || TREE_CODE (type) == ARRAY_TYPE)
3896     type = TREE_TYPE (type);
3897
3898   mode = TYPE_MODE (type);
3899
3900   unsigned_p = TYPE_UNSIGNED (type);
3901   switch (mode)
3902     {
3903     case DImode:
3904       result = (unsigned_p ? unsigned_V2DI_type_node : V2DI_type_node);
3905       break;
3906     case SImode:
3907       result = (unsigned_p ? unsigned_V4SI_type_node : V4SI_type_node);
3908       break;
3909     case HImode:
3910       result = (unsigned_p ? unsigned_V8HI_type_node : V8HI_type_node);
3911       break;
3912     case QImode:
3913       result = (unsigned_p ? unsigned_V16QI_type_node : V16QI_type_node);
3914       break;
3915     case SFmode:
3916       result = V4SF_type_node;
3917       break;
3918     case DFmode:
3919       result = V2DF_type_node;
3920       break;
3921     default:
3922       break;
3923     }
3924
3925   /* Propagate qualifiers attached to the element type
3926      onto the vector type.  */
3927   if (result && result != type && TYPE_QUALS (type))
3928     result = build_qualified_type (result, TYPE_QUALS (type));
3929
3930   *no_add_attrs = true;         /* No need to hang on to the attribute.  */
3931
3932   if (!result)
3933     warning (0, "%qE attribute ignored", name);
3934   else
3935     *node = lang_hooks.types.reconstruct_complex_type (*node, result);
3936
3937   return NULL_TREE;
3938 }
3939
3940 /* Return nonzero if FUNC is a naked function.  */
3941 static int
3942 spu_naked_function_p (tree func)
3943 {
3944   tree a;
3945
3946   if (TREE_CODE (func) != FUNCTION_DECL)
3947     abort ();
3948
3949   a = lookup_attribute ("naked", DECL_ATTRIBUTES (func));
3950   return a != NULL_TREE;
3951 }
3952
3953 int
3954 spu_initial_elimination_offset (int from, int to)
3955 {
3956   int saved_regs_size = spu_saved_regs_size ();
3957   int sp_offset = 0;
3958   if (!current_function_is_leaf || crtl->outgoing_args_size
3959       || get_frame_size () || saved_regs_size)
3960     sp_offset = STACK_POINTER_OFFSET;
3961   if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
3962     return get_frame_size () + crtl->outgoing_args_size + sp_offset;
3963   else if (from == FRAME_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM)
3964     return get_frame_size ();
3965   else if (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
3966     return sp_offset + crtl->outgoing_args_size
3967       + get_frame_size () + saved_regs_size + STACK_POINTER_OFFSET;
3968   else if (from == ARG_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM)
3969     return get_frame_size () + saved_regs_size + sp_offset;
3970   else
3971     gcc_unreachable ();
3972 }
3973
3974 rtx
3975 spu_function_value (const_tree type, const_tree func ATTRIBUTE_UNUSED)
3976 {
3977   enum machine_mode mode = TYPE_MODE (type);
3978   int byte_size = ((mode == BLKmode)
3979                    ? int_size_in_bytes (type) : GET_MODE_SIZE (mode));
3980
3981   /* Make sure small structs are left justified in a register. */
3982   if ((mode == BLKmode || (type && AGGREGATE_TYPE_P (type)))
3983       && byte_size <= UNITS_PER_WORD * MAX_REGISTER_RETURN && byte_size > 0)
3984     {
3985       enum machine_mode smode;
3986       rtvec v;
3987       int i;
3988       int nregs = (byte_size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
3989       int n = byte_size / UNITS_PER_WORD;
3990       v = rtvec_alloc (nregs);
3991       for (i = 0; i < n; i++)
3992         {
3993           RTVEC_ELT (v, i) = gen_rtx_EXPR_LIST (VOIDmode,
3994                                                 gen_rtx_REG (TImode,
3995                                                              FIRST_RETURN_REGNUM
3996                                                              + i),
3997                                                 GEN_INT (UNITS_PER_WORD * i));
3998           byte_size -= UNITS_PER_WORD;
3999         }
4000
4001       if (n < nregs)
4002         {
4003           if (byte_size < 4)
4004             byte_size = 4;
4005           smode =
4006             smallest_mode_for_size (byte_size * BITS_PER_UNIT, MODE_INT);
4007           RTVEC_ELT (v, n) =
4008             gen_rtx_EXPR_LIST (VOIDmode,
4009                                gen_rtx_REG (smode, FIRST_RETURN_REGNUM + n),
4010                                GEN_INT (UNITS_PER_WORD * n));
4011         }
4012       return gen_rtx_PARALLEL (mode, v);
4013     }
4014   return gen_rtx_REG (mode, FIRST_RETURN_REGNUM);
4015 }
4016
4017 static rtx
4018 spu_function_arg (CUMULATIVE_ARGS *cum,
4019                   enum machine_mode mode,
4020                   const_tree type, bool named ATTRIBUTE_UNUSED)
4021 {
4022   int byte_size;
4023
4024   if (*cum >= MAX_REGISTER_ARGS)
4025     return 0;
4026
4027   byte_size = ((mode == BLKmode)
4028                ? int_size_in_bytes (type) : GET_MODE_SIZE (mode));
4029
4030   /* The ABI does not allow parameters to be passed partially in
4031      reg and partially in stack. */
4032   if ((*cum + (byte_size + 15) / 16) > MAX_REGISTER_ARGS)
4033     return 0;
4034
4035   /* Make sure small structs are left justified in a register. */
4036   if ((mode == BLKmode || (type && AGGREGATE_TYPE_P (type)))
4037       && byte_size < UNITS_PER_WORD && byte_size > 0)
4038     {
4039       enum machine_mode smode;
4040       rtx gr_reg;
4041       if (byte_size < 4)
4042         byte_size = 4;
4043       smode = smallest_mode_for_size (byte_size * BITS_PER_UNIT, MODE_INT);
4044       gr_reg = gen_rtx_EXPR_LIST (VOIDmode,
4045                                   gen_rtx_REG (smode, FIRST_ARG_REGNUM + *cum),
4046                                   const0_rtx);
4047       return gen_rtx_PARALLEL (mode, gen_rtvec (1, gr_reg));
4048     }
4049   else
4050     return gen_rtx_REG (mode, FIRST_ARG_REGNUM + *cum);
4051 }
4052
4053 static void
4054 spu_function_arg_advance (CUMULATIVE_ARGS * cum, enum machine_mode mode,
4055                           const_tree type, bool named ATTRIBUTE_UNUSED)
4056 {
4057   *cum += (type && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST
4058            ? 1
4059            : mode == BLKmode
4060            ? ((int_size_in_bytes (type) + 15) / 16)
4061            : mode == VOIDmode
4062            ? 1
4063            : HARD_REGNO_NREGS (cum, mode));
4064 }
4065
4066 /* Variable sized types are passed by reference.  */
4067 static bool
4068 spu_pass_by_reference (CUMULATIVE_ARGS * cum ATTRIBUTE_UNUSED,
4069                        enum machine_mode mode ATTRIBUTE_UNUSED,
4070                        const_tree type, bool named ATTRIBUTE_UNUSED)
4071 {
4072   return type && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST;
4073 }
4074 \f
4075
4076 /* Var args. */
4077
4078 /* Create and return the va_list datatype.
4079
4080    On SPU, va_list is an array type equivalent to
4081
4082       typedef struct __va_list_tag
4083         {
4084             void *__args __attribute__((__aligned(16)));
4085             void *__skip __attribute__((__aligned(16)));
4086             
4087         } va_list[1];
4088
4089    where __args points to the arg that will be returned by the next
4090    va_arg(), and __skip points to the previous stack frame such that
4091    when __args == __skip we should advance __args by 32 bytes. */
4092 static tree
4093 spu_build_builtin_va_list (void)
4094 {
4095   tree f_args, f_skip, record, type_decl;
4096   bool owp;
4097
4098   record = (*lang_hooks.types.make_type) (RECORD_TYPE);
4099
4100   type_decl =
4101     build_decl (BUILTINS_LOCATION,
4102                 TYPE_DECL, get_identifier ("__va_list_tag"), record);
4103
4104   f_args = build_decl (BUILTINS_LOCATION,
4105                        FIELD_DECL, get_identifier ("__args"), ptr_type_node);
4106   f_skip = build_decl (BUILTINS_LOCATION,
4107                        FIELD_DECL, get_identifier ("__skip"), ptr_type_node);
4108
4109   DECL_FIELD_CONTEXT (f_args) = record;
4110   DECL_ALIGN (f_args) = 128;
4111   DECL_USER_ALIGN (f_args) = 1;
4112
4113   DECL_FIELD_CONTEXT (f_skip) = record;
4114   DECL_ALIGN (f_skip) = 128;
4115   DECL_USER_ALIGN (f_skip) = 1;
4116
4117   TYPE_STUB_DECL (record) = type_decl;
4118   TYPE_NAME (record) = type_decl;
4119   TYPE_FIELDS (record) = f_args;
4120   DECL_CHAIN (f_args) = f_skip;
4121
4122   /* We know this is being padded and we want it too.  It is an internal
4123      type so hide the warnings from the user. */
4124   owp = warn_padded;
4125   warn_padded = false;
4126
4127   layout_type (record);
4128
4129   warn_padded = owp;
4130
4131   /* The correct type is an array type of one element.  */
4132   return build_array_type (record, build_index_type (size_zero_node));
4133 }
4134
4135 /* Implement va_start by filling the va_list structure VALIST.
4136    NEXTARG points to the first anonymous stack argument.
4137
4138    The following global variables are used to initialize
4139    the va_list structure:
4140
4141      crtl->args.info;
4142        the CUMULATIVE_ARGS for this function
4143
4144      crtl->args.arg_offset_rtx:
4145        holds the offset of the first anonymous stack argument
4146        (relative to the virtual arg pointer).  */
4147
4148 static void
4149 spu_va_start (tree valist, rtx nextarg)
4150 {
4151   tree f_args, f_skip;
4152   tree args, skip, t;
4153
4154   f_args = TYPE_FIELDS (TREE_TYPE (va_list_type_node));
4155   f_skip = DECL_CHAIN (f_args);
4156
4157   valist = build_simple_mem_ref (valist);
4158   args =
4159     build3 (COMPONENT_REF, TREE_TYPE (f_args), valist, f_args, NULL_TREE);
4160   skip =
4161     build3 (COMPONENT_REF, TREE_TYPE (f_skip), valist, f_skip, NULL_TREE);
4162
4163   /* Find the __args area.  */
4164   t = make_tree (TREE_TYPE (args), nextarg);
4165   if (crtl->args.pretend_args_size > 0)
4166     t = build2 (POINTER_PLUS_EXPR, TREE_TYPE (args), t,
4167                 size_int (-STACK_POINTER_OFFSET));
4168   t = build2 (MODIFY_EXPR, TREE_TYPE (args), args, t);
4169   TREE_SIDE_EFFECTS (t) = 1;
4170   expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
4171
4172   /* Find the __skip area.  */
4173   t = make_tree (TREE_TYPE (skip), virtual_incoming_args_rtx);
4174   t = build2 (POINTER_PLUS_EXPR, TREE_TYPE (skip), t,
4175               size_int (crtl->args.pretend_args_size
4176                          - STACK_POINTER_OFFSET));
4177   t = build2 (MODIFY_EXPR, TREE_TYPE (skip), skip, t);
4178   TREE_SIDE_EFFECTS (t) = 1;
4179   expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
4180 }
4181
4182 /* Gimplify va_arg by updating the va_list structure 
4183    VALIST as required to retrieve an argument of type
4184    TYPE, and returning that argument. 
4185    
4186    ret = va_arg(VALIST, TYPE);
4187
4188    generates code equivalent to:
4189    
4190     paddedsize = (sizeof(TYPE) + 15) & -16;
4191     if (VALIST.__args + paddedsize > VALIST.__skip
4192         && VALIST.__args <= VALIST.__skip)
4193       addr = VALIST.__skip + 32;
4194     else
4195       addr = VALIST.__args;
4196     VALIST.__args = addr + paddedsize;
4197     ret = *(TYPE *)addr;
4198  */
4199 static tree
4200 spu_gimplify_va_arg_expr (tree valist, tree type, gimple_seq * pre_p,
4201                           gimple_seq * post_p ATTRIBUTE_UNUSED)
4202 {
4203   tree f_args, f_skip;
4204   tree args, skip;
4205   HOST_WIDE_INT size, rsize;
4206   tree paddedsize, addr, tmp;
4207   bool pass_by_reference_p;
4208
4209   f_args = TYPE_FIELDS (TREE_TYPE (va_list_type_node));
4210   f_skip = DECL_CHAIN (f_args);
4211
4212   valist = build_simple_mem_ref (valist);
4213   args =
4214     build3 (COMPONENT_REF, TREE_TYPE (f_args), valist, f_args, NULL_TREE);
4215   skip =
4216     build3 (COMPONENT_REF, TREE_TYPE (f_skip), valist, f_skip, NULL_TREE);
4217
4218   addr = create_tmp_var (ptr_type_node, "va_arg");
4219
4220   /* if an object is dynamically sized, a pointer to it is passed
4221      instead of the object itself. */
4222   pass_by_reference_p = spu_pass_by_reference (NULL, TYPE_MODE (type), type,
4223                                                false);
4224   if (pass_by_reference_p)
4225     type = build_pointer_type (type);
4226   size = int_size_in_bytes (type);
4227   rsize = ((size + UNITS_PER_WORD - 1) / UNITS_PER_WORD) * UNITS_PER_WORD;
4228
4229   /* build conditional expression to calculate addr. The expression
4230      will be gimplified later. */
4231   paddedsize = size_int (rsize);
4232   tmp = build2 (POINTER_PLUS_EXPR, ptr_type_node, unshare_expr (args), paddedsize);
4233   tmp = build2 (TRUTH_AND_EXPR, boolean_type_node,
4234                 build2 (GT_EXPR, boolean_type_node, tmp, unshare_expr (skip)),
4235                 build2 (LE_EXPR, boolean_type_node, unshare_expr (args),
4236                 unshare_expr (skip)));
4237
4238   tmp = build3 (COND_EXPR, ptr_type_node, tmp,
4239                 build2 (POINTER_PLUS_EXPR, ptr_type_node, unshare_expr (skip),
4240                         size_int (32)), unshare_expr (args));
4241
4242   gimplify_assign (addr, tmp, pre_p);
4243
4244   /* update VALIST.__args */
4245   tmp = build2 (POINTER_PLUS_EXPR, ptr_type_node, addr, paddedsize);
4246   gimplify_assign (unshare_expr (args), tmp, pre_p);
4247
4248   addr = fold_convert (build_pointer_type_for_mode (type, ptr_mode, true),
4249                        addr);
4250
4251   if (pass_by_reference_p)
4252     addr = build_va_arg_indirect_ref (addr);
4253
4254   return build_va_arg_indirect_ref (addr);
4255 }
4256
4257 /* Save parameter registers starting with the register that corresponds
4258    to the first unnamed parameters.  If the first unnamed parameter is
4259    in the stack then save no registers.  Set pretend_args_size to the
4260    amount of space needed to save the registers. */
4261 void
4262 spu_setup_incoming_varargs (CUMULATIVE_ARGS * cum, enum machine_mode mode,
4263                             tree type, int *pretend_size, int no_rtl)
4264 {
4265   if (!no_rtl)
4266     {
4267       rtx tmp;
4268       int regno;
4269       int offset;
4270       int ncum = *cum;
4271
4272       /* cum currently points to the last named argument, we want to
4273          start at the next argument. */
4274       spu_function_arg_advance (&ncum, mode, type, true);
4275
4276       offset = -STACK_POINTER_OFFSET;
4277       for (regno = ncum; regno < MAX_REGISTER_ARGS; regno++)
4278         {
4279           tmp = gen_frame_mem (V4SImode,
4280                                plus_constant (virtual_incoming_args_rtx,
4281                                               offset));
4282           emit_move_insn (tmp,
4283                           gen_rtx_REG (V4SImode, FIRST_ARG_REGNUM + regno));
4284           offset += 16;
4285         }
4286       *pretend_size = offset + STACK_POINTER_OFFSET;
4287     }
4288 }
4289 \f
4290 static void
4291 spu_conditional_register_usage (void)
4292 {
4293   if (flag_pic)
4294     {
4295       fixed_regs[PIC_OFFSET_TABLE_REGNUM] = 1;
4296       call_used_regs[PIC_OFFSET_TABLE_REGNUM] = 1;
4297     }
4298 }
4299
4300 /* This is called any time we inspect the alignment of a register for
4301    addresses.  */
4302 static int
4303 reg_aligned_for_addr (rtx x)
4304 {
4305   int regno =
4306     REGNO (x) < FIRST_PSEUDO_REGISTER ? ORIGINAL_REGNO (x) : REGNO (x);
4307   return REGNO_POINTER_ALIGN (regno) >= 128;
4308 }
4309
4310 /* Encode symbol attributes (local vs. global, tls model) of a SYMBOL_REF
4311    into its SYMBOL_REF_FLAGS.  */
4312 static void
4313 spu_encode_section_info (tree decl, rtx rtl, int first)
4314 {
4315   default_encode_section_info (decl, rtl, first);
4316
4317   /* If a variable has a forced alignment to < 16 bytes, mark it with
4318      SYMBOL_FLAG_ALIGN1.  */
4319   if (TREE_CODE (decl) == VAR_DECL
4320       && DECL_USER_ALIGN (decl) && DECL_ALIGN (decl) < 128)
4321     SYMBOL_REF_FLAGS (XEXP (rtl, 0)) |= SYMBOL_FLAG_ALIGN1;
4322 }
4323
4324 /* Return TRUE if we are certain the mem refers to a complete object
4325    which is both 16-byte aligned and padded to a 16-byte boundary.  This
4326    would make it safe to store with a single instruction. 
4327    We guarantee the alignment and padding for static objects by aligning
4328    all of them to 16-bytes. (DATA_ALIGNMENT and CONSTANT_ALIGNMENT.)
4329    FIXME: We currently cannot guarantee this for objects on the stack
4330    because assign_parm_setup_stack calls assign_stack_local with the
4331    alignment of the parameter mode and in that case the alignment never
4332    gets adjusted by LOCAL_ALIGNMENT. */
4333 static int
4334 store_with_one_insn_p (rtx mem)
4335 {
4336   enum machine_mode mode = GET_MODE (mem);
4337   rtx addr = XEXP (mem, 0);
4338   if (mode == BLKmode)
4339     return 0;
4340   if (GET_MODE_SIZE (mode) >= 16)
4341     return 1;
4342   /* Only static objects. */
4343   if (GET_CODE (addr) == SYMBOL_REF)
4344     {
4345       /* We use the associated declaration to make sure the access is
4346          referring to the whole object.
4347          We check both MEM_EXPR and and SYMBOL_REF_DECL.  I'm not sure
4348          if it is necessary.  Will there be cases where one exists, and
4349          the other does not?  Will there be cases where both exist, but
4350          have different types?  */
4351       tree decl = MEM_EXPR (mem);
4352       if (decl
4353           && TREE_CODE (decl) == VAR_DECL
4354           && GET_MODE (mem) == TYPE_MODE (TREE_TYPE (decl)))
4355         return 1;
4356       decl = SYMBOL_REF_DECL (addr);
4357       if (decl
4358           && TREE_CODE (decl) == VAR_DECL
4359           && GET_MODE (mem) == TYPE_MODE (TREE_TYPE (decl)))
4360         return 1;
4361     }
4362   return 0;
4363 }
4364
4365 /* Return 1 when the address is not valid for a simple load and store as
4366    required by the '_mov*' patterns.   We could make this less strict
4367    for loads, but we prefer mem's to look the same so they are more
4368    likely to be merged.  */
4369 static int
4370 address_needs_split (rtx mem)
4371 {
4372   if (GET_MODE_SIZE (GET_MODE (mem)) < 16
4373       && (GET_MODE_SIZE (GET_MODE (mem)) < 4
4374           || !(store_with_one_insn_p (mem)
4375                || mem_is_padded_component_ref (mem))))
4376     return 1;
4377
4378   return 0;
4379 }
4380
4381 static GTY(()) rtx cache_fetch;           /* __cache_fetch function */
4382 static GTY(()) rtx cache_fetch_dirty;     /* __cache_fetch_dirty function */
4383 static alias_set_type ea_alias_set = -1;  /* alias set for __ea memory */
4384
4385 /* MEM is known to be an __ea qualified memory access.  Emit a call to
4386    fetch the ppu memory to local store, and return its address in local
4387    store.  */
4388
4389 static void
4390 ea_load_store (rtx mem, bool is_store, rtx ea_addr, rtx data_addr)
4391 {
4392   if (is_store)
4393     {
4394       rtx ndirty = GEN_INT (GET_MODE_SIZE (GET_MODE (mem)));
4395       if (!cache_fetch_dirty)
4396         cache_fetch_dirty = init_one_libfunc ("__cache_fetch_dirty");
4397       emit_library_call_value (cache_fetch_dirty, data_addr, LCT_NORMAL, Pmode,
4398                                2, ea_addr, EAmode, ndirty, SImode);
4399     }
4400   else
4401     {
4402       if (!cache_fetch)
4403         cache_fetch = init_one_libfunc ("__cache_fetch");
4404       emit_library_call_value (cache_fetch, data_addr, LCT_NORMAL, Pmode,
4405                                1, ea_addr, EAmode);
4406     }
4407 }
4408
4409 /* Like ea_load_store, but do the cache tag comparison and, for stores,
4410    dirty bit marking, inline.
4411
4412    The cache control data structure is an array of
4413
4414    struct __cache_tag_array
4415      {
4416         unsigned int tag_lo[4];
4417         unsigned int tag_hi[4];
4418         void *data_pointer[4];
4419         int reserved[4];
4420         vector unsigned short dirty_bits[4];
4421      }  */
4422
4423 static void
4424 ea_load_store_inline (rtx mem, bool is_store, rtx ea_addr, rtx data_addr)
4425 {
4426   rtx ea_addr_si;
4427   HOST_WIDE_INT v;
4428   rtx tag_size_sym = gen_rtx_SYMBOL_REF (Pmode, "__cache_tag_array_size");
4429   rtx tag_arr_sym = gen_rtx_SYMBOL_REF (Pmode, "__cache_tag_array");
4430   rtx index_mask = gen_reg_rtx (SImode);
4431   rtx tag_arr = gen_reg_rtx (Pmode);
4432   rtx splat_mask = gen_reg_rtx (TImode);
4433   rtx splat = gen_reg_rtx (V4SImode);
4434   rtx splat_hi = NULL_RTX;
4435   rtx tag_index = gen_reg_rtx (Pmode);
4436   rtx block_off = gen_reg_rtx (SImode);
4437   rtx tag_addr = gen_reg_rtx (Pmode);
4438   rtx tag = gen_reg_rtx (V4SImode);
4439   rtx cache_tag = gen_reg_rtx (V4SImode);
4440   rtx cache_tag_hi = NULL_RTX;
4441   rtx cache_ptrs = gen_reg_rtx (TImode);
4442   rtx cache_ptrs_si = gen_reg_rtx (SImode);
4443   rtx tag_equal = gen_reg_rtx (V4SImode);
4444   rtx tag_equal_hi = NULL_RTX;
4445   rtx tag_eq_pack = gen_reg_rtx (V4SImode);
4446   rtx tag_eq_pack_si = gen_reg_rtx (SImode);
4447   rtx eq_index = gen_reg_rtx (SImode);
4448   rtx bcomp, hit_label, hit_ref, cont_label, insn;
4449
4450   if (spu_ea_model != 32)
4451     {
4452       splat_hi = gen_reg_rtx (V4SImode);
4453       cache_tag_hi = gen_reg_rtx (V4SImode);
4454       tag_equal_hi = gen_reg_rtx (V4SImode);
4455     }
4456
4457   emit_move_insn (index_mask, plus_constant (tag_size_sym, -128));
4458   emit_move_insn (tag_arr, tag_arr_sym);
4459   v = 0x0001020300010203LL;
4460   emit_move_insn (splat_mask, immed_double_const (v, v, TImode));
4461   ea_addr_si = ea_addr;
4462   if (spu_ea_model != 32)
4463     ea_addr_si = convert_to_mode (SImode, ea_addr, 1);
4464
4465   /* tag_index = ea_addr & (tag_array_size - 128)  */
4466   emit_insn (gen_andsi3 (tag_index, ea_addr_si, index_mask));
4467
4468   /* splat ea_addr to all 4 slots.  */
4469   emit_insn (gen_shufb (splat, ea_addr_si, ea_addr_si, splat_mask));
4470   /* Similarly for high 32 bits of ea_addr.  */
4471   if (spu_ea_model != 32)
4472     emit_insn (gen_shufb (splat_hi, ea_addr, ea_addr, splat_mask));
4473
4474   /* block_off = ea_addr & 127  */
4475   emit_insn (gen_andsi3 (block_off, ea_addr_si, spu_const (SImode, 127)));
4476
4477   /* tag_addr = tag_arr + tag_index  */
4478   emit_insn (gen_addsi3 (tag_addr, tag_arr, tag_index));
4479
4480   /* Read cache tags.  */
4481   emit_move_insn (cache_tag, gen_rtx_MEM (V4SImode, tag_addr));
4482   if (spu_ea_model != 32)
4483     emit_move_insn (cache_tag_hi, gen_rtx_MEM (V4SImode,
4484                                                plus_constant (tag_addr, 16)));
4485
4486   /* tag = ea_addr & -128  */
4487   emit_insn (gen_andv4si3 (tag, splat, spu_const (V4SImode, -128)));
4488
4489   /* Read all four cache data pointers.  */
4490   emit_move_insn (cache_ptrs, gen_rtx_MEM (TImode,
4491                                            plus_constant (tag_addr, 32)));
4492
4493   /* Compare tags.  */
4494   emit_insn (gen_ceq_v4si (tag_equal, tag, cache_tag));
4495   if (spu_ea_model != 32)
4496     {
4497       emit_insn (gen_ceq_v4si (tag_equal_hi, splat_hi, cache_tag_hi));
4498       emit_insn (gen_andv4si3 (tag_equal, tag_equal, tag_equal_hi));
4499     }
4500
4501   /* At most one of the tags compare equal, so tag_equal has one
4502      32-bit slot set to all 1's, with the other slots all zero.
4503      gbb picks off low bit from each byte in the 128-bit registers,
4504      so tag_eq_pack is one of 0xf000, 0x0f00, 0x00f0, 0x000f, assuming
4505      we have a hit.  */
4506   emit_insn (gen_spu_gbb (tag_eq_pack, spu_gen_subreg (V16QImode, tag_equal)));
4507   emit_insn (gen_spu_convert (tag_eq_pack_si, tag_eq_pack));
4508
4509   /* So counting leading zeros will set eq_index to 16, 20, 24 or 28.  */
4510   emit_insn (gen_clzsi2 (eq_index, tag_eq_pack_si));
4511
4512   /* Allowing us to rotate the corresponding cache data pointer to slot0.
4513      (rotating eq_index mod 16 bytes).  */
4514   emit_insn (gen_rotqby_ti (cache_ptrs, cache_ptrs, eq_index));
4515   emit_insn (gen_spu_convert (cache_ptrs_si, cache_ptrs));
4516
4517   /* Add block offset to form final data address.  */
4518   emit_insn (gen_addsi3 (data_addr, cache_ptrs_si, block_off));
4519
4520   /* Check that we did hit.  */
4521   hit_label = gen_label_rtx ();
4522   hit_ref = gen_rtx_LABEL_REF (VOIDmode, hit_label);
4523   bcomp = gen_rtx_NE (SImode, tag_eq_pack_si, const0_rtx);
4524   insn = emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx,
4525                                       gen_rtx_IF_THEN_ELSE (VOIDmode, bcomp,
4526                                                             hit_ref, pc_rtx)));
4527   /* Say that this branch is very likely to happen.  */
4528   v = REG_BR_PROB_BASE - REG_BR_PROB_BASE / 100 - 1;
4529   add_reg_note (insn, REG_BR_PROB, GEN_INT (v));
4530
4531   ea_load_store (mem, is_store, ea_addr, data_addr);
4532   cont_label = gen_label_rtx ();
4533   emit_jump_insn (gen_jump (cont_label));
4534   emit_barrier ();
4535
4536   emit_label (hit_label);
4537
4538   if (is_store)
4539     {
4540       HOST_WIDE_INT v_hi;
4541       rtx dirty_bits = gen_reg_rtx (TImode);
4542       rtx dirty_off = gen_reg_rtx (SImode);
4543       rtx dirty_128 = gen_reg_rtx (TImode);
4544       rtx neg_block_off = gen_reg_rtx (SImode);
4545
4546       /* Set up mask with one dirty bit per byte of the mem we are
4547          writing, starting from top bit.  */
4548       v_hi = v = -1;
4549       v <<= (128 - GET_MODE_SIZE (GET_MODE (mem))) & 63;
4550       if ((128 - GET_MODE_SIZE (GET_MODE (mem))) >= 64)
4551         {
4552           v_hi = v;
4553           v = 0;
4554         }
4555       emit_move_insn (dirty_bits, immed_double_const (v, v_hi, TImode));
4556
4557       /* Form index into cache dirty_bits.  eq_index is one of
4558          0x10, 0x14, 0x18 or 0x1c.  Multiplying by 4 gives us
4559          0x40, 0x50, 0x60 or 0x70 which just happens to be the
4560          offset to each of the four dirty_bits elements.  */
4561       emit_insn (gen_ashlsi3 (dirty_off, eq_index, spu_const (SImode, 2)));
4562
4563       emit_insn (gen_spu_lqx (dirty_128, tag_addr, dirty_off));
4564
4565       /* Rotate bit mask to proper bit.  */
4566       emit_insn (gen_negsi2 (neg_block_off, block_off));
4567       emit_insn (gen_rotqbybi_ti (dirty_bits, dirty_bits, neg_block_off));
4568       emit_insn (gen_rotqbi_ti (dirty_bits, dirty_bits, neg_block_off));
4569
4570       /* Or in the new dirty bits.  */
4571       emit_insn (gen_iorti3 (dirty_128, dirty_bits, dirty_128));
4572
4573       /* Store.  */
4574       emit_insn (gen_spu_stqx (dirty_128, tag_addr, dirty_off));
4575     }
4576
4577   emit_label (cont_label);
4578 }
4579
4580 static rtx
4581 expand_ea_mem (rtx mem, bool is_store)
4582 {
4583   rtx ea_addr;
4584   rtx data_addr = gen_reg_rtx (Pmode);
4585   rtx new_mem;
4586
4587   ea_addr = force_reg (EAmode, XEXP (mem, 0));
4588   if (optimize_size || optimize == 0)
4589     ea_load_store (mem, is_store, ea_addr, data_addr);
4590   else
4591     ea_load_store_inline (mem, is_store, ea_addr, data_addr);
4592
4593   if (ea_alias_set == -1)
4594     ea_alias_set = new_alias_set ();
4595
4596   /* We generate a new MEM RTX to refer to the copy of the data
4597      in the cache.  We do not copy memory attributes (except the
4598      alignment) from the original MEM, as they may no longer apply
4599      to the cache copy.  */
4600   new_mem = gen_rtx_MEM (GET_MODE (mem), data_addr);
4601   set_mem_alias_set (new_mem, ea_alias_set);
4602   set_mem_align (new_mem, MIN (MEM_ALIGN (mem), 128 * 8));
4603
4604   return new_mem;
4605 }
4606
4607 int
4608 spu_expand_mov (rtx * ops, enum machine_mode mode)
4609 {
4610   if (GET_CODE (ops[0]) == SUBREG && !valid_subreg (ops[0]))
4611     abort ();
4612
4613   if (GET_CODE (ops[1]) == SUBREG && !valid_subreg (ops[1]))
4614     {
4615       rtx from = SUBREG_REG (ops[1]);
4616       enum machine_mode imode = int_mode_for_mode (GET_MODE (from));
4617
4618       gcc_assert (GET_MODE_CLASS (mode) == MODE_INT
4619                   && GET_MODE_CLASS (imode) == MODE_INT
4620                   && subreg_lowpart_p (ops[1]));
4621
4622       if (GET_MODE_SIZE (imode) < 4)
4623         imode = SImode;
4624       if (imode != GET_MODE (from))
4625         from = gen_rtx_SUBREG (imode, from, 0);
4626
4627       if (GET_MODE_SIZE (mode) < GET_MODE_SIZE (imode))
4628         {
4629           enum insn_code icode = convert_optab_handler (trunc_optab,
4630                                                         mode, imode);
4631           emit_insn (GEN_FCN (icode) (ops[0], from));
4632         }
4633       else
4634         emit_insn (gen_extend_insn (ops[0], from, mode, imode, 1));
4635       return 1;
4636     }
4637
4638   /* At least one of the operands needs to be a register. */
4639   if ((reload_in_progress | reload_completed) == 0
4640       && !register_operand (ops[0], mode) && !register_operand (ops[1], mode))
4641     {
4642       rtx temp = force_reg (mode, ops[1]);
4643       emit_move_insn (ops[0], temp);
4644       return 1;
4645     }
4646   if (reload_in_progress || reload_completed)
4647     {
4648       if (CONSTANT_P (ops[1]))
4649         return spu_split_immediate (ops);
4650       return 0;
4651     }
4652
4653   /* Catch the SImode immediates greater than 0x7fffffff, and sign
4654      extend them. */
4655   if (GET_CODE (ops[1]) == CONST_INT)
4656     {
4657       HOST_WIDE_INT val = trunc_int_for_mode (INTVAL (ops[1]), mode);
4658       if (val != INTVAL (ops[1]))
4659         {
4660           emit_move_insn (ops[0], GEN_INT (val));
4661           return 1;
4662         }
4663     }
4664   if (MEM_P (ops[0]))
4665     {
4666       if (MEM_ADDR_SPACE (ops[0]))
4667         ops[0] = expand_ea_mem (ops[0], true);
4668       return spu_split_store (ops);
4669     }
4670   if (MEM_P (ops[1]))
4671     {
4672       if (MEM_ADDR_SPACE (ops[1]))
4673         ops[1] = expand_ea_mem (ops[1], false);
4674       return spu_split_load (ops);
4675     }
4676
4677   return 0;
4678 }
4679
4680 static void
4681 spu_convert_move (rtx dst, rtx src)
4682 {
4683   enum machine_mode mode = GET_MODE (dst);
4684   enum machine_mode int_mode = mode_for_size (GET_MODE_BITSIZE (mode), MODE_INT, 0);
4685   rtx reg;
4686   gcc_assert (GET_MODE (src) == TImode);
4687   reg = int_mode != mode ? gen_reg_rtx (int_mode) : dst;
4688   emit_insn (gen_rtx_SET (VOIDmode, reg,
4689                gen_rtx_TRUNCATE (int_mode,
4690                  gen_rtx_LSHIFTRT (TImode, src,
4691                    GEN_INT (int_mode == DImode ? 64 : 96)))));
4692   if (int_mode != mode)
4693     {
4694       reg = simplify_gen_subreg (mode, reg, int_mode, 0);
4695       emit_move_insn (dst, reg);
4696     }
4697 }
4698
4699 /* Load TImode values into DST0 and DST1 (when it is non-NULL) using
4700    the address from SRC and SRC+16.  Return a REG or CONST_INT that 
4701    specifies how many bytes to rotate the loaded registers, plus any
4702    extra from EXTRA_ROTQBY.  The address and rotate amounts are
4703    normalized to improve merging of loads and rotate computations. */
4704 static rtx
4705 spu_expand_load (rtx dst0, rtx dst1, rtx src, int extra_rotby)
4706 {
4707   rtx addr = XEXP (src, 0);
4708   rtx p0, p1, rot, addr0, addr1;
4709   int rot_amt;
4710
4711   rot = 0;
4712   rot_amt = 0;
4713
4714   if (MEM_ALIGN (src) >= 128)
4715     /* Address is already aligned; simply perform a TImode load.  */ ;
4716   else if (GET_CODE (addr) == PLUS)
4717     {
4718       /* 8 cases:
4719          aligned reg   + aligned reg     => lqx
4720          aligned reg   + unaligned reg   => lqx, rotqby
4721          aligned reg   + aligned const   => lqd
4722          aligned reg   + unaligned const => lqd, rotqbyi
4723          unaligned reg + aligned reg     => lqx, rotqby
4724          unaligned reg + unaligned reg   => lqx, a, rotqby (1 scratch)
4725          unaligned reg + aligned const   => lqd, rotqby
4726          unaligned reg + unaligned const -> not allowed by legitimate address
4727        */
4728       p0 = XEXP (addr, 0);
4729       p1 = XEXP (addr, 1);
4730       if (!reg_aligned_for_addr (p0))
4731         {
4732           if (REG_P (p1) && !reg_aligned_for_addr (p1))
4733             {
4734               rot = gen_reg_rtx (SImode);
4735               emit_insn (gen_addsi3 (rot, p0, p1));
4736             }
4737           else if (GET_CODE (p1) == CONST_INT && (INTVAL (p1) & 15))
4738             {
4739               if (INTVAL (p1) > 0
4740                   && REG_POINTER (p0)
4741                   && INTVAL (p1) * BITS_PER_UNIT
4742                      < REGNO_POINTER_ALIGN (REGNO (p0)))
4743                 {
4744                   rot = gen_reg_rtx (SImode);
4745                   emit_insn (gen_addsi3 (rot, p0, p1));
4746                   addr = p0;
4747                 }
4748               else
4749                 {
4750                   rtx x = gen_reg_rtx (SImode);
4751                   emit_move_insn (x, p1);
4752                   if (!spu_arith_operand (p1, SImode))
4753                     p1 = x;
4754                   rot = gen_reg_rtx (SImode);
4755                   emit_insn (gen_addsi3 (rot, p0, p1));
4756                   addr = gen_rtx_PLUS (Pmode, p0, x);
4757                 }
4758             }
4759           else
4760             rot = p0;
4761         }
4762       else
4763         {
4764           if (GET_CODE (p1) == CONST_INT && (INTVAL (p1) & 15))
4765             {
4766               rot_amt = INTVAL (p1) & 15;
4767               if (INTVAL (p1) & -16)
4768                 {
4769                   p1 = GEN_INT (INTVAL (p1) & -16);
4770                   addr = gen_rtx_PLUS (SImode, p0, p1);
4771                 }
4772               else
4773                 addr = p0;
4774             }
4775           else if (REG_P (p1) && !reg_aligned_for_addr (p1))
4776             rot = p1;
4777         }
4778     }
4779   else if (REG_P (addr))
4780     {
4781       if (!reg_aligned_for_addr (addr))
4782         rot = addr;
4783     }
4784   else if (GET_CODE (addr) == CONST)
4785     {
4786       if (GET_CODE (XEXP (addr, 0)) == PLUS
4787           && ALIGNED_SYMBOL_REF_P (XEXP (XEXP (addr, 0), 0))
4788           && GET_CODE (XEXP (XEXP (addr, 0), 1)) == CONST_INT)
4789         {
4790           rot_amt = INTVAL (XEXP (XEXP (addr, 0), 1));
4791           if (rot_amt & -16)
4792             addr = gen_rtx_CONST (Pmode,
4793                                   gen_rtx_PLUS (Pmode,
4794                                                 XEXP (XEXP (addr, 0), 0),
4795                                                 GEN_INT (rot_amt & -16)));
4796           else
4797             addr = XEXP (XEXP (addr, 0), 0);
4798         }
4799       else
4800         {
4801           rot = gen_reg_rtx (Pmode);
4802           emit_move_insn (rot, addr);
4803         }
4804     }
4805   else if (GET_CODE (addr) == CONST_INT)
4806     {
4807       rot_amt = INTVAL (addr);
4808       addr = GEN_INT (rot_amt & -16);
4809     }
4810   else if (!ALIGNED_SYMBOL_REF_P (addr))
4811     {
4812       rot = gen_reg_rtx (Pmode);
4813       emit_move_insn (rot, addr);
4814     }
4815
4816   rot_amt += extra_rotby;
4817
4818   rot_amt &= 15;
4819
4820   if (rot && rot_amt)
4821     {
4822       rtx x = gen_reg_rtx (SImode);
4823       emit_insn (gen_addsi3 (x, rot, GEN_INT (rot_amt)));
4824       rot = x;
4825       rot_amt = 0;
4826     }
4827   if (!rot && rot_amt)
4828     rot = GEN_INT (rot_amt);
4829
4830   addr0 = copy_rtx (addr);
4831   addr0 = gen_rtx_AND (SImode, copy_rtx (addr), GEN_INT (-16));
4832   emit_insn (gen__movti (dst0, change_address (src, TImode, addr0)));
4833
4834   if (dst1)
4835     {
4836       addr1 = plus_constant (copy_rtx (addr), 16);
4837       addr1 = gen_rtx_AND (SImode, addr1, GEN_INT (-16));
4838       emit_insn (gen__movti (dst1, change_address (src, TImode, addr1)));
4839     }
4840
4841   return rot;
4842 }
4843
4844 int
4845 spu_split_load (rtx * ops)
4846 {
4847   enum machine_mode mode = GET_MODE (ops[0]);
4848   rtx addr, load, rot;
4849   int rot_amt;
4850
4851   if (GET_MODE_SIZE (mode) >= 16)
4852     return 0;
4853
4854   addr = XEXP (ops[1], 0);
4855   gcc_assert (GET_CODE (addr) != AND);
4856
4857   if (!address_needs_split (ops[1]))
4858     {
4859       ops[1] = change_address (ops[1], TImode, addr);
4860       load = gen_reg_rtx (TImode);
4861       emit_insn (gen__movti (load, ops[1]));
4862       spu_convert_move (ops[0], load);
4863       return 1;
4864     }
4865
4866   rot_amt = GET_MODE_SIZE (mode) < 4 ? GET_MODE_SIZE (mode) - 4 : 0;
4867
4868   load = gen_reg_rtx (TImode);
4869   rot = spu_expand_load (load, 0, ops[1], rot_amt);
4870
4871   if (rot)
4872     emit_insn (gen_rotqby_ti (load, load, rot));
4873
4874   spu_convert_move (ops[0], load);
4875   return 1;
4876 }
4877
4878 int
4879 spu_split_store (rtx * ops)
4880 {
4881   enum machine_mode mode = GET_MODE (ops[0]);
4882   rtx reg;
4883   rtx addr, p0, p1, p1_lo, smem;
4884   int aform;
4885   int scalar;
4886
4887   if (GET_MODE_SIZE (mode) >= 16)
4888     return 0;
4889
4890   addr = XEXP (ops[0], 0);
4891   gcc_assert (GET_CODE (addr) != AND);
4892
4893   if (!address_needs_split (ops[0]))
4894     {
4895       reg = gen_reg_rtx (TImode);
4896       emit_insn (gen_spu_convert (reg, ops[1]));
4897       ops[0] = change_address (ops[0], TImode, addr);
4898       emit_move_insn (ops[0], reg);
4899       return 1;
4900     }
4901
4902   if (GET_CODE (addr) == PLUS)
4903     {
4904       /* 8 cases:
4905          aligned reg   + aligned reg     => lqx, c?x, shuf, stqx
4906          aligned reg   + unaligned reg   => lqx, c?x, shuf, stqx
4907          aligned reg   + aligned const   => lqd, c?d, shuf, stqx
4908          aligned reg   + unaligned const => lqd, c?d, shuf, stqx
4909          unaligned reg + aligned reg     => lqx, c?x, shuf, stqx
4910          unaligned reg + unaligned reg   => lqx, c?x, shuf, stqx
4911          unaligned reg + aligned const   => lqd, c?d, shuf, stqx
4912          unaligned reg + unaligned const -> lqx, c?d, shuf, stqx
4913        */
4914       aform = 0;
4915       p0 = XEXP (addr, 0);
4916       p1 = p1_lo = XEXP (addr, 1);
4917       if (REG_P (p0) && GET_CODE (p1) == CONST_INT)
4918         {
4919           p1_lo = GEN_INT (INTVAL (p1) & 15);
4920           if (reg_aligned_for_addr (p0))
4921             {
4922               p1 = GEN_INT (INTVAL (p1) & -16);
4923               if (p1 == const0_rtx)
4924                 addr = p0;
4925               else
4926                 addr = gen_rtx_PLUS (SImode, p0, p1);
4927             }
4928           else
4929             {
4930               rtx x = gen_reg_rtx (SImode);
4931               emit_move_insn (x, p1);
4932               addr = gen_rtx_PLUS (SImode, p0, x);
4933             }
4934         }
4935     }
4936   else if (REG_P (addr))
4937     {
4938       aform = 0;
4939       p0 = addr;
4940       p1 = p1_lo = const0_rtx;
4941     }
4942   else
4943     {
4944       aform = 1;
4945       p0 = gen_rtx_REG (SImode, STACK_POINTER_REGNUM);
4946       p1 = 0;                   /* aform doesn't use p1 */
4947       p1_lo = addr;
4948       if (ALIGNED_SYMBOL_REF_P (addr))
4949         p1_lo = const0_rtx;
4950       else if (GET_CODE (addr) == CONST
4951                && GET_CODE (XEXP (addr, 0)) == PLUS
4952                && ALIGNED_SYMBOL_REF_P (XEXP (XEXP (addr, 0), 0))
4953                && GET_CODE (XEXP (XEXP (addr, 0), 1)) == CONST_INT)
4954         {
4955           HOST_WIDE_INT v = INTVAL (XEXP (XEXP (addr, 0), 1));
4956           if ((v & -16) != 0)
4957             addr = gen_rtx_CONST (Pmode,
4958                                   gen_rtx_PLUS (Pmode,
4959                                                 XEXP (XEXP (addr, 0), 0),
4960                                                 GEN_INT (v & -16)));
4961           else
4962             addr = XEXP (XEXP (addr, 0), 0);
4963           p1_lo = GEN_INT (v & 15);
4964         }
4965       else if (GET_CODE (addr) == CONST_INT)
4966         {
4967           p1_lo = GEN_INT (INTVAL (addr) & 15);
4968           addr = GEN_INT (INTVAL (addr) & -16);
4969         }
4970       else
4971         {
4972           p1_lo = gen_reg_rtx (SImode);
4973           emit_move_insn (p1_lo, addr);
4974         }
4975     }
4976
4977   gcc_assert (aform == 0 || aform == 1);
4978   reg = gen_reg_rtx (TImode);
4979
4980   scalar = store_with_one_insn_p (ops[0]);
4981   if (!scalar)
4982     {
4983       /* We could copy the flags from the ops[0] MEM to mem here,
4984          We don't because we want this load to be optimized away if
4985          possible, and copying the flags will prevent that in certain
4986          cases, e.g. consider the volatile flag. */
4987
4988       rtx pat = gen_reg_rtx (TImode);
4989       rtx lmem = change_address (ops[0], TImode, copy_rtx (addr));
4990       set_mem_alias_set (lmem, 0);
4991       emit_insn (gen_movti (reg, lmem));
4992
4993       if (!p0 || reg_aligned_for_addr (p0))
4994         p0 = stack_pointer_rtx;
4995       if (!p1_lo)
4996         p1_lo = const0_rtx;
4997
4998       emit_insn (gen_cpat (pat, p0, p1_lo, GEN_INT (GET_MODE_SIZE (mode))));
4999       emit_insn (gen_shufb (reg, ops[1], reg, pat));
5000     }
5001   else
5002     {
5003       if (GET_CODE (ops[1]) == REG)
5004         emit_insn (gen_spu_convert (reg, ops[1]));
5005       else if (GET_CODE (ops[1]) == SUBREG)
5006         emit_insn (gen_spu_convert (reg, SUBREG_REG (ops[1])));
5007       else
5008         abort ();
5009     }
5010
5011   if (GET_MODE_SIZE (mode) < 4 && scalar)
5012     emit_insn (gen_ashlti3
5013                (reg, reg, GEN_INT (32 - GET_MODE_BITSIZE (mode))));
5014
5015   smem = change_address (ops[0], TImode, copy_rtx (addr));
5016   /* We can't use the previous alias set because the memory has changed
5017      size and can potentially overlap objects of other types.  */
5018   set_mem_alias_set (smem, 0);
5019
5020   emit_insn (gen_movti (smem, reg));
5021   return 1;
5022 }
5023
5024 /* Return TRUE if X is MEM which is a struct member reference
5025    and the member can safely be loaded and stored with a single
5026    instruction because it is padded. */
5027 static int
5028 mem_is_padded_component_ref (rtx x)
5029 {
5030   tree t = MEM_EXPR (x);
5031   tree r;
5032   if (!t || TREE_CODE (t) != COMPONENT_REF)
5033     return 0;
5034   t = TREE_OPERAND (t, 1);
5035   if (!t || TREE_CODE (t) != FIELD_DECL
5036       || DECL_ALIGN (t) < 128 || AGGREGATE_TYPE_P (TREE_TYPE (t)))
5037     return 0;
5038   /* Only do this for RECORD_TYPEs, not UNION_TYPEs. */
5039   r = DECL_FIELD_CONTEXT (t);
5040   if (!r || TREE_CODE (r) != RECORD_TYPE)
5041     return 0;
5042   /* Make sure they are the same mode */
5043   if (GET_MODE (x) != TYPE_MODE (TREE_TYPE (t)))
5044     return 0;
5045   /* If there are no following fields then the field alignment assures
5046      the structure is padded to the alignment which means this field is
5047      padded too.  */
5048   if (TREE_CHAIN (t) == 0)
5049     return 1;
5050   /* If the following field is also aligned then this field will be
5051      padded. */
5052   t = TREE_CHAIN (t);
5053   if (TREE_CODE (t) == FIELD_DECL && DECL_ALIGN (t) >= 128)
5054     return 1;
5055   return 0;
5056 }
5057
5058 /* Parse the -mfixed-range= option string.  */
5059 static void
5060 fix_range (const char *const_str)
5061 {
5062   int i, first, last;
5063   char *str, *dash, *comma;
5064   
5065   /* str must be of the form REG1'-'REG2{,REG1'-'REG} where REG1 and
5066      REG2 are either register names or register numbers.  The effect
5067      of this option is to mark the registers in the range from REG1 to
5068      REG2 as ``fixed'' so they won't be used by the compiler.  */
5069   
5070   i = strlen (const_str);
5071   str = (char *) alloca (i + 1);
5072   memcpy (str, const_str, i + 1);
5073   
5074   while (1)
5075     {
5076       dash = strchr (str, '-');
5077       if (!dash)
5078         {
5079           warning (0, "value of -mfixed-range must have form REG1-REG2");
5080           return;
5081         }
5082       *dash = '\0';
5083       comma = strchr (dash + 1, ',');
5084       if (comma)
5085         *comma = '\0';
5086       
5087       first = decode_reg_name (str);
5088       if (first < 0)
5089         {
5090           warning (0, "unknown register name: %s", str);
5091           return;
5092         }
5093       
5094       last = decode_reg_name (dash + 1);
5095       if (last < 0)
5096         {
5097           warning (0, "unknown register name: %s", dash + 1);
5098           return;
5099         }
5100       
5101       *dash = '-';
5102       
5103       if (first > last)
5104         {
5105           warning (0, "%s-%s is an empty range", str, dash + 1);
5106           return;
5107         }
5108       
5109       for (i = first; i <= last; ++i)
5110         fixed_regs[i] = call_used_regs[i] = 1;
5111
5112       if (!comma)
5113         break;
5114
5115       *comma = ',';
5116       str = comma + 1;
5117     }
5118 }
5119
5120 /* Return TRUE if x is a CONST_INT, CONST_DOUBLE or CONST_VECTOR that
5121    can be generated using the fsmbi instruction. */
5122 int
5123 fsmbi_const_p (rtx x)
5124 {
5125   if (CONSTANT_P (x))
5126     {
5127       /* We can always choose TImode for CONST_INT because the high bits
5128          of an SImode will always be all 1s, i.e., valid for fsmbi. */
5129       enum immediate_class c = classify_immediate (x, TImode);
5130       return c == IC_FSMBI || (!epilogue_completed && c == IC_FSMBI2);
5131     }
5132   return 0;
5133 }
5134
5135 /* Return TRUE if x is a CONST_INT, CONST_DOUBLE or CONST_VECTOR that
5136    can be generated using the cbd, chd, cwd or cdd instruction. */
5137 int
5138 cpat_const_p (rtx x, enum machine_mode mode)
5139 {
5140   if (CONSTANT_P (x))
5141     {
5142       enum immediate_class c = classify_immediate (x, mode);
5143       return c == IC_CPAT;
5144     }
5145   return 0;
5146 }
5147
5148 rtx
5149 gen_cpat_const (rtx * ops)
5150 {
5151   unsigned char dst[16];
5152   int i, offset, shift, isize;
5153   if (GET_CODE (ops[3]) != CONST_INT
5154       || GET_CODE (ops[2]) != CONST_INT
5155       || (GET_CODE (ops[1]) != CONST_INT
5156           && GET_CODE (ops[1]) != REG))
5157     return 0;
5158   if (GET_CODE (ops[1]) == REG
5159       && (!REG_POINTER (ops[1])
5160           || REGNO_POINTER_ALIGN (ORIGINAL_REGNO (ops[1])) < 128))
5161     return 0;
5162
5163   for (i = 0; i < 16; i++)
5164     dst[i] = i + 16;
5165   isize = INTVAL (ops[3]);
5166   if (isize == 1)
5167     shift = 3;
5168   else if (isize == 2)
5169     shift = 2;
5170   else
5171     shift = 0;
5172   offset = (INTVAL (ops[2]) +
5173             (GET_CODE (ops[1]) ==
5174              CONST_INT ? INTVAL (ops[1]) : 0)) & 15;
5175   for (i = 0; i < isize; i++)
5176     dst[offset + i] = i + shift;
5177   return array_to_constant (TImode, dst);
5178 }
5179
5180 /* Convert a CONST_INT, CONST_DOUBLE, or CONST_VECTOR into a 16 byte
5181    array.  Use MODE for CONST_INT's.  When the constant's mode is smaller
5182    than 16 bytes, the value is repeated across the rest of the array. */
5183 void
5184 constant_to_array (enum machine_mode mode, rtx x, unsigned char arr[16])
5185 {
5186   HOST_WIDE_INT val;
5187   int i, j, first;
5188
5189   memset (arr, 0, 16);
5190   mode = GET_MODE (x) != VOIDmode ? GET_MODE (x) : mode;
5191   if (GET_CODE (x) == CONST_INT
5192       || (GET_CODE (x) == CONST_DOUBLE
5193           && (mode == SFmode || mode == DFmode)))
5194     {
5195       gcc_assert (mode != VOIDmode && mode != BLKmode);
5196
5197       if (GET_CODE (x) == CONST_DOUBLE)
5198         val = const_double_to_hwint (x);
5199       else
5200         val = INTVAL (x);
5201       first = GET_MODE_SIZE (mode) - 1;
5202       for (i = first; i >= 0; i--)
5203         {
5204           arr[i] = val & 0xff;
5205           val >>= 8;
5206         }
5207       /* Splat the constant across the whole array. */
5208       for (j = 0, i = first + 1; i < 16; i++)
5209         {
5210           arr[i] = arr[j];
5211           j = (j == first) ? 0 : j + 1;
5212         }
5213     }
5214   else if (GET_CODE (x) == CONST_DOUBLE)
5215     {
5216       val = CONST_DOUBLE_LOW (x);
5217       for (i = 15; i >= 8; i--)
5218         {
5219           arr[i] = val & 0xff;
5220           val >>= 8;
5221         }
5222       val = CONST_DOUBLE_HIGH (x);
5223       for (i = 7; i >= 0; i--)
5224         {
5225           arr[i] = val & 0xff;
5226           val >>= 8;
5227         }
5228     }
5229   else if (GET_CODE (x) == CONST_VECTOR)
5230     {
5231       int units;
5232       rtx elt;
5233       mode = GET_MODE_INNER (mode);
5234       units = CONST_VECTOR_NUNITS (x);
5235       for (i = 0; i < units; i++)
5236         {
5237           elt = CONST_VECTOR_ELT (x, i);
5238           if (GET_CODE (elt) == CONST_INT || GET_CODE (elt) == CONST_DOUBLE)
5239             {
5240               if (GET_CODE (elt) == CONST_DOUBLE)
5241                 val = const_double_to_hwint (elt);
5242               else
5243                 val = INTVAL (elt);
5244               first = GET_MODE_SIZE (mode) - 1;
5245               if (first + i * GET_MODE_SIZE (mode) > 16)
5246                 abort ();
5247               for (j = first; j >= 0; j--)
5248                 {
5249                   arr[j + i * GET_MODE_SIZE (mode)] = val & 0xff;
5250                   val >>= 8;
5251                 }
5252             }
5253         }
5254     }
5255   else
5256     gcc_unreachable();
5257 }
5258
5259 /* Convert a 16 byte array to a constant of mode MODE.  When MODE is
5260    smaller than 16 bytes, use the bytes that would represent that value
5261    in a register, e.g., for QImode return the value of arr[3].  */
5262 rtx
5263 array_to_constant (enum machine_mode mode, const unsigned char arr[16])
5264 {
5265   enum machine_mode inner_mode;
5266   rtvec v;
5267   int units, size, i, j, k;
5268   HOST_WIDE_INT val;
5269
5270   if (GET_MODE_CLASS (mode) == MODE_INT
5271       && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT)
5272     {
5273       j = GET_MODE_SIZE (mode);
5274       i = j < 4 ? 4 - j : 0;
5275       for (val = 0; i < j; i++)
5276         val = (val << 8) | arr[i];
5277       val = trunc_int_for_mode (val, mode);
5278       return GEN_INT (val);
5279     }
5280
5281   if (mode == TImode)
5282     {
5283       HOST_WIDE_INT high;
5284       for (i = high = 0; i < 8; i++)
5285         high = (high << 8) | arr[i];
5286       for (i = 8, val = 0; i < 16; i++)
5287         val = (val << 8) | arr[i];
5288       return immed_double_const (val, high, TImode);
5289     }
5290   if (mode == SFmode)
5291     {
5292       val = (arr[0] << 24) | (arr[1] << 16) | (arr[2] << 8) | arr[3];
5293       val = trunc_int_for_mode (val, SImode);
5294       return hwint_to_const_double (SFmode, val);
5295     }
5296   if (mode == DFmode)
5297     {
5298       for (i = 0, val = 0; i < 8; i++)
5299         val = (val << 8) | arr[i];
5300       return hwint_to_const_double (DFmode, val);
5301     }
5302
5303   if (!VECTOR_MODE_P (mode))
5304     abort ();
5305
5306   units = GET_MODE_NUNITS (mode);
5307   size = GET_MODE_UNIT_SIZE (mode);
5308   inner_mode = GET_MODE_INNER (mode);
5309   v = rtvec_alloc (units);
5310
5311   for (k = i = 0; i < units; ++i)
5312     {
5313       val = 0;
5314       for (j = 0; j < size; j++, k++)
5315         val = (val << 8) | arr[k];
5316
5317       if (GET_MODE_CLASS (inner_mode) == MODE_FLOAT)
5318         RTVEC_ELT (v, i) = hwint_to_const_double (inner_mode, val);
5319       else
5320         RTVEC_ELT (v, i) = GEN_INT (trunc_int_for_mode (val, inner_mode));
5321     }
5322   if (k > 16)
5323     abort ();
5324
5325   return gen_rtx_CONST_VECTOR (mode, v);
5326 }
5327
5328 static void
5329 reloc_diagnostic (rtx x)
5330 {
5331   tree decl = 0;
5332   if (!flag_pic || !(TARGET_WARN_RELOC || TARGET_ERROR_RELOC))
5333     return;
5334
5335   if (GET_CODE (x) == SYMBOL_REF)
5336     decl = SYMBOL_REF_DECL (x);
5337   else if (GET_CODE (x) == CONST
5338            && GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF)
5339     decl = SYMBOL_REF_DECL (XEXP (XEXP (x, 0), 0));
5340
5341   /* SYMBOL_REF_DECL is not necessarily a DECL. */
5342   if (decl && !DECL_P (decl))
5343     decl = 0;
5344
5345   /* The decl could be a string constant.  */
5346   if (decl && DECL_P (decl))
5347     {
5348       location_t loc;
5349       /* We use last_assemble_variable_decl to get line information.  It's
5350          not always going to be right and might not even be close, but will
5351          be right for the more common cases. */
5352       if (!last_assemble_variable_decl || in_section == ctors_section)
5353         loc = DECL_SOURCE_LOCATION (decl);
5354       else
5355         loc = DECL_SOURCE_LOCATION (last_assemble_variable_decl);
5356
5357       if (TARGET_WARN_RELOC)
5358         warning_at (loc, 0,
5359                     "creating run-time relocation for %qD", decl);
5360       else
5361         error_at (loc,
5362                   "creating run-time relocation for %qD", decl);
5363     }
5364   else 
5365     {
5366       if (TARGET_WARN_RELOC)
5367         warning_at (input_location, 0, "creating run-time relocation");
5368       else
5369         error_at (input_location, "creating run-time relocation");
5370     }
5371 }
5372
5373 /* Hook into assemble_integer so we can generate an error for run-time
5374    relocations.  The SPU ABI disallows them. */
5375 static bool
5376 spu_assemble_integer (rtx x, unsigned int size, int aligned_p)
5377 {
5378   /* By default run-time relocations aren't supported, but we allow them
5379      in case users support it in their own run-time loader.  And we provide
5380      a warning for those users that don't.  */
5381   if ((GET_CODE (x) == SYMBOL_REF)
5382       || GET_CODE (x) == LABEL_REF || GET_CODE (x) == CONST)
5383     reloc_diagnostic (x);
5384
5385   return default_assemble_integer (x, size, aligned_p);
5386 }
5387
5388 static void
5389 spu_asm_globalize_label (FILE * file, const char *name)
5390 {
5391   fputs ("\t.global\t", file);
5392   assemble_name (file, name);
5393   fputs ("\n", file);
5394 }
5395
5396 static bool
5397 spu_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED, int *total,
5398                bool speed ATTRIBUTE_UNUSED)
5399 {
5400   enum machine_mode mode = GET_MODE (x);
5401   int cost = COSTS_N_INSNS (2);
5402
5403   /* Folding to a CONST_VECTOR will use extra space but there might
5404      be only a small savings in cycles.  We'd like to use a CONST_VECTOR
5405      only if it allows us to fold away multiple insns.  Changing the cost
5406      of a CONST_VECTOR here (or in CONST_COSTS) doesn't help though
5407      because this cost will only be compared against a single insn. 
5408      if (code == CONST_VECTOR)
5409        return (LEGITIMATE_CONSTANT_P(x)) ? cost : COSTS_N_INSNS(6);
5410    */
5411
5412   /* Use defaults for float operations.  Not accurate but good enough. */
5413   if (mode == DFmode)
5414     {
5415       *total = COSTS_N_INSNS (13);
5416       return true;
5417     }
5418   if (mode == SFmode)
5419     {
5420       *total = COSTS_N_INSNS (6);
5421       return true;
5422     }
5423   switch (code)
5424     {
5425     case CONST_INT:
5426       if (satisfies_constraint_K (x))
5427         *total = 0;
5428       else if (INTVAL (x) >= -0x80000000ll && INTVAL (x) <= 0xffffffffll)
5429         *total = COSTS_N_INSNS (1);
5430       else
5431         *total = COSTS_N_INSNS (3);
5432       return true;
5433
5434     case CONST:
5435       *total = COSTS_N_INSNS (3);
5436       return true;
5437
5438     case LABEL_REF:
5439     case SYMBOL_REF:
5440       *total = COSTS_N_INSNS (0);
5441       return true;
5442
5443     case CONST_DOUBLE:
5444       *total = COSTS_N_INSNS (5);
5445       return true;
5446
5447     case FLOAT_EXTEND:
5448     case FLOAT_TRUNCATE:
5449     case FLOAT:
5450     case UNSIGNED_FLOAT:
5451     case FIX:
5452     case UNSIGNED_FIX:
5453       *total = COSTS_N_INSNS (7);
5454       return true;
5455
5456     case PLUS:
5457       if (mode == TImode)
5458         {
5459           *total = COSTS_N_INSNS (9);
5460           return true;
5461         }
5462       break;
5463
5464     case MULT:
5465       cost =
5466         GET_CODE (XEXP (x, 0)) ==
5467         REG ? COSTS_N_INSNS (12) : COSTS_N_INSNS (7);
5468       if (mode == SImode && GET_CODE (XEXP (x, 0)) == REG)
5469         {
5470           if (GET_CODE (XEXP (x, 1)) == CONST_INT)
5471             {
5472               HOST_WIDE_INT val = INTVAL (XEXP (x, 1));
5473               cost = COSTS_N_INSNS (14);
5474               if ((val & 0xffff) == 0)
5475                 cost = COSTS_N_INSNS (9);
5476               else if (val > 0 && val < 0x10000)
5477                 cost = COSTS_N_INSNS (11);
5478             }
5479         }
5480       *total = cost;
5481       return true;
5482     case DIV:
5483     case UDIV:
5484     case MOD:
5485     case UMOD:
5486       *total = COSTS_N_INSNS (20);
5487       return true;
5488     case ROTATE:
5489     case ROTATERT:
5490     case ASHIFT:
5491     case ASHIFTRT:
5492     case LSHIFTRT:
5493       *total = COSTS_N_INSNS (4);
5494       return true;
5495     case UNSPEC:
5496       if (XINT (x, 1) == UNSPEC_CONVERT)
5497         *total = COSTS_N_INSNS (0);
5498       else
5499         *total = COSTS_N_INSNS (4);
5500       return true;
5501     }
5502   /* Scale cost by mode size.  Except when initializing (cfun->decl == 0). */
5503   if (GET_MODE_CLASS (mode) == MODE_INT
5504       && GET_MODE_SIZE (mode) > GET_MODE_SIZE (SImode) && cfun && cfun->decl)
5505     cost = cost * (GET_MODE_SIZE (mode) / GET_MODE_SIZE (SImode))
5506       * (GET_MODE_SIZE (mode) / GET_MODE_SIZE (SImode));
5507   *total = cost;
5508   return true;
5509 }
5510
5511 static enum machine_mode
5512 spu_unwind_word_mode (void)
5513 {
5514   return SImode;
5515 }
5516
5517 /* Decide whether we can make a sibling call to a function.  DECL is the
5518    declaration of the function being targeted by the call and EXP is the
5519    CALL_EXPR representing the call.  */
5520 static bool
5521 spu_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED)
5522 {
5523   return decl && !TARGET_LARGE_MEM;
5524 }
5525
5526 /* We need to correctly update the back chain pointer and the Available
5527    Stack Size (which is in the second slot of the sp register.) */
5528 void
5529 spu_allocate_stack (rtx op0, rtx op1)
5530 {
5531   HOST_WIDE_INT v;
5532   rtx chain = gen_reg_rtx (V4SImode);
5533   rtx stack_bot = gen_frame_mem (V4SImode, stack_pointer_rtx);
5534   rtx sp = gen_reg_rtx (V4SImode);
5535   rtx splatted = gen_reg_rtx (V4SImode);
5536   rtx pat = gen_reg_rtx (TImode);
5537
5538   /* copy the back chain so we can save it back again. */
5539   emit_move_insn (chain, stack_bot);
5540
5541   op1 = force_reg (SImode, op1);
5542
5543   v = 0x1020300010203ll;
5544   emit_move_insn (pat, immed_double_const (v, v, TImode));
5545   emit_insn (gen_shufb (splatted, op1, op1, pat));
5546
5547   emit_insn (gen_spu_convert (sp, stack_pointer_rtx));
5548   emit_insn (gen_subv4si3 (sp, sp, splatted));
5549
5550   if (flag_stack_check)
5551     {
5552       rtx avail = gen_reg_rtx(SImode);
5553       rtx result = gen_reg_rtx(SImode);
5554       emit_insn (gen_vec_extractv4si (avail, sp, GEN_INT (1)));
5555       emit_insn (gen_cgt_si(result, avail, GEN_INT (-1)));
5556       emit_insn (gen_spu_heq (result, GEN_INT(0) ));
5557     }
5558
5559   emit_insn (gen_spu_convert (stack_pointer_rtx, sp));
5560
5561   emit_move_insn (stack_bot, chain);
5562
5563   emit_move_insn (op0, virtual_stack_dynamic_rtx);
5564 }
5565
5566 void
5567 spu_restore_stack_nonlocal (rtx op0 ATTRIBUTE_UNUSED, rtx op1)
5568 {
5569   static unsigned char arr[16] =
5570     { 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3 };
5571   rtx temp = gen_reg_rtx (SImode);
5572   rtx temp2 = gen_reg_rtx (SImode);
5573   rtx temp3 = gen_reg_rtx (V4SImode);
5574   rtx temp4 = gen_reg_rtx (V4SImode);
5575   rtx pat = gen_reg_rtx (TImode);
5576   rtx sp = gen_rtx_REG (V4SImode, STACK_POINTER_REGNUM);
5577
5578   /* Restore the backchain from the first word, sp from the second.  */
5579   emit_move_insn (temp2, adjust_address_nv (op1, SImode, 0));
5580   emit_move_insn (temp, adjust_address_nv (op1, SImode, 4));
5581
5582   emit_move_insn (pat, array_to_constant (TImode, arr));
5583
5584   /* Compute Available Stack Size for sp */
5585   emit_insn (gen_subsi3 (temp, temp, stack_pointer_rtx));
5586   emit_insn (gen_shufb (temp3, temp, temp, pat));
5587
5588   /* Compute Available Stack Size for back chain */
5589   emit_insn (gen_subsi3 (temp2, temp2, stack_pointer_rtx));
5590   emit_insn (gen_shufb (temp4, temp2, temp2, pat));
5591   emit_insn (gen_addv4si3 (temp4, sp, temp4));
5592
5593   emit_insn (gen_addv4si3 (sp, sp, temp3));
5594   emit_move_insn (gen_frame_mem (V4SImode, stack_pointer_rtx), temp4);
5595 }
5596
5597 static void
5598 spu_init_libfuncs (void)
5599 {
5600   set_optab_libfunc (smul_optab, DImode, "__muldi3");
5601   set_optab_libfunc (sdiv_optab, DImode, "__divdi3");
5602   set_optab_libfunc (smod_optab, DImode, "__moddi3");
5603   set_optab_libfunc (udiv_optab, DImode, "__udivdi3");
5604   set_optab_libfunc (umod_optab, DImode, "__umoddi3");
5605   set_optab_libfunc (udivmod_optab, DImode, "__udivmoddi4");
5606   set_optab_libfunc (ffs_optab, DImode, "__ffsdi2");
5607   set_optab_libfunc (clz_optab, DImode, "__clzdi2");
5608   set_optab_libfunc (ctz_optab, DImode, "__ctzdi2");
5609   set_optab_libfunc (popcount_optab, DImode, "__popcountdi2");
5610   set_optab_libfunc (parity_optab, DImode, "__paritydi2");
5611
5612   set_conv_libfunc (ufloat_optab, DFmode, SImode, "__float_unssidf");
5613   set_conv_libfunc (ufloat_optab, DFmode, DImode, "__float_unsdidf");
5614
5615   set_optab_libfunc (smul_optab, TImode, "__multi3");
5616   set_optab_libfunc (sdiv_optab, TImode, "__divti3");
5617   set_optab_libfunc (smod_optab, TImode, "__modti3");
5618   set_optab_libfunc (udiv_optab, TImode, "__udivti3");
5619   set_optab_libfunc (umod_optab, TImode, "__umodti3");
5620   set_optab_libfunc (udivmod_optab, TImode, "__udivmodti4");
5621 }
5622
5623 /* Make a subreg, stripping any existing subreg.  We could possibly just
5624    call simplify_subreg, but in this case we know what we want. */
5625 rtx
5626 spu_gen_subreg (enum machine_mode mode, rtx x)
5627 {
5628   if (GET_CODE (x) == SUBREG)
5629     x = SUBREG_REG (x);
5630   if (GET_MODE (x) == mode)
5631     return x;
5632   return gen_rtx_SUBREG (mode, x, 0);
5633 }
5634
5635 static bool
5636 spu_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
5637 {
5638   return (TYPE_MODE (type) == BLKmode
5639           && ((type) == 0
5640               || TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST
5641               || int_size_in_bytes (type) >
5642               (MAX_REGISTER_RETURN * UNITS_PER_WORD)));
5643 }
5644 \f
5645 /* Create the built-in types and functions */
5646
5647 enum spu_function_code
5648 {
5649 #define DEF_BUILTIN(fcode, icode, name, type, params) fcode,
5650 #include "spu-builtins.def"
5651 #undef DEF_BUILTIN
5652    NUM_SPU_BUILTINS
5653 };
5654
5655 extern GTY(()) struct spu_builtin_description spu_builtins[NUM_SPU_BUILTINS];
5656
5657 struct spu_builtin_description spu_builtins[] = {
5658 #define DEF_BUILTIN(fcode, icode, name, type, params) \
5659   {fcode, icode, name, type, params},
5660 #include "spu-builtins.def"
5661 #undef DEF_BUILTIN
5662 };
5663
5664 static GTY(()) tree spu_builtin_decls[NUM_SPU_BUILTINS];
5665
5666 /* Returns the spu builtin decl for CODE.  */
5667
5668 static tree
5669 spu_builtin_decl (unsigned code, bool initialize_p ATTRIBUTE_UNUSED)
5670 {           
5671   if (code >= NUM_SPU_BUILTINS)
5672     return error_mark_node;
5673           
5674   return spu_builtin_decls[code];
5675 }
5676
5677
5678 static void
5679 spu_init_builtins (void)
5680 {
5681   struct spu_builtin_description *d;
5682   unsigned int i;
5683
5684   V16QI_type_node = build_vector_type (intQI_type_node, 16);
5685   V8HI_type_node = build_vector_type (intHI_type_node, 8);
5686   V4SI_type_node = build_vector_type (intSI_type_node, 4);
5687   V2DI_type_node = build_vector_type (intDI_type_node, 2);
5688   V4SF_type_node = build_vector_type (float_type_node, 4);
5689   V2DF_type_node = build_vector_type (double_type_node, 2);
5690
5691   unsigned_V16QI_type_node = build_vector_type (unsigned_intQI_type_node, 16);
5692   unsigned_V8HI_type_node = build_vector_type (unsigned_intHI_type_node, 8);
5693   unsigned_V4SI_type_node = build_vector_type (unsigned_intSI_type_node, 4);
5694   unsigned_V2DI_type_node = build_vector_type (unsigned_intDI_type_node, 2);
5695
5696   spu_builtin_types[SPU_BTI_QUADWORD] = V16QI_type_node;
5697
5698   spu_builtin_types[SPU_BTI_7] = global_trees[TI_INTSI_TYPE];
5699   spu_builtin_types[SPU_BTI_S7] = global_trees[TI_INTSI_TYPE];
5700   spu_builtin_types[SPU_BTI_U7] = global_trees[TI_INTSI_TYPE];
5701   spu_builtin_types[SPU_BTI_S10] = global_trees[TI_INTSI_TYPE];
5702   spu_builtin_types[SPU_BTI_S10_4] = global_trees[TI_INTSI_TYPE];
5703   spu_builtin_types[SPU_BTI_U14] = global_trees[TI_INTSI_TYPE];
5704   spu_builtin_types[SPU_BTI_16] = global_trees[TI_INTSI_TYPE];
5705   spu_builtin_types[SPU_BTI_S16] = global_trees[TI_INTSI_TYPE];
5706   spu_builtin_types[SPU_BTI_S16_2] = global_trees[TI_INTSI_TYPE];
5707   spu_builtin_types[SPU_BTI_U16] = global_trees[TI_INTSI_TYPE];
5708   spu_builtin_types[SPU_BTI_U16_2] = global_trees[TI_INTSI_TYPE];
5709   spu_builtin_types[SPU_BTI_U18] = global_trees[TI_INTSI_TYPE];
5710
5711   spu_builtin_types[SPU_BTI_INTQI] = global_trees[TI_INTQI_TYPE];
5712   spu_builtin_types[SPU_BTI_INTHI] = global_trees[TI_INTHI_TYPE];
5713   spu_builtin_types[SPU_BTI_INTSI] = global_trees[TI_INTSI_TYPE];
5714   spu_builtin_types[SPU_BTI_INTDI] = global_trees[TI_INTDI_TYPE];
5715   spu_builtin_types[SPU_BTI_UINTQI] = global_trees[TI_UINTQI_TYPE];
5716   spu_builtin_types[SPU_BTI_UINTHI] = global_trees[TI_UINTHI_TYPE];
5717   spu_builtin_types[SPU_BTI_UINTSI] = global_trees[TI_UINTSI_TYPE];
5718   spu_builtin_types[SPU_BTI_UINTDI] = global_trees[TI_UINTDI_TYPE];
5719
5720   spu_builtin_types[SPU_BTI_FLOAT] = global_trees[TI_FLOAT_TYPE];
5721   spu_builtin_types[SPU_BTI_DOUBLE] = global_trees[TI_DOUBLE_TYPE];
5722
5723   spu_builtin_types[SPU_BTI_VOID] = global_trees[TI_VOID_TYPE];
5724
5725   spu_builtin_types[SPU_BTI_PTR] =
5726     build_pointer_type (build_qualified_type
5727                         (void_type_node,
5728                          TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE));
5729
5730   /* For each builtin we build a new prototype.  The tree code will make
5731      sure nodes are shared. */
5732   for (i = 0, d = spu_builtins; i < NUM_SPU_BUILTINS; i++, d++)
5733     {
5734       tree p;
5735       char name[64];            /* build_function will make a copy. */
5736       int parm;
5737
5738       if (d->name == 0)
5739         continue;
5740
5741       /* Find last parm.  */
5742       for (parm = 1; d->parm[parm] != SPU_BTI_END_OF_PARAMS; parm++)
5743         ;
5744
5745       p = void_list_node;
5746       while (parm > 1)
5747         p = tree_cons (NULL_TREE, spu_builtin_types[d->parm[--parm]], p);
5748
5749       p = build_function_type (spu_builtin_types[d->parm[0]], p);
5750
5751       sprintf (name, "__builtin_%s", d->name);
5752       spu_builtin_decls[i] =
5753         add_builtin_function (name, p, i, BUILT_IN_MD, NULL, NULL_TREE);
5754       if (d->fcode == SPU_MASK_FOR_LOAD)
5755         TREE_READONLY (spu_builtin_decls[i]) = 1;       
5756
5757       /* These builtins don't throw.  */
5758       TREE_NOTHROW (spu_builtin_decls[i]) = 1;
5759     }
5760 }
5761
5762 void
5763 spu_restore_stack_block (rtx op0 ATTRIBUTE_UNUSED, rtx op1)
5764 {
5765   static unsigned char arr[16] =
5766     { 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3 };
5767
5768   rtx temp = gen_reg_rtx (Pmode);
5769   rtx temp2 = gen_reg_rtx (V4SImode);
5770   rtx temp3 = gen_reg_rtx (V4SImode);
5771   rtx pat = gen_reg_rtx (TImode);
5772   rtx sp = gen_rtx_REG (V4SImode, STACK_POINTER_REGNUM);
5773
5774   emit_move_insn (pat, array_to_constant (TImode, arr));
5775
5776   /* Restore the sp.  */
5777   emit_move_insn (temp, op1);
5778   emit_move_insn (temp2, gen_frame_mem (V4SImode, stack_pointer_rtx));
5779
5780   /* Compute available stack size for sp.  */
5781   emit_insn (gen_subsi3 (temp, temp, stack_pointer_rtx));
5782   emit_insn (gen_shufb (temp3, temp, temp, pat));
5783
5784   emit_insn (gen_addv4si3 (sp, sp, temp3));
5785   emit_move_insn (gen_frame_mem (V4SImode, stack_pointer_rtx), temp2);
5786 }
5787
5788 int
5789 spu_safe_dma (HOST_WIDE_INT channel)
5790 {
5791   return TARGET_SAFE_DMA && channel >= 21 && channel <= 27;
5792 }
5793
5794 void
5795 spu_builtin_splats (rtx ops[])
5796 {
5797   enum machine_mode mode = GET_MODE (ops[0]);
5798   if (GET_CODE (ops[1]) == CONST_INT || GET_CODE (ops[1]) == CONST_DOUBLE)
5799     {
5800       unsigned char arr[16];
5801       constant_to_array (GET_MODE_INNER (mode), ops[1], arr);
5802       emit_move_insn (ops[0], array_to_constant (mode, arr));
5803     }
5804   else
5805     {
5806       rtx reg = gen_reg_rtx (TImode);
5807       rtx shuf;
5808       if (GET_CODE (ops[1]) != REG
5809           && GET_CODE (ops[1]) != SUBREG)
5810         ops[1] = force_reg (GET_MODE_INNER (mode), ops[1]);
5811       switch (mode)
5812         {
5813         case V2DImode:
5814         case V2DFmode:
5815           shuf =
5816             immed_double_const (0x0001020304050607ll, 0x1011121314151617ll,
5817                                 TImode);
5818           break;
5819         case V4SImode:
5820         case V4SFmode:
5821           shuf =
5822             immed_double_const (0x0001020300010203ll, 0x0001020300010203ll,
5823                                 TImode);
5824           break;
5825         case V8HImode:
5826           shuf =
5827             immed_double_const (0x0203020302030203ll, 0x0203020302030203ll,
5828                                 TImode);
5829           break;
5830         case V16QImode:
5831           shuf =
5832             immed_double_const (0x0303030303030303ll, 0x0303030303030303ll,
5833                                 TImode);
5834           break;
5835         default:
5836           abort ();
5837         }
5838       emit_move_insn (reg, shuf);
5839       emit_insn (gen_shufb (ops[0], ops[1], ops[1], reg));
5840     }
5841 }
5842
5843 void
5844 spu_builtin_extract (rtx ops[])
5845 {
5846   enum machine_mode mode;
5847   rtx rot, from, tmp;
5848
5849   mode = GET_MODE (ops[1]);
5850
5851   if (GET_CODE (ops[2]) == CONST_INT)
5852     {
5853       switch (mode)
5854         {
5855         case V16QImode:
5856           emit_insn (gen_vec_extractv16qi (ops[0], ops[1], ops[2]));
5857           break;
5858         case V8HImode:
5859           emit_insn (gen_vec_extractv8hi (ops[0], ops[1], ops[2]));
5860           break;
5861         case V4SFmode:
5862           emit_insn (gen_vec_extractv4sf (ops[0], ops[1], ops[2]));
5863           break;
5864         case V4SImode:
5865           emit_insn (gen_vec_extractv4si (ops[0], ops[1], ops[2]));
5866           break;
5867         case V2DImode:
5868           emit_insn (gen_vec_extractv2di (ops[0], ops[1], ops[2]));
5869           break;
5870         case V2DFmode:
5871           emit_insn (gen_vec_extractv2df (ops[0], ops[1], ops[2]));
5872           break;
5873         default:
5874           abort ();
5875         }
5876       return;
5877     }
5878
5879   from = spu_gen_subreg (TImode, ops[1]);
5880   rot = gen_reg_rtx (TImode);
5881   tmp = gen_reg_rtx (SImode);
5882
5883   switch (mode)
5884     {
5885     case V16QImode:
5886       emit_insn (gen_addsi3 (tmp, ops[2], GEN_INT (-3)));
5887       break;
5888     case V8HImode:
5889       emit_insn (gen_addsi3 (tmp, ops[2], ops[2]));
5890       emit_insn (gen_addsi3 (tmp, tmp, GEN_INT (-2)));
5891       break;
5892     case V4SFmode:
5893     case V4SImode:
5894       emit_insn (gen_ashlsi3 (tmp, ops[2], GEN_INT (2)));
5895       break;
5896     case V2DImode:
5897     case V2DFmode:
5898       emit_insn (gen_ashlsi3 (tmp, ops[2], GEN_INT (3)));
5899       break;
5900     default:
5901       abort ();
5902     }
5903   emit_insn (gen_rotqby_ti (rot, from, tmp));
5904
5905   emit_insn (gen_spu_convert (ops[0], rot));
5906 }
5907
5908 void
5909 spu_builtin_insert (rtx ops[])
5910 {
5911   enum machine_mode mode = GET_MODE (ops[0]);
5912   enum machine_mode imode = GET_MODE_INNER (mode);
5913   rtx mask = gen_reg_rtx (TImode);
5914   rtx offset;
5915
5916   if (GET_CODE (ops[3]) == CONST_INT)
5917     offset = GEN_INT (INTVAL (ops[3]) * GET_MODE_SIZE (imode));
5918   else
5919     {
5920       offset = gen_reg_rtx (SImode);
5921       emit_insn (gen_mulsi3
5922                  (offset, ops[3], GEN_INT (GET_MODE_SIZE (imode))));
5923     }
5924   emit_insn (gen_cpat
5925              (mask, stack_pointer_rtx, offset,
5926               GEN_INT (GET_MODE_SIZE (imode))));
5927   emit_insn (gen_shufb (ops[0], ops[1], ops[2], mask));
5928 }
5929
5930 void
5931 spu_builtin_promote (rtx ops[])
5932 {
5933   enum machine_mode mode, imode;
5934   rtx rot, from, offset;
5935   HOST_WIDE_INT pos;
5936
5937   mode = GET_MODE (ops[0]);
5938   imode = GET_MODE_INNER (mode);
5939
5940   from = gen_reg_rtx (TImode);
5941   rot = spu_gen_subreg (TImode, ops[0]);
5942
5943   emit_insn (gen_spu_convert (from, ops[1]));
5944
5945   if (GET_CODE (ops[2]) == CONST_INT)
5946     {
5947       pos = -GET_MODE_SIZE (imode) * INTVAL (ops[2]);
5948       if (GET_MODE_SIZE (imode) < 4)
5949         pos += 4 - GET_MODE_SIZE (imode);
5950       offset = GEN_INT (pos & 15);
5951     }
5952   else
5953     {
5954       offset = gen_reg_rtx (SImode);
5955       switch (mode)
5956         {
5957         case V16QImode:
5958           emit_insn (gen_subsi3 (offset, GEN_INT (3), ops[2]));
5959           break;
5960         case V8HImode:
5961           emit_insn (gen_subsi3 (offset, GEN_INT (1), ops[2]));
5962           emit_insn (gen_addsi3 (offset, offset, offset));
5963           break;
5964         case V4SFmode:
5965         case V4SImode:
5966           emit_insn (gen_subsi3 (offset, GEN_INT (0), ops[2]));
5967           emit_insn (gen_ashlsi3 (offset, offset, GEN_INT (2)));
5968           break;
5969         case V2DImode:
5970         case V2DFmode:
5971           emit_insn (gen_ashlsi3 (offset, ops[2], GEN_INT (3)));
5972           break;
5973         default:
5974           abort ();
5975         }
5976     }
5977   emit_insn (gen_rotqby_ti (rot, from, offset));
5978 }
5979
5980 static void
5981 spu_trampoline_init (rtx m_tramp, tree fndecl, rtx cxt)
5982 {
5983   rtx fnaddr = XEXP (DECL_RTL (fndecl), 0);
5984   rtx shuf = gen_reg_rtx (V4SImode);
5985   rtx insn = gen_reg_rtx (V4SImode);
5986   rtx shufc;
5987   rtx insnc;
5988   rtx mem;
5989
5990   fnaddr = force_reg (SImode, fnaddr);
5991   cxt = force_reg (SImode, cxt);
5992
5993   if (TARGET_LARGE_MEM)
5994     {
5995       rtx rotl = gen_reg_rtx (V4SImode);
5996       rtx mask = gen_reg_rtx (V4SImode);
5997       rtx bi = gen_reg_rtx (SImode);
5998       static unsigned char const shufa[16] = {
5999         2, 3, 0, 1, 18, 19, 16, 17,
6000         0, 1, 2, 3, 16, 17, 18, 19
6001       };
6002       static unsigned char const insna[16] = {
6003         0x41, 0, 0, 79,
6004         0x41, 0, 0, STATIC_CHAIN_REGNUM,
6005         0x60, 0x80, 0, 79,
6006         0x60, 0x80, 0, STATIC_CHAIN_REGNUM
6007       };
6008
6009       shufc = force_reg (TImode, array_to_constant (TImode, shufa));
6010       insnc = force_reg (V4SImode, array_to_constant (V4SImode, insna));
6011
6012       emit_insn (gen_shufb (shuf, fnaddr, cxt, shufc));
6013       emit_insn (gen_vrotlv4si3 (rotl, shuf, spu_const (V4SImode, 7)));
6014       emit_insn (gen_movv4si (mask, spu_const (V4SImode, 0xffff << 7)));
6015       emit_insn (gen_selb (insn, insnc, rotl, mask));
6016
6017       mem = adjust_address (m_tramp, V4SImode, 0);
6018       emit_move_insn (mem, insn);
6019
6020       emit_move_insn (bi, GEN_INT (0x35000000 + (79 << 7)));
6021       mem = adjust_address (m_tramp, Pmode, 16);
6022       emit_move_insn (mem, bi);
6023     }
6024   else
6025     {
6026       rtx scxt = gen_reg_rtx (SImode);
6027       rtx sfnaddr = gen_reg_rtx (SImode);
6028       static unsigned char const insna[16] = {
6029         0x42, 0, 0, STATIC_CHAIN_REGNUM,
6030         0x30, 0, 0, 0,
6031         0, 0, 0, 0,
6032         0, 0, 0, 0
6033       };
6034
6035       shufc = gen_reg_rtx (TImode);
6036       insnc = force_reg (V4SImode, array_to_constant (V4SImode, insna));
6037
6038       /* By or'ing all of cxt with the ila opcode we are assuming cxt
6039          fits 18 bits and the last 4 are zeros.  This will be true if
6040          the stack pointer is initialized to 0x3fff0 at program start,
6041          otherwise the ila instruction will be garbage. */
6042
6043       emit_insn (gen_ashlsi3 (scxt, cxt, GEN_INT (7)));
6044       emit_insn (gen_ashlsi3 (sfnaddr, fnaddr, GEN_INT (5)));
6045       emit_insn (gen_cpat
6046                  (shufc, stack_pointer_rtx, GEN_INT (4), GEN_INT (4)));
6047       emit_insn (gen_shufb (shuf, sfnaddr, scxt, shufc));
6048       emit_insn (gen_iorv4si3 (insn, insnc, shuf));
6049
6050       mem = adjust_address (m_tramp, V4SImode, 0);
6051       emit_move_insn (mem, insn);
6052     }
6053   emit_insn (gen_sync ());
6054 }
6055
6056 void
6057 spu_expand_sign_extend (rtx ops[])
6058 {
6059   unsigned char arr[16];
6060   rtx pat = gen_reg_rtx (TImode);
6061   rtx sign, c;
6062   int i, last;
6063   last = GET_MODE (ops[0]) == DImode ? 7 : 15;
6064   if (GET_MODE (ops[1]) == QImode)
6065     {
6066       sign = gen_reg_rtx (HImode);
6067       emit_insn (gen_extendqihi2 (sign, ops[1]));
6068       for (i = 0; i < 16; i++)
6069         arr[i] = 0x12;
6070       arr[last] = 0x13;
6071     }
6072   else
6073     {
6074       for (i = 0; i < 16; i++)
6075         arr[i] = 0x10;
6076       switch (GET_MODE (ops[1]))
6077         {
6078         case HImode:
6079           sign = gen_reg_rtx (SImode);
6080           emit_insn (gen_extendhisi2 (sign, ops[1]));
6081           arr[last] = 0x03;
6082           arr[last - 1] = 0x02;
6083           break;
6084         case SImode:
6085           sign = gen_reg_rtx (SImode);
6086           emit_insn (gen_ashrsi3 (sign, ops[1], GEN_INT (31)));
6087           for (i = 0; i < 4; i++)
6088             arr[last - i] = 3 - i;
6089           break;
6090         case DImode:
6091           sign = gen_reg_rtx (SImode);
6092           c = gen_reg_rtx (SImode);
6093           emit_insn (gen_spu_convert (c, ops[1]));
6094           emit_insn (gen_ashrsi3 (sign, c, GEN_INT (31)));
6095           for (i = 0; i < 8; i++)
6096             arr[last - i] = 7 - i;
6097           break;
6098         default:
6099           abort ();
6100         }
6101     }
6102   emit_move_insn (pat, array_to_constant (TImode, arr));
6103   emit_insn (gen_shufb (ops[0], ops[1], sign, pat));
6104 }
6105
6106 /* expand vector initialization. If there are any constant parts,
6107    load constant parts first. Then load any non-constant parts.  */
6108 void
6109 spu_expand_vector_init (rtx target, rtx vals)
6110 {
6111   enum machine_mode mode = GET_MODE (target);
6112   int n_elts = GET_MODE_NUNITS (mode);
6113   int n_var = 0;
6114   bool all_same = true;
6115   rtx first, x = NULL_RTX, first_constant = NULL_RTX;
6116   int i;
6117
6118   first = XVECEXP (vals, 0, 0); 
6119   for (i = 0; i < n_elts; ++i)
6120     {
6121       x = XVECEXP (vals, 0, i);
6122       if (!(CONST_INT_P (x)
6123             || GET_CODE (x) == CONST_DOUBLE
6124             || GET_CODE (x) == CONST_FIXED))
6125         ++n_var;
6126       else
6127         {
6128           if (first_constant == NULL_RTX)
6129             first_constant = x;
6130         }
6131       if (i > 0 && !rtx_equal_p (x, first))
6132         all_same = false;
6133     }
6134
6135   /* if all elements are the same, use splats to repeat elements */
6136   if (all_same)
6137     {
6138       if (!CONSTANT_P (first)
6139           && !register_operand (first, GET_MODE (x)))
6140         first = force_reg (GET_MODE (first), first);
6141       emit_insn (gen_spu_splats (target, first));
6142       return;
6143     }
6144
6145   /* load constant parts */
6146   if (n_var != n_elts)
6147     {
6148       if (n_var == 0)
6149         {
6150           emit_move_insn (target,
6151                           gen_rtx_CONST_VECTOR (mode, XVEC (vals, 0)));
6152         }
6153       else
6154         {
6155           rtx constant_parts_rtx = copy_rtx (vals);
6156
6157           gcc_assert (first_constant != NULL_RTX);
6158           /* fill empty slots with the first constant, this increases
6159              our chance of using splats in the recursive call below. */
6160           for (i = 0; i < n_elts; ++i)
6161             {
6162               x = XVECEXP (constant_parts_rtx, 0, i);
6163               if (!(CONST_INT_P (x)
6164                     || GET_CODE (x) == CONST_DOUBLE
6165                     || GET_CODE (x) == CONST_FIXED))
6166                 XVECEXP (constant_parts_rtx, 0, i) = first_constant;
6167             }
6168
6169           spu_expand_vector_init (target, constant_parts_rtx);
6170         }
6171     }
6172
6173   /* load variable parts */
6174   if (n_var != 0)
6175     {
6176       rtx insert_operands[4];
6177
6178       insert_operands[0] = target;
6179       insert_operands[2] = target;
6180       for (i = 0; i < n_elts; ++i)
6181         {
6182           x = XVECEXP (vals, 0, i);
6183           if (!(CONST_INT_P (x)
6184                 || GET_CODE (x) == CONST_DOUBLE
6185                 || GET_CODE (x) == CONST_FIXED))
6186             {
6187               if (!register_operand (x, GET_MODE (x)))
6188                 x = force_reg (GET_MODE (x), x);
6189               insert_operands[1] = x;
6190               insert_operands[3] = GEN_INT (i);
6191               spu_builtin_insert (insert_operands);
6192             }
6193         }
6194     }
6195 }
6196
6197 /* Return insn index for the vector compare instruction for given CODE,
6198    and DEST_MODE, OP_MODE. Return -1 if valid insn is not available.  */
6199
6200 static int
6201 get_vec_cmp_insn (enum rtx_code code,
6202                   enum machine_mode dest_mode,
6203                   enum machine_mode op_mode)
6204
6205 {
6206   switch (code)
6207     {
6208     case EQ:
6209       if (dest_mode == V16QImode && op_mode == V16QImode)
6210         return CODE_FOR_ceq_v16qi;
6211       if (dest_mode == V8HImode && op_mode == V8HImode)
6212         return CODE_FOR_ceq_v8hi;
6213       if (dest_mode == V4SImode && op_mode == V4SImode)
6214         return CODE_FOR_ceq_v4si;
6215       if (dest_mode == V4SImode && op_mode == V4SFmode)
6216         return CODE_FOR_ceq_v4sf;
6217       if (dest_mode == V2DImode && op_mode == V2DFmode)
6218         return CODE_FOR_ceq_v2df;
6219       break;
6220     case GT:
6221       if (dest_mode == V16QImode && op_mode == V16QImode)
6222         return CODE_FOR_cgt_v16qi;
6223       if (dest_mode == V8HImode && op_mode == V8HImode)
6224         return CODE_FOR_cgt_v8hi;
6225       if (dest_mode == V4SImode && op_mode == V4SImode)
6226         return CODE_FOR_cgt_v4si;
6227       if (dest_mode == V4SImode && op_mode == V4SFmode)
6228         return CODE_FOR_cgt_v4sf;
6229       if (dest_mode == V2DImode && op_mode == V2DFmode)
6230         return CODE_FOR_cgt_v2df;
6231       break;
6232     case GTU:
6233       if (dest_mode == V16QImode && op_mode == V16QImode)
6234         return CODE_FOR_clgt_v16qi;
6235       if (dest_mode == V8HImode && op_mode == V8HImode)
6236         return CODE_FOR_clgt_v8hi;
6237       if (dest_mode == V4SImode && op_mode == V4SImode)
6238         return CODE_FOR_clgt_v4si;
6239       break;
6240     default:
6241       break;
6242     }
6243   return -1;
6244 }
6245
6246 /* Emit vector compare for operands OP0 and OP1 using code RCODE.
6247    DMODE is expected destination mode. This is a recursive function.  */
6248
6249 static rtx
6250 spu_emit_vector_compare (enum rtx_code rcode,
6251                          rtx op0, rtx op1,
6252                          enum machine_mode dmode)
6253 {
6254   int vec_cmp_insn;
6255   rtx mask;
6256   enum machine_mode dest_mode;
6257   enum machine_mode op_mode = GET_MODE (op1);
6258
6259   gcc_assert (GET_MODE (op0) == GET_MODE (op1));
6260
6261   /* Floating point vector compare instructions uses destination V4SImode.
6262      Double floating point vector compare instructions uses destination V2DImode.
6263      Move destination to appropriate mode later.  */
6264   if (dmode == V4SFmode)
6265     dest_mode = V4SImode;
6266   else if (dmode == V2DFmode)
6267     dest_mode = V2DImode;
6268   else
6269     dest_mode = dmode;
6270
6271   mask = gen_reg_rtx (dest_mode);
6272   vec_cmp_insn = get_vec_cmp_insn (rcode, dest_mode, op_mode);
6273
6274   if (vec_cmp_insn == -1)
6275     {
6276       bool swap_operands = false;
6277       bool try_again = false;
6278       switch (rcode)
6279         {
6280         case LT:
6281           rcode = GT;
6282           swap_operands = true;
6283           try_again = true;
6284           break;
6285         case LTU:
6286           rcode = GTU;
6287           swap_operands = true;
6288           try_again = true;
6289           break;
6290         case NE:
6291           /* Treat A != B as ~(A==B).  */
6292           {
6293             enum insn_code nor_code;
6294             rtx eq_rtx = spu_emit_vector_compare (EQ, op0, op1, dest_mode);
6295             nor_code = optab_handler (one_cmpl_optab, dest_mode);
6296             gcc_assert (nor_code != CODE_FOR_nothing);
6297             emit_insn (GEN_FCN (nor_code) (mask, eq_rtx));
6298             if (dmode != dest_mode)
6299               {
6300                 rtx temp = gen_reg_rtx (dest_mode);
6301                 convert_move (temp, mask, 0);
6302                 return temp;
6303               }
6304             return mask;
6305           }
6306           break;
6307         case GE:
6308         case GEU:
6309         case LE:
6310         case LEU:
6311           /* Try GT/GTU/LT/LTU OR EQ */
6312           {
6313             rtx c_rtx, eq_rtx;
6314             enum insn_code ior_code;
6315             enum rtx_code new_code;
6316
6317             switch (rcode)
6318               {
6319               case GE:  new_code = GT;  break;
6320               case GEU: new_code = GTU; break;
6321               case LE:  new_code = LT;  break;
6322               case LEU: new_code = LTU; break;
6323               default:
6324                 gcc_unreachable ();
6325               }
6326
6327             c_rtx = spu_emit_vector_compare (new_code, op0, op1, dest_mode);
6328             eq_rtx = spu_emit_vector_compare (EQ, op0, op1, dest_mode);
6329
6330             ior_code = optab_handler (ior_optab, dest_mode);
6331             gcc_assert (ior_code != CODE_FOR_nothing);
6332             emit_insn (GEN_FCN (ior_code) (mask, c_rtx, eq_rtx));
6333             if (dmode != dest_mode)
6334               {
6335                 rtx temp = gen_reg_rtx (dest_mode);
6336                 convert_move (temp, mask, 0);
6337                 return temp;
6338               }
6339             return mask;
6340           }
6341           break;
6342         default:
6343           gcc_unreachable ();
6344         }
6345
6346       /* You only get two chances.  */
6347       if (try_again)
6348           vec_cmp_insn = get_vec_cmp_insn (rcode, dest_mode, op_mode);
6349
6350       gcc_assert (vec_cmp_insn != -1);
6351
6352       if (swap_operands)
6353         {
6354           rtx tmp;
6355           tmp = op0;
6356           op0 = op1;
6357           op1 = tmp;
6358         }
6359     }
6360
6361   emit_insn (GEN_FCN (vec_cmp_insn) (mask, op0, op1));
6362   if (dmode != dest_mode)
6363     {
6364       rtx temp = gen_reg_rtx (dest_mode);
6365       convert_move (temp, mask, 0);
6366       return temp;
6367     }
6368   return mask;
6369 }
6370
6371
6372 /* Emit vector conditional expression.
6373    DEST is destination. OP1 and OP2 are two VEC_COND_EXPR operands.
6374    CC_OP0 and CC_OP1 are the two operands for the relation operation COND.  */
6375
6376 int
6377 spu_emit_vector_cond_expr (rtx dest, rtx op1, rtx op2,
6378                            rtx cond, rtx cc_op0, rtx cc_op1)
6379 {   
6380   enum machine_mode dest_mode = GET_MODE (dest);
6381   enum rtx_code rcode = GET_CODE (cond);
6382   rtx mask;
6383     
6384   /* Get the vector mask for the given relational operations.  */
6385   mask = spu_emit_vector_compare (rcode, cc_op0, cc_op1, dest_mode);
6386
6387   emit_insn(gen_selb (dest, op2, op1, mask));
6388
6389   return 1;
6390 }
6391
6392 static rtx
6393 spu_force_reg (enum machine_mode mode, rtx op)
6394 {
6395   rtx x, r;
6396   if (GET_MODE (op) == VOIDmode || GET_MODE (op) == BLKmode)
6397     {
6398       if ((SCALAR_INT_MODE_P (mode) && GET_CODE (op) == CONST_INT)
6399           || GET_MODE (op) == BLKmode)
6400         return force_reg (mode, convert_to_mode (mode, op, 0));
6401       abort ();
6402     }
6403
6404   r = force_reg (GET_MODE (op), op);
6405   if (GET_MODE_SIZE (GET_MODE (op)) == GET_MODE_SIZE (mode))
6406     {
6407       x = simplify_gen_subreg (mode, r, GET_MODE (op), 0);
6408       if (x)
6409         return x;
6410     }
6411
6412   x = gen_reg_rtx (mode);
6413   emit_insn (gen_spu_convert (x, r));
6414   return x;
6415 }
6416
6417 static void
6418 spu_check_builtin_parm (struct spu_builtin_description *d, rtx op, int p)
6419 {
6420   HOST_WIDE_INT v = 0;
6421   int lsbits;
6422   /* Check the range of immediate operands. */
6423   if (p >= SPU_BTI_7 && p <= SPU_BTI_U18)
6424     {
6425       int range = p - SPU_BTI_7;
6426
6427       if (!CONSTANT_P (op))
6428         error ("%s expects an integer literal in the range [%d, %d]",
6429                d->name,
6430                spu_builtin_range[range].low, spu_builtin_range[range].high);
6431
6432       if (GET_CODE (op) == CONST
6433           && (GET_CODE (XEXP (op, 0)) == PLUS
6434               || GET_CODE (XEXP (op, 0)) == MINUS))
6435         {
6436           v = INTVAL (XEXP (XEXP (op, 0), 1));
6437           op = XEXP (XEXP (op, 0), 0);
6438         }
6439       else if (GET_CODE (op) == CONST_INT)
6440         v = INTVAL (op);
6441       else if (GET_CODE (op) == CONST_VECTOR
6442                && GET_CODE (CONST_VECTOR_ELT (op, 0)) == CONST_INT)
6443         v = INTVAL (CONST_VECTOR_ELT (op, 0));
6444
6445       /* The default for v is 0 which is valid in every range. */
6446       if (v < spu_builtin_range[range].low
6447           || v > spu_builtin_range[range].high)
6448         error ("%s expects an integer literal in the range [%d, %d]. (%wd)",
6449                d->name,
6450                spu_builtin_range[range].low, spu_builtin_range[range].high,
6451                v);
6452
6453       switch (p)
6454         {
6455         case SPU_BTI_S10_4:
6456           lsbits = 4;
6457           break;
6458         case SPU_BTI_U16_2:
6459           /* This is only used in lqa, and stqa.  Even though the insns
6460              encode 16 bits of the address (all but the 2 least
6461              significant), only 14 bits are used because it is masked to
6462              be 16 byte aligned. */
6463           lsbits = 4;
6464           break;
6465         case SPU_BTI_S16_2:
6466           /* This is used for lqr and stqr. */
6467           lsbits = 2;
6468           break;
6469         default:
6470           lsbits = 0;
6471         }
6472
6473       if (GET_CODE (op) == LABEL_REF
6474           || (GET_CODE (op) == SYMBOL_REF
6475               && SYMBOL_REF_FUNCTION_P (op))
6476           || (v & ((1 << lsbits) - 1)) != 0)
6477         warning (0, "%d least significant bits of %s are ignored", lsbits,
6478                  d->name);
6479     }
6480 }
6481
6482
6483 static int
6484 expand_builtin_args (struct spu_builtin_description *d, tree exp,
6485                      rtx target, rtx ops[])
6486 {
6487   enum insn_code icode = (enum insn_code) d->icode;
6488   int i = 0, a;
6489
6490   /* Expand the arguments into rtl. */
6491
6492   if (d->parm[0] != SPU_BTI_VOID)
6493     ops[i++] = target;
6494
6495   for (a = 0; d->parm[a+1] != SPU_BTI_END_OF_PARAMS; i++, a++)
6496     {
6497       tree arg = CALL_EXPR_ARG (exp, a);
6498       if (arg == 0)
6499         abort ();
6500       ops[i] = expand_expr (arg, NULL_RTX, VOIDmode, EXPAND_NORMAL);
6501     }
6502
6503   /* The insn pattern may have additional operands (SCRATCH).
6504      Return the number of actual non-SCRATCH operands.  */
6505   gcc_assert (i <= insn_data[icode].n_operands);
6506   return i;
6507 }
6508
6509 static rtx
6510 spu_expand_builtin_1 (struct spu_builtin_description *d,
6511                       tree exp, rtx target)
6512 {
6513   rtx pat;
6514   rtx ops[8];
6515   enum insn_code icode = (enum insn_code) d->icode;
6516   enum machine_mode mode, tmode;
6517   int i, p;
6518   int n_operands;
6519   tree return_type;
6520
6521   /* Set up ops[] with values from arglist. */
6522   n_operands = expand_builtin_args (d, exp, target, ops);
6523
6524   /* Handle the target operand which must be operand 0. */
6525   i = 0;
6526   if (d->parm[0] != SPU_BTI_VOID)
6527     {
6528
6529       /* We prefer the mode specified for the match_operand otherwise
6530          use the mode from the builtin function prototype. */
6531       tmode = insn_data[d->icode].operand[0].mode;
6532       if (tmode == VOIDmode)
6533         tmode = TYPE_MODE (spu_builtin_types[d->parm[0]]);
6534
6535       /* Try to use target because not using it can lead to extra copies
6536          and when we are using all of the registers extra copies leads
6537          to extra spills.  */
6538       if (target && GET_CODE (target) == REG && GET_MODE (target) == tmode)
6539         ops[0] = target;
6540       else
6541         target = ops[0] = gen_reg_rtx (tmode);
6542
6543       if (!(*insn_data[icode].operand[0].predicate) (ops[0], tmode))
6544         abort ();
6545
6546       i++;
6547     }
6548
6549   if (d->fcode == SPU_MASK_FOR_LOAD)
6550     {
6551       enum machine_mode mode = insn_data[icode].operand[1].mode;
6552       tree arg;
6553       rtx addr, op, pat;
6554
6555       /* get addr */
6556       arg = CALL_EXPR_ARG (exp, 0);
6557       gcc_assert (POINTER_TYPE_P (TREE_TYPE (arg)));
6558       op = expand_expr (arg, NULL_RTX, Pmode, EXPAND_NORMAL);
6559       addr = memory_address (mode, op);
6560
6561       /* negate addr */
6562       op = gen_reg_rtx (GET_MODE (addr));
6563       emit_insn (gen_rtx_SET (VOIDmode, op,
6564                  gen_rtx_NEG (GET_MODE (addr), addr)));
6565       op = gen_rtx_MEM (mode, op);
6566
6567       pat = GEN_FCN (icode) (target, op);
6568       if (!pat) 
6569         return 0;
6570       emit_insn (pat);
6571       return target;
6572     }   
6573
6574   /* Ignore align_hint, but still expand it's args in case they have
6575      side effects. */
6576   if (icode == CODE_FOR_spu_align_hint)
6577     return 0;
6578
6579   /* Handle the rest of the operands. */
6580   for (p = 1; i < n_operands; i++, p++)
6581     {
6582       if (insn_data[d->icode].operand[i].mode != VOIDmode)
6583         mode = insn_data[d->icode].operand[i].mode;
6584       else
6585         mode = TYPE_MODE (spu_builtin_types[d->parm[i]]);
6586
6587       /* mode can be VOIDmode here for labels */
6588
6589       /* For specific intrinsics with an immediate operand, e.g.,
6590          si_ai(), we sometimes need to convert the scalar argument to a
6591          vector argument by splatting the scalar. */
6592       if (VECTOR_MODE_P (mode)
6593           && (GET_CODE (ops[i]) == CONST_INT
6594               || GET_MODE_CLASS (GET_MODE (ops[i])) == MODE_INT
6595               || GET_MODE_CLASS (GET_MODE (ops[i])) == MODE_FLOAT))
6596         {
6597           if (GET_CODE (ops[i]) == CONST_INT)
6598             ops[i] = spu_const (mode, INTVAL (ops[i]));
6599           else
6600             {
6601               rtx reg = gen_reg_rtx (mode);
6602               enum machine_mode imode = GET_MODE_INNER (mode);
6603               if (!spu_nonmem_operand (ops[i], GET_MODE (ops[i])))
6604                 ops[i] = force_reg (GET_MODE (ops[i]), ops[i]);
6605               if (imode != GET_MODE (ops[i]))
6606                 ops[i] = convert_to_mode (imode, ops[i],
6607                                           TYPE_UNSIGNED (spu_builtin_types
6608                                                          [d->parm[i]]));
6609               emit_insn (gen_spu_splats (reg, ops[i]));
6610               ops[i] = reg;
6611             }
6612         }
6613
6614       spu_check_builtin_parm (d, ops[i], d->parm[p]);
6615
6616       if (!(*insn_data[icode].operand[i].predicate) (ops[i], mode))
6617         ops[i] = spu_force_reg (mode, ops[i]);
6618     }
6619
6620   switch (n_operands)
6621     {
6622     case 0:
6623       pat = GEN_FCN (icode) (0);
6624       break;
6625     case 1:
6626       pat = GEN_FCN (icode) (ops[0]);
6627       break;
6628     case 2:
6629       pat = GEN_FCN (icode) (ops[0], ops[1]);
6630       break;
6631     case 3:
6632       pat = GEN_FCN (icode) (ops[0], ops[1], ops[2]);
6633       break;
6634     case 4:
6635       pat = GEN_FCN (icode) (ops[0], ops[1], ops[2], ops[3]);
6636       break;
6637     case 5:
6638       pat = GEN_FCN (icode) (ops[0], ops[1], ops[2], ops[3], ops[4]);
6639       break;
6640     case 6:
6641       pat = GEN_FCN (icode) (ops[0], ops[1], ops[2], ops[3], ops[4], ops[5]);
6642       break;
6643     default:
6644       abort ();
6645     }
6646
6647   if (!pat)
6648     abort ();
6649
6650   if (d->type == B_CALL || d->type == B_BISLED)
6651     emit_call_insn (pat);
6652   else if (d->type == B_JUMP)
6653     {
6654       emit_jump_insn (pat);
6655       emit_barrier ();
6656     }
6657   else
6658     emit_insn (pat);
6659
6660   return_type = spu_builtin_types[d->parm[0]];
6661   if (d->parm[0] != SPU_BTI_VOID
6662       && GET_MODE (target) != TYPE_MODE (return_type))
6663     {
6664       /* target is the return value.  It should always be the mode of
6665          the builtin function prototype. */
6666       target = spu_force_reg (TYPE_MODE (return_type), target);
6667     }
6668
6669   return target;
6670 }
6671
6672 rtx
6673 spu_expand_builtin (tree exp,
6674                     rtx target,
6675                     rtx subtarget ATTRIBUTE_UNUSED,
6676                     enum machine_mode mode ATTRIBUTE_UNUSED,
6677                     int ignore ATTRIBUTE_UNUSED)
6678 {
6679   tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
6680   unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
6681   struct spu_builtin_description *d;
6682
6683   if (fcode < NUM_SPU_BUILTINS)
6684     {
6685       d = &spu_builtins[fcode];
6686
6687       return spu_expand_builtin_1 (d, exp, target);
6688     }
6689   abort ();
6690 }
6691
6692 /* Implement targetm.vectorize.builtin_mul_widen_even.  */
6693 static tree
6694 spu_builtin_mul_widen_even (tree type)
6695 {
6696   switch (TYPE_MODE (type))
6697     {
6698     case V8HImode:
6699       if (TYPE_UNSIGNED (type))
6700         return spu_builtin_decls[SPU_MULE_0];
6701       else
6702         return spu_builtin_decls[SPU_MULE_1];
6703       break;
6704     default:
6705       return NULL_TREE;
6706     }
6707 }
6708
6709 /* Implement targetm.vectorize.builtin_mul_widen_odd.  */
6710 static tree
6711 spu_builtin_mul_widen_odd (tree type)
6712 {
6713   switch (TYPE_MODE (type))
6714     {
6715     case V8HImode:
6716       if (TYPE_UNSIGNED (type))
6717         return spu_builtin_decls[SPU_MULO_1];
6718       else
6719         return spu_builtin_decls[SPU_MULO_0]; 
6720       break;
6721     default:
6722       return NULL_TREE;
6723     }
6724 }
6725
6726 /* Implement targetm.vectorize.builtin_mask_for_load.  */
6727 static tree
6728 spu_builtin_mask_for_load (void)
6729 {
6730   return spu_builtin_decls[SPU_MASK_FOR_LOAD];
6731 }
6732
6733 /* Implement targetm.vectorize.builtin_vectorization_cost.  */
6734 static int 
6735 spu_builtin_vectorization_cost (enum vect_cost_for_stmt type_of_cost,
6736                                 tree vectype ATTRIBUTE_UNUSED,
6737                                 int misalign ATTRIBUTE_UNUSED)
6738 {
6739   switch (type_of_cost)
6740     {
6741       case scalar_stmt:
6742       case vector_stmt:
6743       case vector_load:
6744       case vector_store:
6745       case vec_to_scalar:
6746       case scalar_to_vec:
6747       case cond_branch_not_taken:
6748       case vec_perm:
6749         return 1;
6750
6751       case scalar_store:
6752         return 10;
6753
6754       case scalar_load:
6755         /* Load + rotate.  */
6756         return 2;
6757
6758       case unaligned_load:
6759         return 2;
6760
6761       case cond_branch_taken:
6762         return 6;
6763
6764       default:
6765         gcc_unreachable ();
6766     }
6767 }
6768
6769 /* Return true iff, data reference of TYPE can reach vector alignment (16)
6770    after applying N number of iterations.  This routine does not determine
6771    how may iterations are required to reach desired alignment.  */
6772
6773 static bool
6774 spu_vector_alignment_reachable (const_tree type ATTRIBUTE_UNUSED, bool is_packed)
6775 {
6776   if (is_packed)
6777     return false;
6778
6779   /* All other types are naturally aligned.  */
6780   return true;
6781 }
6782
6783 /* Implement targetm.vectorize.builtin_vec_perm.  */
6784 tree
6785 spu_builtin_vec_perm (tree type, tree *mask_element_type)
6786 {
6787   *mask_element_type = unsigned_char_type_node;
6788
6789   switch (TYPE_MODE (type))
6790     {
6791     case V16QImode:
6792       if (TYPE_UNSIGNED (type))
6793         return spu_builtin_decls[SPU_SHUFFLE_0];
6794       else
6795         return spu_builtin_decls[SPU_SHUFFLE_1];
6796
6797     case V8HImode:
6798       if (TYPE_UNSIGNED (type))
6799         return spu_builtin_decls[SPU_SHUFFLE_2];
6800       else
6801         return spu_builtin_decls[SPU_SHUFFLE_3];
6802
6803     case V4SImode:
6804       if (TYPE_UNSIGNED (type))
6805         return spu_builtin_decls[SPU_SHUFFLE_4];
6806       else
6807         return spu_builtin_decls[SPU_SHUFFLE_5];
6808
6809     case V2DImode:
6810       if (TYPE_UNSIGNED (type))
6811         return spu_builtin_decls[SPU_SHUFFLE_6];
6812       else
6813         return spu_builtin_decls[SPU_SHUFFLE_7];
6814
6815     case V4SFmode:
6816       return spu_builtin_decls[SPU_SHUFFLE_8];
6817
6818     case V2DFmode:
6819       return spu_builtin_decls[SPU_SHUFFLE_9];
6820
6821     default:
6822       return NULL_TREE;
6823     }
6824 }
6825
6826 /* Return the appropriate mode for a named address pointer.  */
6827 static enum machine_mode
6828 spu_addr_space_pointer_mode (addr_space_t addrspace)
6829 {
6830   switch (addrspace)
6831     {
6832     case ADDR_SPACE_GENERIC:
6833       return ptr_mode;
6834     case ADDR_SPACE_EA:
6835       return EAmode;
6836     default:
6837       gcc_unreachable ();
6838     }
6839 }
6840
6841 /* Return the appropriate mode for a named address address.  */
6842 static enum machine_mode
6843 spu_addr_space_address_mode (addr_space_t addrspace)
6844 {
6845   switch (addrspace)
6846     {
6847     case ADDR_SPACE_GENERIC:
6848       return Pmode;
6849     case ADDR_SPACE_EA:
6850       return EAmode;
6851     default:
6852       gcc_unreachable ();
6853     }
6854 }
6855
6856 /* Determine if one named address space is a subset of another.  */
6857
6858 static bool
6859 spu_addr_space_subset_p (addr_space_t subset, addr_space_t superset)
6860 {
6861   gcc_assert (subset == ADDR_SPACE_GENERIC || subset == ADDR_SPACE_EA);
6862   gcc_assert (superset == ADDR_SPACE_GENERIC || superset == ADDR_SPACE_EA);
6863
6864   if (subset == superset)
6865     return true;
6866
6867   /* If we have -mno-address-space-conversion, treat __ea and generic as not
6868      being subsets but instead as disjoint address spaces.  */
6869   else if (!TARGET_ADDRESS_SPACE_CONVERSION)
6870     return false;
6871
6872   else
6873     return (subset == ADDR_SPACE_GENERIC && superset == ADDR_SPACE_EA);
6874 }
6875
6876 /* Convert from one address space to another.  */
6877 static rtx
6878 spu_addr_space_convert (rtx op, tree from_type, tree to_type)
6879 {
6880   addr_space_t from_as = TYPE_ADDR_SPACE (TREE_TYPE (from_type));
6881   addr_space_t to_as = TYPE_ADDR_SPACE (TREE_TYPE (to_type));
6882
6883   gcc_assert (from_as == ADDR_SPACE_GENERIC || from_as == ADDR_SPACE_EA);
6884   gcc_assert (to_as == ADDR_SPACE_GENERIC || to_as == ADDR_SPACE_EA);
6885
6886   if (to_as == ADDR_SPACE_GENERIC && from_as == ADDR_SPACE_EA)
6887     {
6888       rtx result, ls;
6889
6890       ls = gen_const_mem (DImode,
6891                           gen_rtx_SYMBOL_REF (Pmode, "__ea_local_store"));
6892       set_mem_align (ls, 128);
6893
6894       result = gen_reg_rtx (Pmode);
6895       ls = force_reg (Pmode, convert_modes (Pmode, DImode, ls, 1));
6896       op = force_reg (Pmode, convert_modes (Pmode, EAmode, op, 1));
6897       ls = emit_conditional_move (ls, NE, op, const0_rtx, Pmode,
6898                                           ls, const0_rtx, Pmode, 1);
6899
6900       emit_insn (gen_subsi3 (result, op, ls));
6901
6902       return result;
6903     }
6904
6905   else if (to_as == ADDR_SPACE_EA && from_as == ADDR_SPACE_GENERIC)
6906     {
6907       rtx result, ls;
6908
6909       ls = gen_const_mem (DImode,
6910                           gen_rtx_SYMBOL_REF (Pmode, "__ea_local_store"));
6911       set_mem_align (ls, 128);
6912
6913       result = gen_reg_rtx (EAmode);
6914       ls = force_reg (EAmode, convert_modes (EAmode, DImode, ls, 1));
6915       op = force_reg (Pmode, op);
6916       ls = emit_conditional_move (ls, NE, op, const0_rtx, Pmode,
6917                                           ls, const0_rtx, EAmode, 1);
6918       op = force_reg (EAmode, convert_modes (EAmode, Pmode, op, 1));
6919
6920       if (EAmode == SImode)
6921         emit_insn (gen_addsi3 (result, op, ls));
6922       else
6923         emit_insn (gen_adddi3 (result, op, ls));
6924
6925       return result;
6926     }
6927
6928   else
6929     gcc_unreachable ();
6930 }
6931
6932
6933 /* Count the total number of instructions in each pipe and return the
6934    maximum, which is used as the Minimum Iteration Interval (MII)
6935    in the modulo scheduler.  get_pipe() will return -2, -1, 0, or 1.
6936    -2 are instructions that can go in pipe0 or pipe1.  */
6937 static int
6938 spu_sms_res_mii (struct ddg *g)
6939 {
6940   int i;
6941   unsigned t[4] = {0, 0, 0, 0};
6942
6943   for (i = 0; i < g->num_nodes; i++)
6944     {
6945       rtx insn = g->nodes[i].insn;
6946       int p = get_pipe (insn) + 2;
6947
6948       gcc_assert (p >= 0);
6949       gcc_assert (p < 4);
6950
6951       t[p]++;
6952       if (dump_file && INSN_P (insn))
6953             fprintf (dump_file, "i%d %s %d %d\n",
6954                      INSN_UID (insn),
6955                      insn_data[INSN_CODE(insn)].name,
6956                      p, t[p]);
6957     }
6958   if (dump_file)
6959     fprintf (dump_file, "%d %d %d %d\n", t[0], t[1], t[2], t[3]);
6960
6961   return MAX ((t[0] + t[2] + t[3] + 1) / 2, MAX (t[2], t[3]));
6962 }
6963
6964
6965 void
6966 spu_init_expanders (void)
6967 {
6968   if (cfun)
6969     {
6970       rtx r0, r1;
6971       /* HARD_FRAME_REGISTER is only 128 bit aligned when
6972          frame_pointer_needed is true.  We don't know that until we're
6973          expanding the prologue. */
6974       REGNO_POINTER_ALIGN (HARD_FRAME_POINTER_REGNUM) = 8;
6975
6976       /* A number of passes use LAST_VIRTUAL_REGISTER+1 and
6977          LAST_VIRTUAL_REGISTER+2 to test the back-end.  We want them
6978          to be treated as aligned, so generate them here. */
6979       r0 = gen_reg_rtx (SImode);
6980       r1 = gen_reg_rtx (SImode);
6981       mark_reg_pointer (r0, 128);
6982       mark_reg_pointer (r1, 128);
6983       gcc_assert (REGNO (r0) == LAST_VIRTUAL_REGISTER + 1
6984                   && REGNO (r1) == LAST_VIRTUAL_REGISTER + 2);
6985     }
6986 }
6987
6988 static enum machine_mode
6989 spu_libgcc_cmp_return_mode (void)
6990 {
6991
6992 /* For SPU word mode is TI mode so it is better to use SImode
6993    for compare returns.  */
6994   return SImode;
6995 }
6996
6997 static enum machine_mode
6998 spu_libgcc_shift_count_mode (void)
6999 {
7000 /* For SPU word mode is TI mode so it is better to use SImode
7001    for shift counts.  */
7002   return SImode;
7003 }
7004
7005 /* An early place to adjust some flags after GCC has finished processing
7006  * them. */
7007 static void
7008 asm_file_start (void)
7009 {
7010   /* Variable tracking should be run after all optimizations which
7011      change order of insns.  It also needs a valid CFG. */
7012   spu_flag_var_tracking = flag_var_tracking;
7013   flag_var_tracking = 0;
7014
7015   default_file_start ();
7016 }
7017
7018 /* Implement targetm.section_type_flags.  */
7019 static unsigned int
7020 spu_section_type_flags (tree decl, const char *name, int reloc)
7021 {
7022   /* .toe needs to have type @nobits.  */
7023   if (strcmp (name, ".toe") == 0)
7024     return SECTION_BSS;
7025   /* Don't load _ea into the current address space.  */
7026   if (strcmp (name, "._ea") == 0)
7027     return SECTION_WRITE | SECTION_DEBUG;
7028   return default_section_type_flags (decl, name, reloc);
7029 }
7030
7031 /* Implement targetm.select_section.  */
7032 static section *
7033 spu_select_section (tree decl, int reloc, unsigned HOST_WIDE_INT align)
7034 {
7035   /* Variables and constants defined in the __ea address space
7036      go into a special section named "._ea".  */
7037   if (TREE_TYPE (decl) != error_mark_node
7038       && TYPE_ADDR_SPACE (TREE_TYPE (decl)) == ADDR_SPACE_EA)
7039     {
7040       /* We might get called with string constants, but get_named_section
7041          doesn't like them as they are not DECLs.  Also, we need to set
7042          flags in that case.  */
7043       if (!DECL_P (decl))
7044         return get_section ("._ea", SECTION_WRITE | SECTION_DEBUG, NULL);
7045
7046       return get_named_section (decl, "._ea", reloc);
7047     }
7048
7049   return default_elf_select_section (decl, reloc, align);
7050 }
7051
7052 /* Implement targetm.unique_section.  */
7053 static void
7054 spu_unique_section (tree decl, int reloc)
7055 {
7056   /* We don't support unique section names in the __ea address
7057      space for now.  */
7058   if (TREE_TYPE (decl) != error_mark_node
7059       && TYPE_ADDR_SPACE (TREE_TYPE (decl)) != 0)
7060     return;
7061
7062   default_unique_section (decl, reloc);
7063 }
7064
7065 /* Generate a constant or register which contains 2^SCALE.  We assume
7066    the result is valid for MODE.  Currently, MODE must be V4SFmode and
7067    SCALE must be SImode. */
7068 rtx
7069 spu_gen_exp2 (enum machine_mode mode, rtx scale)
7070 {
7071   gcc_assert (mode == V4SFmode);
7072   gcc_assert (GET_MODE (scale) == SImode || GET_CODE (scale) == CONST_INT);
7073   if (GET_CODE (scale) != CONST_INT)
7074     {
7075       /* unsigned int exp = (127 + scale) << 23;
7076         __vector float m = (__vector float) spu_splats (exp); */
7077       rtx reg = force_reg (SImode, scale);
7078       rtx exp = gen_reg_rtx (SImode);
7079       rtx mul = gen_reg_rtx (mode);
7080       emit_insn (gen_addsi3 (exp, reg, GEN_INT (127)));
7081       emit_insn (gen_ashlsi3 (exp, exp, GEN_INT (23)));
7082       emit_insn (gen_spu_splats (mul, gen_rtx_SUBREG (GET_MODE_INNER (mode), exp, 0)));
7083       return mul;
7084     }
7085   else 
7086     {
7087       HOST_WIDE_INT exp = 127 + INTVAL (scale);
7088       unsigned char arr[16];
7089       arr[0] = arr[4] = arr[8] = arr[12] = exp >> 1;
7090       arr[1] = arr[5] = arr[9] = arr[13] = exp << 7;
7091       arr[2] = arr[6] = arr[10] = arr[14] = 0;
7092       arr[3] = arr[7] = arr[11] = arr[15] = 0;
7093       return array_to_constant (mode, arr);
7094     }
7095 }
7096
7097 /* After reload, just change the convert into a move instruction
7098    or a dead instruction. */
7099 void
7100 spu_split_convert (rtx ops[])
7101 {
7102   if (REGNO (ops[0]) == REGNO (ops[1]))
7103     emit_note (NOTE_INSN_DELETED);
7104   else
7105     {
7106       /* Use TImode always as this might help hard reg copyprop.  */
7107       rtx op0 = gen_rtx_REG (TImode, REGNO (ops[0]));
7108       rtx op1 = gen_rtx_REG (TImode, REGNO (ops[1]));
7109       emit_insn (gen_move_insn (op0, op1));
7110     }
7111 }
7112
7113 void
7114 spu_function_profiler (FILE * file, int labelno ATTRIBUTE_UNUSED)
7115 {
7116   fprintf (file, "# profile\n");
7117   fprintf (file, "brsl $75,  _mcount\n");
7118 }
7119
7120 #include "gt-spu.h"