xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/config/tilepro/tilepro.c (revision fdd524d4ccd2bb0c6f67401e938dabf773eb0372)
1 /* Subroutines used for code generation on the Tilera TILEPro.
2    Copyright (C) 2011-2013 Free Software Foundation, Inc.
3    Contributed by Walter Lee (walt@tilera.com)
4 
5    This file is part of GCC.
6 
7    GCC is free software; you can redistribute it and/or modify it
8    under the terms of the GNU General Public License as published
9    by the Free Software Foundation; either version 3, or (at your
10    option) any later version.
11 
12    GCC is distributed in the hope that it will be useful, but WITHOUT
13    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
15    License for more details.
16 
17    You should have received a copy of the GNU General Public License
18    along with GCC; see the file COPYING3.  If not see
19    <http://www.gnu.org/licenses/>.  */
20 
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "tm.h"
25 #include "rtl.h"
26 #include "regs.h"
27 #include "insn-config.h"
28 #include "output.h"
29 #include "insn-attr.h"
30 #include "recog.h"
31 #include "expr.h"
32 #include "langhooks.h"
33 #include "optabs.h"
34 #include "sched-int.h"
35 #include "sel-sched.h"
36 #include "tm_p.h"
37 #include "tm-constrs.h"
38 #include "target.h"
39 #include "target-def.h"
40 #include "function.h"
41 #include "dwarf2.h"
42 #include "timevar.h"
43 #include "gimple.h"
44 #include "cfgloop.h"
45 #include "tilepro-builtins.h"
46 #include "tilepro-multiply.h"
47 #include "diagnostic.h"
48 
49 /* SYMBOL_REF for GOT */
50 static GTY(()) rtx g_got_symbol = NULL;
51 
52 /* In case of a POST_INC or POST_DEC memory reference, we must report
53    the mode of the memory reference from TARGET_PRINT_OPERAND to
54    TARGET_PRINT_OPERAND_ADDRESS.  */
55 static enum machine_mode output_memory_reference_mode;
56 
57 /* Report whether we're printing out the first address fragment of a
58    POST_INC or POST_DEC memory reference, from TARGET_PRINT_OPERAND to
59    TARGET_PRINT_OPERAND_ADDRESS.  */
60 static bool output_memory_autoinc_first;
61 
62 
63 
64 /* Option handling  */
65 
66 /* Implement TARGET_OPTION_OVERRIDE.  */
67 static void
68 tilepro_option_override (void)
69 {
70   /* When modulo scheduling is enabled, we still rely on regular
71      scheduler for bundling.  */
72   if (flag_modulo_sched)
73     flag_resched_modulo_sched = 1;
74 }
75 
76 
77 
78 /* Implement TARGET_SCALAR_MODE_SUPPORTED_P.  */
79 static bool
80 tilepro_scalar_mode_supported_p (enum machine_mode mode)
81 {
82   switch (mode)
83     {
84     case QImode:
85     case HImode:
86     case SImode:
87     case DImode:
88       return true;
89 
90     case SFmode:
91     case DFmode:
92       return true;
93 
94     default:
95       return false;
96     }
97 }
98 
99 
100 /* Implement TARGET_VECTOR_MODE_SUPPORTED_P.  */
101 static bool
102 tile_vector_mode_supported_p (enum machine_mode mode)
103 {
104   return mode == V4QImode || mode == V2HImode;
105 }
106 
107 
108 /* Implement TARGET_CANNOT_FORCE_CONST_MEM.  */
109 static bool
110 tilepro_cannot_force_const_mem (enum machine_mode mode ATTRIBUTE_UNUSED,
111 				rtx x ATTRIBUTE_UNUSED)
112 {
113   return true;
114 }
115 
116 
117 /* Implement TARGET_FUNCTION_OK_FOR_SIBCALL.  */
118 static bool
119 tilepro_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED)
120 {
121   return decl != NULL;
122 }
123 
124 
125 /* Implement TARGET_PASS_BY_REFERENCE.  Variable sized types are
126    passed by reference.  */
127 static bool
128 tilepro_pass_by_reference (cumulative_args_t cum ATTRIBUTE_UNUSED,
129 			   enum machine_mode mode ATTRIBUTE_UNUSED,
130 			   const_tree type, bool named ATTRIBUTE_UNUSED)
131 {
132   return (type && TYPE_SIZE (type)
133 	  && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST);
134 }
135 
136 
137 /* Implement TARGET_RETURN_IN_MEMORY.  */
138 static bool
139 tilepro_return_in_memory (const_tree type, const_tree fndecl ATTRIBUTE_UNUSED)
140 {
141   return !IN_RANGE (int_size_in_bytes (type),
142 		    0, TILEPRO_NUM_RETURN_REGS * UNITS_PER_WORD);
143 }
144 
145 
146 /* Implement TARGET_FUNCTION_ARG_BOUNDARY.  */
147 static unsigned int
148 tilepro_function_arg_boundary (enum machine_mode mode, const_tree type)
149 {
150   unsigned int alignment;
151 
152   alignment = type ? TYPE_ALIGN (type) : GET_MODE_ALIGNMENT (mode);
153   if (alignment < PARM_BOUNDARY)
154     alignment = PARM_BOUNDARY;
155   if (alignment > STACK_BOUNDARY)
156     alignment = STACK_BOUNDARY;
157   return alignment;
158 }
159 
160 
161 /* Implement TARGET_FUNCTION_ARG.  */
162 static rtx
163 tilepro_function_arg (cumulative_args_t cum_v,
164 		      enum machine_mode mode,
165 		      const_tree type, bool named ATTRIBUTE_UNUSED)
166 {
167   CUMULATIVE_ARGS cum = *get_cumulative_args (cum_v);
168   int byte_size = ((mode == BLKmode)
169 		   ? int_size_in_bytes (type) : GET_MODE_SIZE (mode));
170   bool doubleword_aligned_p;
171 
172   if (cum >= TILEPRO_NUM_ARG_REGS)
173     return NULL_RTX;
174 
175   /* See whether the argument has doubleword alignment.  */
176   doubleword_aligned_p =
177     tilepro_function_arg_boundary (mode, type) > BITS_PER_WORD;
178 
179   if (doubleword_aligned_p)
180     cum += cum & 1;
181 
182   /* The ABI does not allow parameters to be passed partially in reg
183      and partially in stack.  */
184   if ((cum + (byte_size + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
185       > TILEPRO_NUM_ARG_REGS)
186     return NULL_RTX;
187 
188   return gen_rtx_REG (mode, cum);
189 }
190 
191 
192 /* Implement TARGET_FUNCTION_ARG_ADVANCE.  */
193 static void
194 tilepro_function_arg_advance (cumulative_args_t cum_v,
195 			      enum machine_mode mode,
196 			      const_tree type, bool named ATTRIBUTE_UNUSED)
197 {
198   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
199 
200   int byte_size = ((mode == BLKmode)
201 		   ? int_size_in_bytes (type) : GET_MODE_SIZE (mode));
202   int word_size = (byte_size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
203   bool doubleword_aligned_p;
204 
205   /* See whether the argument has doubleword alignment.  */
206   doubleword_aligned_p =
207     tilepro_function_arg_boundary (mode, type) > BITS_PER_WORD;
208 
209   if (doubleword_aligned_p)
210     *cum += *cum & 1;
211 
212   /* If the current argument does not fit in the pretend_args space,
213      skip over it.  */
214   if (*cum < TILEPRO_NUM_ARG_REGS
215       && *cum + word_size > TILEPRO_NUM_ARG_REGS)
216     *cum = TILEPRO_NUM_ARG_REGS;
217 
218   *cum += word_size;
219 }
220 
221 
222 /* Implement TARGET_FUNCTION_VALUE.  */
223 static rtx
224 tilepro_function_value (const_tree valtype, const_tree fn_decl_or_type,
225 			bool outgoing ATTRIBUTE_UNUSED)
226 {
227   enum machine_mode mode;
228   int unsigned_p;
229 
230   mode = TYPE_MODE (valtype);
231   unsigned_p = TYPE_UNSIGNED (valtype);
232 
233   mode = promote_function_mode (valtype, mode, &unsigned_p,
234 				fn_decl_or_type, 1);
235 
236   return gen_rtx_REG (mode, 0);
237 }
238 
239 
240 /* Implement TARGET_LIBCALL_VALUE.  */
241 static rtx
242 tilepro_libcall_value (enum machine_mode mode,
243 		       const_rtx fun ATTRIBUTE_UNUSED)
244 {
245   return gen_rtx_REG (mode, 0);
246 }
247 
248 
249 /* Implement FUNCTION_VALUE_REGNO_P.  */
250 static bool
251 tilepro_function_value_regno_p (const unsigned int regno)
252 {
253   return regno < TILEPRO_NUM_RETURN_REGS;
254 }
255 
256 
257 /* Implement TARGET_BUILD_BUILTIN_VA_LIST.  */
258 static tree
259 tilepro_build_builtin_va_list (void)
260 {
261   tree f_args, f_skip, record, type_decl;
262   bool owp;
263 
264   record = lang_hooks.types.make_type (RECORD_TYPE);
265 
266   type_decl = build_decl (BUILTINS_LOCATION, TYPE_DECL,
267 			  get_identifier ("__va_list_tag"), record);
268 
269   f_args = build_decl (BUILTINS_LOCATION, FIELD_DECL,
270 		       get_identifier ("__args"), ptr_type_node);
271   f_skip = build_decl (BUILTINS_LOCATION, FIELD_DECL,
272 		       get_identifier ("__skip"), ptr_type_node);
273 
274   DECL_FIELD_CONTEXT (f_args) = record;
275 
276   DECL_FIELD_CONTEXT (f_skip) = record;
277 
278   TREE_CHAIN (record) = type_decl;
279   TYPE_NAME (record) = type_decl;
280   TYPE_FIELDS (record) = f_args;
281   TREE_CHAIN (f_args) = f_skip;
282 
283   /* We know this is being padded and we want it too.  It is an
284      internal type so hide the warnings from the user.  */
285   owp = warn_padded;
286   warn_padded = false;
287 
288   layout_type (record);
289 
290   warn_padded = owp;
291 
292   /* The correct type is an array type of one element.  */
293   return record;
294 }
295 
296 
297 /* Implement TARGET_EXPAND_BUILTIN_VA_START.  */
298 static void
299 tilepro_va_start (tree valist, rtx nextarg ATTRIBUTE_UNUSED)
300 {
301   tree f_args, f_skip;
302   tree args, skip, t;
303 
304   f_args = TYPE_FIELDS (TREE_TYPE (valist));
305   f_skip = TREE_CHAIN (f_args);
306 
307   args =
308     build3 (COMPONENT_REF, TREE_TYPE (f_args), valist, f_args, NULL_TREE);
309   skip =
310     build3 (COMPONENT_REF, TREE_TYPE (f_skip), valist, f_skip, NULL_TREE);
311 
312   /* Find the __args area.  */
313   t = make_tree (TREE_TYPE (args), virtual_incoming_args_rtx);
314   t = fold_build_pointer_plus_hwi (t,
315 				   UNITS_PER_WORD *
316 				   (crtl->args.info - TILEPRO_NUM_ARG_REGS));
317 
318   if (crtl->args.pretend_args_size > 0)
319     t = fold_build_pointer_plus_hwi (t, -STACK_POINTER_OFFSET);
320 
321   t = build2 (MODIFY_EXPR, TREE_TYPE (args), args, t);
322   TREE_SIDE_EFFECTS (t) = 1;
323   expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
324 
325   /* Find the __skip area.  */
326   t = make_tree (TREE_TYPE (skip), virtual_incoming_args_rtx);
327   t = fold_build_pointer_plus_hwi (t, -STACK_POINTER_OFFSET);
328   t = build2 (MODIFY_EXPR, TREE_TYPE (skip), skip, t);
329   TREE_SIDE_EFFECTS (t) = 1;
330   expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
331 }
332 
333 
334 /* Implement TARGET_SETUP_INCOMING_VARARGS.  */
335 static void
336 tilepro_setup_incoming_varargs (cumulative_args_t cum,
337 				enum machine_mode mode,
338 				tree type, int *pretend_args, int no_rtl)
339 {
340   CUMULATIVE_ARGS local_cum = *get_cumulative_args (cum);
341   int first_reg;
342 
343   /* The caller has advanced CUM up to, but not beyond, the last named
344      argument.  Advance a local copy of CUM past the last "real" named
345      argument, to find out how many registers are left over.  */
346   targetm.calls.function_arg_advance (pack_cumulative_args (&local_cum),
347 				      mode, type, true);
348   first_reg = local_cum;
349 
350   if (local_cum < TILEPRO_NUM_ARG_REGS)
351     {
352       *pretend_args = UNITS_PER_WORD * (TILEPRO_NUM_ARG_REGS - first_reg);
353 
354       if (!no_rtl)
355 	{
356 	  alias_set_type set = get_varargs_alias_set ();
357 	  rtx tmp =
358 	    gen_rtx_MEM (BLKmode, plus_constant (Pmode, \
359 						 virtual_incoming_args_rtx,
360 						 -STACK_POINTER_OFFSET -
361 						 UNITS_PER_WORD *
362 						 (TILEPRO_NUM_ARG_REGS -
363 						  first_reg)));
364 	  MEM_NOTRAP_P (tmp) = 1;
365 	  set_mem_alias_set (tmp, set);
366 	  move_block_from_reg (first_reg, tmp,
367 			       TILEPRO_NUM_ARG_REGS - first_reg);
368 	}
369     }
370   else
371     *pretend_args = 0;
372 }
373 
374 
375 /* Implement TARGET_GIMPLIFY_VA_ARG_EXPR.  Gimplify va_arg by updating
376    the va_list structure VALIST as required to retrieve an argument of
377    type TYPE, and returning that argument.
378 
379    ret = va_arg(VALIST, TYPE);
380 
381    generates code equivalent to:
382 
383     paddedsize = (sizeof(TYPE) + 3) & -4;
384     if ((VALIST.__args + paddedsize > VALIST.__skip)
385 	& (VALIST.__args <= VALIST.__skip))
386       addr = VALIST.__skip + STACK_POINTER_OFFSET;
387     else
388       addr = VALIST.__args;
389     VALIST.__args = addr + paddedsize;
390     ret = *(TYPE *)addr;                                          */
391 static tree
392 tilepro_gimplify_va_arg_expr (tree valist, tree type, gimple_seq * pre_p,
393 			      gimple_seq * post_p ATTRIBUTE_UNUSED)
394 {
395   tree f_args, f_skip;
396   tree args, skip;
397   HOST_WIDE_INT size, rsize;
398   tree addr, tmp;
399   bool pass_by_reference_p;
400 
401   f_args = TYPE_FIELDS (va_list_type_node);
402   f_skip = TREE_CHAIN (f_args);
403 
404   args =
405     build3 (COMPONENT_REF, TREE_TYPE (f_args), valist, f_args, NULL_TREE);
406   skip =
407     build3 (COMPONENT_REF, TREE_TYPE (f_skip), valist, f_skip, NULL_TREE);
408 
409   addr = create_tmp_var (ptr_type_node, "va_arg");
410 
411   /* if an object is dynamically sized, a pointer to it is passed
412      instead of the object itself.  */
413   pass_by_reference_p = pass_by_reference (NULL, TYPE_MODE (type), type,
414 					   false);
415 
416   if (pass_by_reference_p)
417     type = build_pointer_type (type);
418 
419   size = int_size_in_bytes (type);
420   rsize = ((size + UNITS_PER_WORD - 1) / UNITS_PER_WORD) * UNITS_PER_WORD;
421 
422   /* If the alignment of the type is greater than the default for a
423      parameter, align to STACK_BOUNDARY.  */
424   if (TYPE_ALIGN (type) > PARM_BOUNDARY)
425     {
426       /* Assert the only case we generate code for: when
427          stack boundary = 2 * parm boundary.  */
428       gcc_assert (STACK_BOUNDARY == PARM_BOUNDARY * 2);
429 
430       tmp = build2 (BIT_AND_EXPR, sizetype,
431 		    fold_convert (sizetype, unshare_expr (args)),
432 		    size_int (PARM_BOUNDARY / 8));
433       tmp = build2 (POINTER_PLUS_EXPR, ptr_type_node,
434 		    unshare_expr (args), tmp);
435 
436       gimplify_assign (unshare_expr (args), tmp, pre_p);
437     }
438 
439   /* Build conditional expression to calculate addr. The expression
440      will be gimplified later.  */
441   tmp = fold_build_pointer_plus_hwi (unshare_expr (args), rsize);
442   tmp = build2 (TRUTH_AND_EXPR, boolean_type_node,
443 		build2 (GT_EXPR, boolean_type_node, tmp, unshare_expr (skip)),
444 		build2 (LE_EXPR, boolean_type_node, unshare_expr (args),
445 			unshare_expr (skip)));
446 
447   tmp = build3 (COND_EXPR, ptr_type_node, tmp,
448 		build2 (POINTER_PLUS_EXPR, ptr_type_node, unshare_expr (skip),
449 			size_int (STACK_POINTER_OFFSET)),
450 		unshare_expr (args));
451 
452   gimplify_assign (addr, tmp, pre_p);
453 
454   /* Update VALIST.__args.  */
455   tmp = fold_build_pointer_plus_hwi (addr, rsize);
456   gimplify_assign (unshare_expr (args), tmp, pre_p);
457 
458   addr = fold_convert (build_pointer_type (type), addr);
459 
460   if (pass_by_reference_p)
461     addr = build_va_arg_indirect_ref (addr);
462 
463   return build_va_arg_indirect_ref (addr);
464 }
465 
466 
467 
468 /* Implement TARGET_RTX_COSTS.  */
469 static bool
470 tilepro_rtx_costs (rtx x, int code, int outer_code, int opno, int *total,
471 		   bool speed)
472 {
473   switch (code)
474     {
475     case CONST_INT:
476       /* If this is an 8-bit constant, return zero since it can be
477          used nearly anywhere with no cost.  If it is a valid operand
478          for an ADD or AND, likewise return 0 if we know it will be
479          used in that context.  Otherwise, return 2 since it might be
480          used there later.  All other constants take at least two
481          insns.  */
482       if (satisfies_constraint_I (x))
483 	{
484 	  *total = 0;
485 	  return true;
486 	}
487       else if (outer_code == PLUS && add_operand (x, VOIDmode))
488 	{
489 	  /* Slightly penalize large constants even though we can add
490 	     them in one instruction, because it forces the use of
491 	     2-wide bundling mode.  */
492 	  *total = 1;
493 	  return true;
494 	}
495       else if (move_operand (x, SImode))
496 	{
497 	  /* We can materialize in one move.  */
498 	  *total = COSTS_N_INSNS (1);
499 	  return true;
500 	}
501       else
502 	{
503 	  /* We can materialize in two moves.  */
504 	  *total = COSTS_N_INSNS (2);
505 	  return true;
506 	}
507 
508       return false;
509 
510     case CONST:
511     case LABEL_REF:
512     case SYMBOL_REF:
513       *total = COSTS_N_INSNS (2);
514       return true;
515 
516     case CONST_DOUBLE:
517       *total = COSTS_N_INSNS (4);
518       return true;
519 
520     case HIGH:
521       *total = 0;
522       return true;
523 
524     case MEM:
525       /* If outer-code was a sign or zero extension, a cost of
526          COSTS_N_INSNS (1) was already added in, so account for
527          that.  */
528       if (outer_code == ZERO_EXTEND || outer_code == SIGN_EXTEND)
529 	*total = COSTS_N_INSNS (1);
530       else
531 	*total = COSTS_N_INSNS (2);
532       return true;
533 
534     case PLUS:
535       /* Convey that s[123]a are efficient.  */
536       if (GET_CODE (XEXP (x, 0)) == MULT
537 	  && cint_248_operand (XEXP (XEXP (x, 0), 1), VOIDmode))
538 	{
539 	  *total = (rtx_cost (XEXP (XEXP (x, 0), 0),
540 			      (enum rtx_code) outer_code, opno, speed)
541 		    + rtx_cost (XEXP (x, 1),
542 				(enum rtx_code) outer_code, opno, speed)
543 		    + COSTS_N_INSNS (1));
544 	  return true;
545 	}
546       return false;
547 
548     case MULT:
549       *total = COSTS_N_INSNS (2);
550       return false;
551 
552     case SIGN_EXTEND:
553     case ZERO_EXTEND:
554       if (outer_code == MULT)
555 	*total = 0;
556       else
557 	*total = COSTS_N_INSNS (1);
558       return false;
559 
560     case DIV:
561     case UDIV:
562     case MOD:
563     case UMOD:
564       /* These are handled by software and are very expensive.  */
565       *total = COSTS_N_INSNS (100);
566       return false;
567 
568     case UNSPEC:
569     case UNSPEC_VOLATILE:
570       {
571 	int num = XINT (x, 1);
572 
573 	if (num <= TILEPRO_LAST_LATENCY_1_INSN)
574 	  *total = COSTS_N_INSNS (1);
575 	else if (num <= TILEPRO_LAST_LATENCY_2_INSN)
576 	  *total = COSTS_N_INSNS (2);
577 	else if (num > TILEPRO_LAST_LATENCY_INSN)
578 	  {
579 	    if (outer_code == PLUS)
580 	      *total = 0;
581 	    else
582 	      *total = COSTS_N_INSNS (1);
583 	  }
584 	else
585 	  {
586 	    switch (num)
587 	      {
588 	      case UNSPEC_BLOCKAGE:
589 	      case UNSPEC_NETWORK_BARRIER:
590 		*total = 0;
591 		break;
592 
593 	      case UNSPEC_LNK_AND_LABEL:
594 	      case UNSPEC_MF:
595 	      case UNSPEC_NETWORK_RECEIVE:
596 	      case UNSPEC_NETWORK_SEND:
597 	      case UNSPEC_TLS_GD_ADD:
598 		*total = COSTS_N_INSNS (1);
599 		break;
600 
601 	      case UNSPEC_TLS_IE_LOAD:
602 		*total = COSTS_N_INSNS (2);
603 		break;
604 
605 	      case UNSPEC_SP_SET:
606 		*total = COSTS_N_INSNS (3);
607 		break;
608 
609 	      case UNSPEC_SP_TEST:
610 		*total = COSTS_N_INSNS (4);
611 		break;
612 
613 	      case UNSPEC_LATENCY_L2:
614 		*total = COSTS_N_INSNS (8);
615 		break;
616 
617 	      case UNSPEC_TLS_GD_CALL:
618 		*total = COSTS_N_INSNS (30);
619 		break;
620 
621 	      case UNSPEC_LATENCY_MISS:
622 		*total = COSTS_N_INSNS (80);
623 		break;
624 
625 	      default:
626 		*total = COSTS_N_INSNS (1);
627 	      }
628 	  }
629 	return true;
630       }
631 
632     default:
633       return false;
634     }
635 }
636 
637 
638 
639 /* Returns an SImode integer rtx with value VAL.  */
640 static rtx
641 gen_int_si (HOST_WIDE_INT val)
642 {
643   return gen_int_mode (val, SImode);
644 }
645 
646 
647 /* Create a temporary variable to hold a partial result, to enable
648    CSE.  */
649 static rtx
650 create_temp_reg_if_possible (enum machine_mode mode, rtx default_reg)
651 {
652   return can_create_pseudo_p ()? gen_reg_rtx (mode) : default_reg;
653 }
654 
655 
656 /* Functions to save and restore machine-specific function data.  */
657 static struct machine_function *
658 tilepro_init_machine_status (void)
659 {
660   return ggc_alloc_cleared_machine_function ();
661 }
662 
663 
664 /* Do anything needed before RTL is emitted for each function.  */
665 void
666 tilepro_init_expanders (void)
667 {
668   /* Arrange to initialize and mark the machine per-function
669      status.  */
670   init_machine_status = tilepro_init_machine_status;
671 
672   if (cfun && cfun->machine && flag_pic)
673     {
674       static int label_num = 0;
675 
676       char text_label_name[32];
677 
678       struct machine_function *machine = cfun->machine;
679 
680       ASM_GENERATE_INTERNAL_LABEL (text_label_name, "L_PICLNK", label_num++);
681 
682       machine->text_label_symbol =
683 	gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (text_label_name));
684 
685       machine->text_label_rtx =
686 	gen_rtx_REG (Pmode, TILEPRO_PIC_TEXT_LABEL_REGNUM);
687 
688       machine->got_rtx = gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM);
689 
690       machine->calls_tls_get_addr = false;
691     }
692 }
693 
694 
695 /* Return true if X contains a thread-local symbol.  */
696 static bool
697 tilepro_tls_referenced_p (rtx x)
698 {
699   if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == PLUS)
700     x = XEXP (XEXP (x, 0), 0);
701 
702   if (GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (x))
703     return true;
704 
705   /* That's all we handle in tilepro_legitimize_tls_address for
706      now.  */
707   return false;
708 }
709 
710 
711 /* Return true if X requires a scratch register.  It is given that
712    flag_pic is on and that X satisfies CONSTANT_P.  */
713 static int
714 tilepro_pic_address_needs_scratch (rtx x)
715 {
716   if (GET_CODE (x) == CONST
717       && GET_CODE (XEXP (x, 0)) == PLUS
718       && (GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF
719 	  || GET_CODE (XEXP (XEXP (x, 0), 0)) == LABEL_REF)
720       && CONST_INT_P (XEXP (XEXP (x, 0), 1)))
721     return true;
722 
723   return false;
724 }
725 
726 
727 /* Implement TARGET_LEGITIMATE_CONSTANT_P.  This is all constants for
728    which we are willing to load the value into a register via a move
729    pattern.  TLS cannot be treated as a constant because it can
730    include a function call.  */
731 static bool
732 tilepro_legitimate_constant_p (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x)
733 {
734   switch (GET_CODE (x))
735     {
736     case CONST:
737     case SYMBOL_REF:
738       return !tilepro_tls_referenced_p (x);
739 
740     default:
741       return true;
742     }
743 }
744 
745 
746 /* Return true if the constant value X is a legitimate general operand
747    when generating PIC code.  It is given that flag_pic is on and that
748    X satisfies CONSTANT_P.  */
749 bool
750 tilepro_legitimate_pic_operand_p (rtx x)
751 {
752   if (tilepro_pic_address_needs_scratch (x))
753     return false;
754 
755   if (tilepro_tls_referenced_p (x))
756     return false;
757 
758   return true;
759 }
760 
761 
762 /* Return true if the rtx X can be used as an address operand.  */
763 static bool
764 tilepro_legitimate_address_p (enum machine_mode ARG_UNUSED (mode), rtx x,
765 			      bool strict)
766 {
767   if (GET_CODE (x) == SUBREG)
768     x = SUBREG_REG (x);
769 
770   switch (GET_CODE (x))
771     {
772     case POST_INC:
773     case POST_DEC:
774       if (GET_MODE_SIZE (GET_MODE (x)) > UNITS_PER_WORD)
775 	return false;
776 
777       x = XEXP (x, 0);
778       break;
779 
780     case POST_MODIFY:
781       if (GET_MODE_SIZE (GET_MODE (x)) > UNITS_PER_WORD)
782 	return false;
783 
784       if (GET_CODE (XEXP (x, 1)) != PLUS)
785 	return false;
786 
787       if (!rtx_equal_p (XEXP (x, 0), XEXP (XEXP (x, 1), 0)))
788 	return false;
789 
790       if (!satisfies_constraint_I (XEXP (XEXP (x, 1), 1)))
791 	return false;
792 
793       x = XEXP (x, 0);
794       break;
795 
796     case REG:
797       break;
798 
799     default:
800       return false;
801     }
802 
803   /* Check if x is a valid reg.  */
804   if (!REG_P (x))
805     return false;
806 
807   if (strict)
808     return REGNO_OK_FOR_BASE_P (REGNO (x));
809   else
810     return true;
811 }
812 
813 
814 /* Return the rtx containing SYMBOL_REF to the text label.  */
815 static rtx
816 tilepro_text_label_symbol (void)
817 {
818   return cfun->machine->text_label_symbol;
819 }
820 
821 
822 /* Return the register storing the value of the text label.  */
823 static rtx
824 tilepro_text_label_rtx (void)
825 {
826   return cfun->machine->text_label_rtx;
827 }
828 
829 
830 /* Return the register storing the value of the global offset
831    table.  */
832 static rtx
833 tilepro_got_rtx (void)
834 {
835   return cfun->machine->got_rtx;
836 }
837 
838 
839 /* Return the SYMBOL_REF for _GLOBAL_OFFSET_TABLE_.  */
840 static rtx
841 tilepro_got_symbol (void)
842 {
843   if (g_got_symbol == NULL)
844     g_got_symbol = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");
845 
846   return g_got_symbol;
847 }
848 
849 
850 /* Return a reference to the got to be used by tls references.  */
851 static rtx
852 tilepro_tls_got (void)
853 {
854   rtx temp;
855   if (flag_pic)
856     {
857       crtl->uses_pic_offset_table = 1;
858       return tilepro_got_rtx ();
859     }
860 
861   temp = gen_reg_rtx (Pmode);
862   emit_move_insn (temp, tilepro_got_symbol ());
863 
864   return temp;
865 }
866 
867 
868 /* ADDR contains a thread-local SYMBOL_REF.  Generate code to compute
869    this (thread-local) address.  */
870 static rtx
871 tilepro_legitimize_tls_address (rtx addr)
872 {
873   rtx ret;
874 
875   gcc_assert (can_create_pseudo_p ());
876 
877   if (GET_CODE (addr) == SYMBOL_REF)
878     switch (SYMBOL_REF_TLS_MODEL (addr))
879       {
880       case TLS_MODEL_GLOBAL_DYNAMIC:
881       case TLS_MODEL_LOCAL_DYNAMIC:
882 	{
883 	  rtx r0, temp1, temp2, temp3, got, last;
884 
885 	  ret = gen_reg_rtx (Pmode);
886 	  r0 = gen_rtx_REG (Pmode, 0);
887 	  temp1 = gen_reg_rtx (Pmode);
888 	  temp2 = gen_reg_rtx (Pmode);
889 	  temp3 = gen_reg_rtx (Pmode);
890 
891 	  got = tilepro_tls_got ();
892 	  emit_insn (gen_tls_gd_addhi (temp1, got, addr));
893 	  emit_insn (gen_tls_gd_addlo (temp2, temp1, addr));
894 	  emit_move_insn (r0, temp2);
895 	  emit_insn (gen_tls_gd_call (addr));
896 	  emit_move_insn (temp3, r0);
897 	  last = emit_insn (gen_tls_gd_add (ret, temp3, addr));
898 	  set_unique_reg_note (last, REG_EQUAL, copy_rtx (addr));
899 	  break;
900 	}
901       case TLS_MODEL_INITIAL_EXEC:
902 	{
903 	  rtx temp1, temp2, temp3, got, last;
904 
905 	  ret = gen_reg_rtx (Pmode);
906 	  temp1 = gen_reg_rtx (Pmode);
907 	  temp2 = gen_reg_rtx (Pmode);
908 	  temp3 = gen_reg_rtx (Pmode);
909 
910 	  got = tilepro_tls_got ();
911 	  emit_insn (gen_tls_ie_addhi (temp1, got, addr));
912 	  emit_insn (gen_tls_ie_addlo (temp2, temp1, addr));
913 	  emit_insn (gen_tls_ie_load (temp3, temp2, addr));
914 	  last =
915 	    emit_move_insn(ret,
916 			   gen_rtx_PLUS (Pmode,
917 					 gen_rtx_REG (Pmode,
918 						      THREAD_POINTER_REGNUM),
919 					 temp3));
920 	  set_unique_reg_note (last, REG_EQUAL, copy_rtx (addr));
921 	  break;
922 	}
923       case TLS_MODEL_LOCAL_EXEC:
924 	{
925 	  rtx temp1, last;
926 
927 	  ret = gen_reg_rtx (Pmode);
928 	  temp1 = gen_reg_rtx (Pmode);
929 
930 	  emit_insn (gen_tls_le_addhi (temp1,
931 				       gen_rtx_REG (Pmode,
932 						    THREAD_POINTER_REGNUM),
933 				       addr));
934 	  last = emit_insn (gen_tls_le_addlo (ret, temp1, addr));
935 	  set_unique_reg_note (last, REG_EQUAL, copy_rtx (addr));
936 	  break;
937 	}
938       default:
939 	gcc_unreachable ();
940       }
941   else if (GET_CODE (addr) == CONST)
942     {
943       rtx base, offset;
944 
945       gcc_assert (GET_CODE (XEXP (addr, 0)) == PLUS);
946 
947       base = tilepro_legitimize_tls_address (XEXP (XEXP (addr, 0), 0));
948       offset = XEXP (XEXP (addr, 0), 1);
949 
950       base = force_operand (base, NULL_RTX);
951       ret = force_reg (Pmode, gen_rtx_PLUS (Pmode, base, offset));
952     }
953   else
954     gcc_unreachable ();
955 
956   return ret;
957 }
958 
959 
960 /* Legitimize PIC addresses.  If the address is already
961    position-independent, we return ORIG.  Newly generated
962    position-independent addresses go into a reg.  This is REG if
963    nonzero, otherwise we allocate register(s) as necessary.  */
964 static rtx
965 tilepro_legitimize_pic_address (rtx orig,
966 				enum machine_mode mode ATTRIBUTE_UNUSED,
967 				rtx reg)
968 {
969   if (GET_CODE (orig) == SYMBOL_REF)
970     {
971       rtx address, pic_ref;
972 
973       if (reg == 0)
974 	{
975 	  gcc_assert (can_create_pseudo_p ());
976 	  reg = gen_reg_rtx (Pmode);
977 	}
978 
979       if (SYMBOL_REF_LOCAL_P (orig))
980 	{
981 	  /* If not during reload, allocate another temp reg here for
982 	     loading in the address, so that these instructions can be
983 	     optimized properly.  */
984 	  rtx temp_reg = create_temp_reg_if_possible (Pmode, reg);
985 	  rtx text_label_symbol = tilepro_text_label_symbol ();
986 	  rtx text_label_rtx = tilepro_text_label_rtx ();
987 
988 	  emit_insn (gen_addli_pcrel (temp_reg, text_label_rtx, orig,
989 				      text_label_symbol));
990 	  emit_insn (gen_auli_pcrel (temp_reg, temp_reg, orig,
991 				     text_label_symbol));
992 
993 	  /* Note: this is conservative.  We use the text_label but we
994 	     don't use the pic_offset_table.  However, in some cases
995 	     we may need the pic_offset_table (see
996 	     tilepro_fixup_pcrel_references).  */
997 	  crtl->uses_pic_offset_table = 1;
998 
999 	  address = temp_reg;
1000 
1001 	  emit_move_insn (reg, address);
1002 	  return reg;
1003 	}
1004       else
1005 	{
1006 	  /* If not during reload, allocate another temp reg here for
1007 	     loading in the address, so that these instructions can be
1008 	     optimized properly.  */
1009 	  rtx temp_reg = create_temp_reg_if_possible (Pmode, reg);
1010 
1011 	  gcc_assert (flag_pic);
1012 	  if (flag_pic == 1)
1013 	    {
1014 	      emit_insn (gen_add_got16 (temp_reg,
1015 					tilepro_got_rtx (), orig));
1016 	    }
1017 	  else
1018 	    {
1019 	      rtx temp_reg2 = create_temp_reg_if_possible (Pmode, reg);
1020 	      emit_insn (gen_addhi_got32 (temp_reg2,
1021 					  tilepro_got_rtx (), orig));
1022 	      emit_insn (gen_addlo_got32 (temp_reg, temp_reg2, orig));
1023 	    }
1024 
1025 	  address = temp_reg;
1026 
1027 	  pic_ref = gen_const_mem (Pmode, address);
1028 	  crtl->uses_pic_offset_table = 1;
1029 	  emit_move_insn (reg, pic_ref);
1030 	  /* The following put a REG_EQUAL note on this insn, so that
1031 	     it can be optimized by loop.  But it causes the label to
1032 	     be optimized away.  */
1033 	  /* set_unique_reg_note (insn, REG_EQUAL, orig); */
1034 	  return reg;
1035 	}
1036     }
1037   else if (GET_CODE (orig) == CONST)
1038     {
1039       rtx base, offset;
1040 
1041       if (GET_CODE (XEXP (orig, 0)) == PLUS
1042 	  && XEXP (XEXP (orig, 0), 0) == tilepro_got_rtx ())
1043 	return orig;
1044 
1045       if (reg == 0)
1046 	{
1047 	  gcc_assert (can_create_pseudo_p ());
1048 	  reg = gen_reg_rtx (Pmode);
1049 	}
1050 
1051       gcc_assert (GET_CODE (XEXP (orig, 0)) == PLUS);
1052       base = tilepro_legitimize_pic_address (XEXP (XEXP (orig, 0), 0), Pmode,
1053 					     reg);
1054       offset =
1055 	tilepro_legitimize_pic_address (XEXP (XEXP (orig, 0), 1), Pmode,
1056 					base == reg ? 0 : reg);
1057 
1058       if (CONST_INT_P (offset))
1059 	{
1060 	  if (can_create_pseudo_p ())
1061 	    offset = force_reg (Pmode, offset);
1062 	  else
1063 	    /* If we reach here, then something is seriously
1064 	       wrong.  */
1065 	    gcc_unreachable ();
1066 	}
1067 
1068       if (can_create_pseudo_p ())
1069 	return force_reg (Pmode, gen_rtx_PLUS (Pmode, base, offset));
1070       else
1071 	gcc_unreachable ();
1072     }
1073   else if (GET_CODE (orig) == LABEL_REF)
1074     {
1075       rtx address, temp_reg;
1076       rtx text_label_symbol;
1077       rtx text_label_rtx;
1078 
1079       if (reg == 0)
1080 	{
1081 	  gcc_assert (can_create_pseudo_p ());
1082 	  reg = gen_reg_rtx (Pmode);
1083 	}
1084 
1085       /* If not during reload, allocate another temp reg here for
1086          loading in the address, so that these instructions can be
1087          optimized properly.  */
1088       temp_reg = create_temp_reg_if_possible (Pmode, reg);
1089       text_label_symbol = tilepro_text_label_symbol ();
1090       text_label_rtx = tilepro_text_label_rtx ();
1091 
1092       emit_insn (gen_addli_pcrel (temp_reg, text_label_rtx, orig,
1093 				  text_label_symbol));
1094       emit_insn (gen_auli_pcrel (temp_reg, temp_reg, orig,
1095 				 text_label_symbol));
1096 
1097       /* Note: this is conservative.  We use the text_label but we
1098          don't use the pic_offset_table.  */
1099       crtl->uses_pic_offset_table = 1;
1100 
1101       address = temp_reg;
1102 
1103       emit_move_insn (reg, address);
1104 
1105       return reg;
1106     }
1107 
1108   return orig;
1109 }
1110 
1111 
1112 /* Implement TARGET_LEGITIMIZE_ADDRESS.  */
1113 static rtx
1114 tilepro_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
1115 			    enum machine_mode mode)
1116 {
1117   if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD
1118       && symbolic_operand (x, Pmode) && tilepro_tls_referenced_p (x))
1119     {
1120       return tilepro_legitimize_tls_address (x);
1121     }
1122   else if (flag_pic)
1123     {
1124       return tilepro_legitimize_pic_address (x, mode, 0);
1125     }
1126   else
1127     return x;
1128 }
1129 
1130 
1131 /* Implement TARGET_DELEGITIMIZE_ADDRESS.  */
1132 static rtx
1133 tilepro_delegitimize_address (rtx x)
1134 {
1135   x = delegitimize_mem_from_attrs (x);
1136 
1137   if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == UNSPEC)
1138     {
1139       switch (XINT (XEXP (x, 0), 1))
1140 	{
1141 	case UNSPEC_PCREL_SYM:
1142 	case UNSPEC_GOT16_SYM:
1143 	case UNSPEC_GOT32_SYM:
1144 	case UNSPEC_TLS_GD:
1145 	case UNSPEC_TLS_IE:
1146 	  x = XVECEXP (XEXP (x, 0), 0, 0);
1147 	  break;
1148 	}
1149     }
1150 
1151   return x;
1152 }
1153 
1154 
1155 /* Emit code to load the PIC register.  */
1156 static void
1157 load_pic_register (bool delay_pic_helper ATTRIBUTE_UNUSED)
1158 {
1159   int orig_flag_pic = flag_pic;
1160 
1161   rtx got_symbol = tilepro_got_symbol ();
1162   rtx text_label_symbol = tilepro_text_label_symbol ();
1163   rtx text_label_rtx = tilepro_text_label_rtx ();
1164   flag_pic = 0;
1165 
1166   emit_insn (gen_insn_lnk_and_label (text_label_rtx, text_label_symbol));
1167 
1168   emit_insn (gen_addli_pcrel (tilepro_got_rtx (),
1169 			      text_label_rtx, got_symbol, text_label_symbol));
1170 
1171   emit_insn (gen_auli_pcrel (tilepro_got_rtx (),
1172 			     tilepro_got_rtx (),
1173 			     got_symbol, text_label_symbol));
1174 
1175   flag_pic = orig_flag_pic;
1176 
1177   /* Need to emit this whether or not we obey regdecls, since
1178      setjmp/longjmp can cause life info to screw up.  ??? In the case
1179      where we don't obey regdecls, this is not sufficient since we may
1180      not fall out the bottom.  */
1181   emit_use (tilepro_got_rtx ());
1182 }
1183 
1184 
1185 /* Return the simd variant of the constant NUM of mode MODE, by
1186    replicating it to fill an interger of mode SImode.  NUM is first
1187    truncated to fit in MODE.  */
1188 rtx
1189 tilepro_simd_int (rtx num, enum machine_mode mode)
1190 {
1191   HOST_WIDE_INT n = 0;
1192 
1193   gcc_assert (CONST_INT_P (num));
1194 
1195   n = INTVAL (num);
1196 
1197   switch (mode)
1198     {
1199     case QImode:
1200       n = 0x01010101 * (n & 0x000000FF);
1201       break;
1202     case HImode:
1203       n = 0x00010001 * (n & 0x0000FFFF);
1204       break;
1205     case SImode:
1206       break;
1207     case DImode:
1208       break;
1209     default:
1210       gcc_unreachable ();
1211     }
1212 
1213   return gen_int_si (n);
1214 }
1215 
1216 
1217 /* Split one or more DImode RTL references into pairs of SImode
1218    references.  The RTL can be REG, offsettable MEM, integer constant,
1219    or CONST_DOUBLE.  "operands" is a pointer to an array of DImode RTL
1220    to split and "num" is its length.  lo_half and hi_half are output
1221    arrays that parallel "operands".  */
1222 void
1223 split_di (rtx operands[], int num, rtx lo_half[], rtx hi_half[])
1224 {
1225   while (num--)
1226     {
1227       rtx op = operands[num];
1228 
1229       /* simplify_subreg refuse to split volatile memory addresses,
1230          but we still have to handle it.  */
1231       if (MEM_P (op))
1232 	{
1233 	  lo_half[num] = adjust_address (op, SImode, 0);
1234 	  hi_half[num] = adjust_address (op, SImode, 4);
1235 	}
1236       else
1237 	{
1238 	  lo_half[num] = simplify_gen_subreg (SImode, op,
1239 					      GET_MODE (op) == VOIDmode
1240 					      ? DImode : GET_MODE (op), 0);
1241 	  hi_half[num] = simplify_gen_subreg (SImode, op,
1242 					      GET_MODE (op) == VOIDmode
1243 					      ? DImode : GET_MODE (op), 4);
1244 	}
1245     }
1246 }
1247 
1248 
1249 /* Returns true iff val can be moved into a register in one
1250    instruction.  And if it can, it emits the code to move the
1251    constant.
1252 
1253    If three_wide_only is true, this insists on an instruction that
1254    works in a bundle containing three instructions.  */
1255 static bool
1256 expand_set_cint32_one_inst (rtx dest_reg,
1257 			    HOST_WIDE_INT val, bool three_wide_only)
1258 {
1259   val = trunc_int_for_mode (val, SImode);
1260 
1261   if (val == trunc_int_for_mode (val, QImode))
1262     {
1263       /* Success! */
1264       emit_move_insn (dest_reg, GEN_INT (val));
1265       return true;
1266     }
1267   else if (!three_wide_only)
1268     {
1269       rtx imm_op = GEN_INT (val);
1270 
1271       if (satisfies_constraint_J (imm_op)
1272 	  || satisfies_constraint_K (imm_op)
1273 	  || satisfies_constraint_N (imm_op)
1274 	  || satisfies_constraint_P (imm_op))
1275 	{
1276 	  emit_move_insn (dest_reg, imm_op);
1277 	  return true;
1278 	}
1279     }
1280 
1281   return false;
1282 }
1283 
1284 
1285 /* Implement SImode rotatert.  */
1286 static HOST_WIDE_INT
1287 rotate_right (HOST_WIDE_INT n, int count)
1288 {
1289   unsigned HOST_WIDE_INT x = n & 0xFFFFFFFF;
1290   if (count == 0)
1291     return x;
1292   return ((x >> count) | (x << (32 - count))) & 0xFFFFFFFF;
1293 }
1294 
1295 
1296 /* Return true iff n contains exactly one contiguous sequence of 1
1297    bits, possibly wrapping around from high bits to low bits.  */
1298 bool
1299 tilepro_bitfield_operand_p (HOST_WIDE_INT n, int *first_bit, int *last_bit)
1300 {
1301   int i;
1302 
1303   if (n == 0)
1304     return false;
1305 
1306   for (i = 0; i < 32; i++)
1307     {
1308       unsigned HOST_WIDE_INT x = rotate_right (n, i);
1309       if (!(x & 1))
1310 	continue;
1311 
1312       /* See if x is a power of two minus one, i.e. only consecutive 1
1313          bits starting from bit 0.  */
1314       if ((x & (x + 1)) == 0)
1315 	{
1316 	  if (first_bit != NULL)
1317 	    *first_bit = i;
1318 	  if (last_bit != NULL)
1319 	    *last_bit = (i + exact_log2 (x ^ (x >> 1))) & 31;
1320 
1321 	  return true;
1322 	}
1323     }
1324 
1325   return false;
1326 }
1327 
1328 
1329 /* Create code to move the CONST_INT value in src_val to dest_reg.  */
1330 static void
1331 expand_set_cint32 (rtx dest_reg, rtx src_val)
1332 {
1333   HOST_WIDE_INT val;
1334   int leading_zeroes, trailing_zeroes;
1335   int lower, upper;
1336   int three_wide_only;
1337   rtx temp;
1338 
1339   gcc_assert (CONST_INT_P (src_val));
1340   val = trunc_int_for_mode (INTVAL (src_val), SImode);
1341 
1342   /* See if we can generate the constant in one instruction.  */
1343   if (expand_set_cint32_one_inst (dest_reg, val, false))
1344     return;
1345 
1346   /* Create a temporary variable to hold a partial result, to enable
1347      CSE.  */
1348   temp = create_temp_reg_if_possible (SImode, dest_reg);
1349 
1350   leading_zeroes = 31 - floor_log2 (val & 0xFFFFFFFF);
1351   trailing_zeroes = exact_log2 (val & -val);
1352 
1353   lower = trunc_int_for_mode (val, HImode);
1354   upper = trunc_int_for_mode ((val - lower) >> 16, HImode);
1355 
1356   /* First try all three-wide instructions that generate a constant
1357      (i.e. movei) followed by various shifts and rotates. If none of
1358      those work, try various two-wide ways of generating a constant
1359      followed by various shifts and rotates.  */
1360   for (three_wide_only = 1; three_wide_only >= 0; three_wide_only--)
1361     {
1362       int count;
1363 
1364       if (expand_set_cint32_one_inst (temp, val >> trailing_zeroes,
1365 				      three_wide_only))
1366 	{
1367 	  /* 0xFFFFA500 becomes:
1368 	     movei temp, 0xFFFFFFA5
1369 	     shli dest, temp, 8  */
1370 	  emit_move_insn (dest_reg,
1371 			  gen_rtx_ASHIFT (SImode, temp,
1372 					  GEN_INT (trailing_zeroes)));
1373 	  return;
1374 	}
1375 
1376       if (expand_set_cint32_one_inst (temp, val << leading_zeroes,
1377 				      three_wide_only))
1378 	{
1379 	  /* 0x7FFFFFFF becomes:
1380 	     movei temp, -2
1381 	     shri dest, temp, 1  */
1382 	  emit_move_insn (dest_reg,
1383 			  gen_rtx_LSHIFTRT (SImode, temp,
1384 					    GEN_INT (leading_zeroes)));
1385 	  return;
1386 	}
1387 
1388       /* Try rotating a one-instruction immediate, since rotate is
1389          3-wide.  */
1390       for (count = 1; count < 32; count++)
1391 	{
1392 	  HOST_WIDE_INT r = rotate_right (val, count);
1393 	  if (expand_set_cint32_one_inst (temp, r, three_wide_only))
1394 	    {
1395 	      /* 0xFFA5FFFF becomes:
1396 	         movei temp, 0xFFFFFFA5
1397 	         rli dest, temp, 16  */
1398 	      emit_move_insn (dest_reg,
1399 			      gen_rtx_ROTATE (SImode, temp, GEN_INT (count)));
1400 	      return;
1401 	    }
1402 	}
1403 
1404       if (lower == trunc_int_for_mode (lower, QImode))
1405 	{
1406 	  /* We failed to use two 3-wide instructions, but the low 16
1407 	     bits are a small number so just use a 2-wide + 3-wide
1408 	     auli + addi pair rather than anything more exotic.
1409 
1410 	     0x12340056 becomes:
1411 	     auli temp, zero, 0x1234
1412 	     addi dest, temp, 0x56  */
1413 	  break;
1414 	}
1415     }
1416 
1417   /* Fallback case: use a auli + addli/addi pair.  */
1418   emit_move_insn (temp, GEN_INT (upper << 16));
1419   emit_move_insn (dest_reg, (gen_rtx_PLUS (SImode, temp, GEN_INT (lower))));
1420 }
1421 
1422 
1423 /* Load OP1, a 32-bit constant, into OP0, a register.  We know it
1424    can't be done in one insn when we get here, the move expander
1425    guarantees this.  */
1426 void
1427 tilepro_expand_set_const32 (rtx op0, rtx op1)
1428 {
1429   enum machine_mode mode = GET_MODE (op0);
1430   rtx temp;
1431 
1432   if (CONST_INT_P (op1))
1433     {
1434       /* TODO: I don't know if we want to split large constants now,
1435          or wait until later (with a define_split).
1436 
1437          Does splitting early help CSE?  Does it harm other
1438          optimizations that might fold loads? */
1439       expand_set_cint32 (op0, op1);
1440     }
1441   else
1442     {
1443       temp = create_temp_reg_if_possible (mode, op0);
1444 
1445       /* A symbol, emit in the traditional way.  */
1446       emit_move_insn (temp, gen_rtx_HIGH (mode, op1));
1447       emit_move_insn (op0, gen_rtx_LO_SUM (mode, temp, op1));
1448     }
1449 }
1450 
1451 
1452 /* Expand a move instruction.  Return true if all work is done.  */
1453 bool
1454 tilepro_expand_mov (enum machine_mode mode, rtx *operands)
1455 {
1456   /* Handle sets of MEM first.  */
1457   if (MEM_P (operands[0]))
1458     {
1459       if (can_create_pseudo_p ())
1460 	operands[0] = validize_mem (operands[0]);
1461 
1462       if (reg_or_0_operand (operands[1], mode))
1463 	return false;
1464 
1465       if (!reload_in_progress)
1466 	operands[1] = force_reg (mode, operands[1]);
1467     }
1468 
1469   /* Fixup TLS cases.  */
1470   if (CONSTANT_P (operands[1]) && tilepro_tls_referenced_p (operands[1]))
1471     {
1472       operands[1] = tilepro_legitimize_tls_address (operands[1]);
1473       return false;
1474     }
1475 
1476   /* Fixup PIC cases.  */
1477   if (flag_pic && CONSTANT_P (operands[1]))
1478     {
1479       if (tilepro_pic_address_needs_scratch (operands[1]))
1480 	operands[1] = tilepro_legitimize_pic_address (operands[1], mode, 0);
1481 
1482       if (symbolic_operand (operands[1], mode))
1483 	{
1484 	  operands[1] = tilepro_legitimize_pic_address (operands[1],
1485 							mode,
1486 							(reload_in_progress ?
1487 							 operands[0] :
1488 							 NULL_RTX));
1489 	  return false;
1490 	}
1491     }
1492 
1493   /* Fixup for UNSPEC addresses.  */
1494   if (flag_pic
1495       && GET_CODE (operands[1]) == HIGH
1496       && GET_CODE (XEXP (operands[1], 0)) == CONST
1497       && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == UNSPEC)
1498     {
1499       rtx unspec = XEXP (XEXP (operands[1], 0), 0);
1500       int unspec_num = XINT (unspec, 1);
1501       if (unspec_num == UNSPEC_PCREL_SYM)
1502 	{
1503 	  emit_insn (gen_auli_pcrel (operands[0], const0_rtx,
1504 				     XVECEXP (unspec, 0, 0),
1505 				     XVECEXP (unspec, 0, 1)));
1506 	  return true;
1507 	}
1508       else if (flag_pic == 2 && unspec_num == UNSPEC_GOT32_SYM)
1509 	{
1510 	  emit_insn (gen_addhi_got32 (operands[0], const0_rtx,
1511 				      XVECEXP (unspec, 0, 0)));
1512 	  return true;
1513 	}
1514       else if (HAVE_AS_TLS && unspec_num == UNSPEC_TLS_GD)
1515 	{
1516 	  emit_insn (gen_tls_gd_addhi (operands[0], const0_rtx,
1517 				       XVECEXP (unspec, 0, 0)));
1518 	  return true;
1519 	}
1520       else if (HAVE_AS_TLS && unspec_num == UNSPEC_TLS_IE)
1521 	{
1522 	  emit_insn (gen_tls_ie_addhi (operands[0], const0_rtx,
1523 				       XVECEXP (unspec, 0, 0)));
1524 	  return true;
1525 	}
1526       else if (HAVE_AS_TLS && unspec_num == UNSPEC_TLS_LE)
1527 	{
1528 	  emit_insn (gen_tls_le_addhi (operands[0], const0_rtx,
1529 				       XVECEXP (unspec, 0, 0)));
1530 	  return true;
1531 	}
1532     }
1533 
1534   /* Accept non-constants and valid constants unmodified.  */
1535   if (!CONSTANT_P (operands[1])
1536       || GET_CODE (operands[1]) == HIGH || move_operand (operands[1], mode))
1537     return false;
1538 
1539   /* Split large integers.  */
1540   if (GET_MODE_SIZE (mode) <= 4)
1541     {
1542       tilepro_expand_set_const32 (operands[0], operands[1]);
1543       return true;
1544     }
1545 
1546   return false;
1547 }
1548 
1549 
1550 /* Expand the "insv" pattern.  */
1551 void
1552 tilepro_expand_insv (rtx operands[4])
1553 {
1554   rtx first_rtx = operands[2];
1555   HOST_WIDE_INT first = INTVAL (first_rtx);
1556   HOST_WIDE_INT width = INTVAL (operands[1]);
1557   rtx v = operands[3];
1558 
1559   /* Shift the inserted bits into position.  */
1560   if (first != 0)
1561     {
1562       if (CONST_INT_P (v))
1563 	{
1564 	  /* Shift the constant into mm position.  */
1565 	  v = gen_int_si (INTVAL (v) << first);
1566 	}
1567       else
1568 	{
1569 	  /* Shift over the value to be inserted.  */
1570 	  rtx tmp = gen_reg_rtx (SImode);
1571 	  emit_insn (gen_ashlsi3 (tmp, v, first_rtx));
1572 	  v = tmp;
1573 	}
1574     }
1575 
1576   /* Insert the shifted bits using an 'mm' insn.  */
1577   emit_insn (gen_insn_mm (operands[0], v, operands[0], first_rtx,
1578 			  GEN_INT (first + width - 1)));
1579 }
1580 
1581 
1582 /* Expand unaligned loads.  */
1583 void
1584 tilepro_expand_unaligned_load (rtx dest_reg, rtx mem, HOST_WIDE_INT bitsize,
1585 			       HOST_WIDE_INT bit_offset, bool sign)
1586 {
1587   enum machine_mode mode;
1588   rtx addr_lo, addr_hi;
1589   rtx mem_lo, mem_hi, hi;
1590   rtx mema, wide_result;
1591   int last_byte_offset;
1592   HOST_WIDE_INT byte_offset = bit_offset / BITS_PER_UNIT;
1593 
1594   mode = GET_MODE (dest_reg);
1595 
1596   hi = gen_reg_rtx (mode);
1597 
1598   if (bitsize == 2 * BITS_PER_UNIT && (bit_offset % BITS_PER_UNIT) == 0)
1599     {
1600       rtx lo;
1601 
1602       /* When just loading a two byte value, we can load the two bytes
1603          individually and combine them efficiently.  */
1604 
1605       mem_lo = adjust_address (mem, QImode, byte_offset);
1606       mem_hi = adjust_address (mem, QImode, byte_offset + 1);
1607 
1608       lo = gen_reg_rtx (mode);
1609       emit_insn (gen_zero_extendqisi2 (lo, mem_lo));
1610 
1611       if (sign)
1612 	{
1613 	  rtx tmp = gen_reg_rtx (mode);
1614 
1615 	  /* Do a signed load of the second byte then shift and OR it
1616 	     in.  */
1617 	  emit_insn (gen_extendqisi2 (gen_lowpart (SImode, hi), mem_hi));
1618 	  emit_insn (gen_ashlsi3 (gen_lowpart (SImode, tmp),
1619 				  gen_lowpart (SImode, hi), GEN_INT (8)));
1620 	  emit_insn (gen_iorsi3 (gen_lowpart (SImode, dest_reg),
1621 				 gen_lowpart (SImode, lo),
1622 				 gen_lowpart (SImode, tmp)));
1623 	}
1624       else
1625 	{
1626 	  /* Do two unsigned loads and use intlb to interleave
1627 	     them.  */
1628 	  emit_insn (gen_zero_extendqisi2 (gen_lowpart (SImode, hi), mem_hi));
1629 	  emit_insn (gen_insn_intlb (gen_lowpart (SImode, dest_reg),
1630 				     gen_lowpart (SImode, hi),
1631 				     gen_lowpart (SImode, lo)));
1632 	}
1633 
1634       return;
1635     }
1636 
1637   mema = XEXP (mem, 0);
1638 
1639   /* AND addresses cannot be in any alias set, since they may
1640      implicitly alias surrounding code.  Ideally we'd have some alias
1641      set that covered all types except those with alignment 8 or
1642      higher.  */
1643   addr_lo = force_reg (Pmode, plus_constant (Pmode, mema, byte_offset));
1644   mem_lo = change_address (mem, mode,
1645 			   gen_rtx_AND (Pmode, addr_lo, GEN_INT (-4)));
1646   set_mem_alias_set (mem_lo, 0);
1647 
1648   /* Load the high word at an address that will not fault if the low
1649      address is aligned and at the very end of a page.  */
1650   last_byte_offset = (bit_offset + bitsize - 1) / BITS_PER_UNIT;
1651   addr_hi = force_reg (Pmode, plus_constant (Pmode, mema, last_byte_offset));
1652   mem_hi = change_address (mem, mode,
1653 			   gen_rtx_AND (Pmode, addr_hi, GEN_INT (-4)));
1654   set_mem_alias_set (mem_hi, 0);
1655 
1656   if (bitsize == 32)
1657     {
1658       addr_lo = make_safe_from (addr_lo, dest_reg);
1659       wide_result = dest_reg;
1660     }
1661   else
1662     {
1663       wide_result = gen_reg_rtx (mode);
1664     }
1665 
1666   /* Load hi first in case dest_reg is used in mema.  */
1667   emit_move_insn (hi, mem_hi);
1668   emit_move_insn (wide_result, mem_lo);
1669 
1670   emit_insn (gen_insn_dword_align (gen_lowpart (SImode, wide_result),
1671 				   gen_lowpart (SImode, wide_result),
1672 				   gen_lowpart (SImode, hi), addr_lo));
1673 
1674   if (bitsize != 32)
1675     {
1676       rtx extracted =
1677 	extract_bit_field (gen_lowpart (SImode, wide_result),
1678 			   bitsize, bit_offset % BITS_PER_UNIT,
1679 			   !sign, false, gen_lowpart (SImode, dest_reg),
1680 			   SImode, SImode);
1681 
1682       if (extracted != dest_reg)
1683 	emit_move_insn (dest_reg, gen_lowpart (SImode, extracted));
1684     }
1685 }
1686 
1687 
1688 /* Expand unaligned stores.  */
1689 static void
1690 tilepro_expand_unaligned_store (rtx mem, rtx src, HOST_WIDE_INT bitsize,
1691 				HOST_WIDE_INT bit_offset)
1692 {
1693   HOST_WIDE_INT byte_offset = bit_offset / BITS_PER_UNIT;
1694   HOST_WIDE_INT bytesize = bitsize / BITS_PER_UNIT;
1695   HOST_WIDE_INT shift_amt;
1696   HOST_WIDE_INT i;
1697   rtx mem_addr;
1698   rtx store_val;
1699 
1700   for (i = 0, shift_amt = 0; i < bytesize; i++, shift_amt += BITS_PER_UNIT)
1701     {
1702       mem_addr = adjust_address (mem, QImode, byte_offset + i);
1703 
1704       if (shift_amt)
1705 	{
1706 	  store_val = expand_simple_binop (SImode, LSHIFTRT,
1707 					   gen_lowpart (SImode, src),
1708 					   GEN_INT (shift_amt), NULL, 1,
1709 					   OPTAB_LIB_WIDEN);
1710 	  store_val = gen_lowpart (QImode, store_val);
1711 	}
1712       else
1713 	{
1714 	  store_val = gen_lowpart (QImode, src);
1715 	}
1716 
1717       emit_move_insn (mem_addr, store_val);
1718     }
1719 }
1720 
1721 
1722 /* Implement the movmisalign patterns.  One of the operands is a
1723    memory that is not naturally aligned.  Emit instructions to load
1724    it.  */
1725 void
1726 tilepro_expand_movmisalign (enum machine_mode mode, rtx *operands)
1727 {
1728   if (MEM_P (operands[1]))
1729     {
1730       rtx tmp;
1731 
1732       if (register_operand (operands[0], mode))
1733 	tmp = operands[0];
1734       else
1735 	tmp = gen_reg_rtx (mode);
1736 
1737       tilepro_expand_unaligned_load (tmp, operands[1],
1738 				     GET_MODE_BITSIZE (mode), 0, true);
1739 
1740       if (tmp != operands[0])
1741 	emit_move_insn (operands[0], tmp);
1742     }
1743   else if (MEM_P (operands[0]))
1744     {
1745       if (!reg_or_0_operand (operands[1], mode))
1746 	operands[1] = force_reg (mode, operands[1]);
1747 
1748       tilepro_expand_unaligned_store (operands[0], operands[1],
1749 				      GET_MODE_BITSIZE (mode), 0);
1750     }
1751   else
1752     gcc_unreachable ();
1753 }
1754 
1755 
1756 /* Implement the addsi3 pattern.  */
1757 bool
1758 tilepro_expand_addsi (rtx op0, rtx op1, rtx op2)
1759 {
1760   rtx temp;
1761   HOST_WIDE_INT n;
1762   HOST_WIDE_INT high;
1763 
1764   /* Skip anything that only takes one instruction.  */
1765   if (add_operand (op2, SImode))
1766     return false;
1767 
1768   /* We can only optimize ints here (it should be impossible to get
1769      here with any other type, but it is harmless to check.  */
1770   if (!CONST_INT_P (op2))
1771     return false;
1772 
1773   temp = create_temp_reg_if_possible (SImode, op0);
1774   n = INTVAL (op2);
1775   high = (n + (n & 0x8000)) & ~0xffff;
1776 
1777   emit_move_insn (temp, gen_rtx_PLUS (SImode, op1, gen_int_si (high)));
1778   emit_move_insn (op0, gen_rtx_PLUS (SImode, temp, gen_int_si (n - high)));
1779 
1780   return true;
1781 }
1782 
1783 
1784 /* Implement the allocate_stack pattern (alloca).  */
1785 void
1786 tilepro_allocate_stack (rtx op0, rtx op1)
1787 {
1788   /* Technically the correct way to initialize chain_loc is with
1789    * gen_frame_mem() instead of gen_rtx_MEM(), but gen_frame_mem()
1790    * sets the alias_set to that of a frame reference.  Some of our
1791    * tests rely on some unsafe assumption about when the chaining
1792    * update is done, we need to be conservative about reordering the
1793    * chaining instructions.
1794    */
1795   rtx fp_addr = gen_reg_rtx (Pmode);
1796   rtx fp_value = gen_reg_rtx (Pmode);
1797   rtx fp_loc;
1798 
1799   emit_move_insn (fp_addr, gen_rtx_PLUS (Pmode, stack_pointer_rtx,
1800 					 GEN_INT (UNITS_PER_WORD)));
1801 
1802   fp_loc = gen_frame_mem (Pmode, fp_addr);
1803 
1804   emit_move_insn (fp_value, fp_loc);
1805 
1806   op1 = force_reg (Pmode, op1);
1807 
1808   emit_move_insn (stack_pointer_rtx,
1809 		  gen_rtx_MINUS (Pmode, stack_pointer_rtx, op1));
1810 
1811   emit_move_insn (fp_addr, gen_rtx_PLUS (Pmode, stack_pointer_rtx,
1812 					 GEN_INT (UNITS_PER_WORD)));
1813 
1814   fp_loc = gen_frame_mem (Pmode, fp_addr);
1815 
1816   emit_move_insn (fp_loc, fp_value);
1817 
1818   emit_move_insn (op0, virtual_stack_dynamic_rtx);
1819 }
1820 
1821 
1822 
1823 /* Multiplies */
1824 
1825 /* Returns the insn_code in ENTRY.  */
1826 static enum insn_code
1827 tilepro_multiply_get_opcode (const struct tilepro_multiply_insn_seq_entry
1828 			     *entry)
1829 {
1830   return tilepro_multiply_insn_seq_decode_opcode[entry->compressed_opcode];
1831 }
1832 
1833 
1834 /* Returns the length of the 'op' array.  */
1835 static int
1836 tilepro_multiply_get_num_ops (const struct tilepro_multiply_insn_seq *seq)
1837 {
1838   /* The array either uses all of its allocated slots or is terminated
1839      by a bogus opcode. Either way, the array size is the index of the
1840      last valid opcode plus one.  */
1841   int i;
1842   for (i = tilepro_multiply_insn_seq_MAX_OPERATIONS - 1; i >= 0; i--)
1843     if (tilepro_multiply_get_opcode (&seq->op[i]) != CODE_FOR_nothing)
1844       return i + 1;
1845 
1846   /* An empty array is not allowed.  */
1847   gcc_unreachable ();
1848 }
1849 
1850 
1851 /* We precompute a number of expression trees for multiplying by
1852    constants.  This generates code for such an expression tree by
1853    walking through the nodes in the tree (which are conveniently
1854    pre-linearized) and emitting an instruction for each one.  */
1855 static void
1856 tilepro_expand_constant_multiply_given_sequence (rtx result, rtx src,
1857 						 const struct
1858 						 tilepro_multiply_insn_seq
1859 						 *seq)
1860 {
1861   int i;
1862   int num_ops;
1863 
1864   /* Keep track of the subexpressions computed so far, so later
1865      instructions can refer to them.  We seed the array with zero and
1866      the value being multiplied.  */
1867   int num_subexprs = 2;
1868   rtx subexprs[tilepro_multiply_insn_seq_MAX_OPERATIONS + 2];
1869   subexprs[0] = const0_rtx;
1870   subexprs[1] = src;
1871 
1872   /* Determine how many instructions we are going to generate.  */
1873   num_ops = tilepro_multiply_get_num_ops (seq);
1874   gcc_assert (num_ops > 0
1875 	      && num_ops <= tilepro_multiply_insn_seq_MAX_OPERATIONS);
1876 
1877   for (i = 0; i < num_ops; i++)
1878     {
1879       const struct tilepro_multiply_insn_seq_entry *entry = &seq->op[i];
1880 
1881       /* Figure out where to store the output of this instruction.  */
1882       const bool is_last_op = (i + 1 == num_ops);
1883       rtx out = is_last_op ? result : gen_reg_rtx (SImode);
1884 
1885       enum insn_code opcode = tilepro_multiply_get_opcode (entry);
1886       if (opcode == CODE_FOR_ashlsi3)
1887 	{
1888 	  /* Handle shift by immediate. This is a special case because
1889 	     the meaning of the second operand is a constant shift
1890 	     count rather than an operand index.  */
1891 
1892 	  /* Make sure the shift count is in range. Zero should not
1893 	     happen.  */
1894 	  const int shift_count = entry->rhs;
1895 	  gcc_assert (shift_count > 0 && shift_count < 32);
1896 
1897 	  /* Emit the actual instruction.  */
1898 	  emit_insn (GEN_FCN (opcode)
1899 		     (out, subexprs[entry->lhs],
1900 		      gen_rtx_CONST_INT (SImode, shift_count)));
1901 	}
1902       else
1903 	{
1904 	  /* Handle a normal two-operand instruction, such as add or
1905 	     s1a.  */
1906 
1907 	  /* Make sure we are referring to a previously computed
1908 	     subexpression.  */
1909 	  gcc_assert (entry->rhs < num_subexprs);
1910 
1911 	  /* Emit the actual instruction.  */
1912 	  emit_insn (GEN_FCN (opcode)
1913 		     (out, subexprs[entry->lhs], subexprs[entry->rhs]));
1914 	}
1915 
1916       /* Record this subexpression for use by later expressions.  */
1917       subexprs[num_subexprs++] = out;
1918     }
1919 }
1920 
1921 
1922 /* bsearch helper function.  */
1923 static int
1924 tilepro_compare_multipliers (const void *key, const void *t)
1925 {
1926   return *(const int *) key -
1927     ((const struct tilepro_multiply_insn_seq *) t)->multiplier;
1928 }
1929 
1930 
1931 /* Returns the tilepro_multiply_insn_seq for multiplier, or NULL if
1932    none exists.  */
1933 static const struct tilepro_multiply_insn_seq *
1934 tilepro_find_multiply_insn_seq_for_constant (int multiplier)
1935 {
1936   return ((const struct tilepro_multiply_insn_seq *)
1937 	  bsearch (&multiplier, tilepro_multiply_insn_seq_table,
1938 		   tilepro_multiply_insn_seq_table_size,
1939 		   sizeof tilepro_multiply_insn_seq_table[0],
1940 		   tilepro_compare_multipliers));
1941 }
1942 
1943 
1944 /* Try to a expand constant multiply in SImode by looking it up in a
1945    precompiled table.  OP0 is the result operand, OP1 is the source
1946    operand, and MULTIPLIER is the value of the constant.  Return true
1947    if it succeeds.  */
1948 static bool
1949 tilepro_expand_const_mulsi (rtx op0, rtx op1, int multiplier)
1950 {
1951   /* See if we have precomputed an efficient way to multiply by this
1952      constant.  */
1953   const struct tilepro_multiply_insn_seq *seq =
1954     tilepro_find_multiply_insn_seq_for_constant (multiplier);
1955   if (seq != NULL)
1956     {
1957       tilepro_expand_constant_multiply_given_sequence (op0, op1, seq);
1958       return true;
1959     }
1960   else
1961     return false;
1962 }
1963 
1964 
1965 /* Expand the mulsi pattern.  */
1966 bool
1967 tilepro_expand_mulsi (rtx op0, rtx op1, rtx op2)
1968 {
1969   if (CONST_INT_P (op2))
1970     {
1971       HOST_WIDE_INT n = trunc_int_for_mode (INTVAL (op2), SImode);
1972       return tilepro_expand_const_mulsi (op0, op1, n);
1973     }
1974   return false;
1975 }
1976 
1977 
1978 /* Expand a high multiply pattern in SImode.  RESULT, OP1, OP2 are the
1979    operands, and SIGN is true if it's a signed multiply, and false if
1980    it's an unsigned multiply.  */
1981 static void
1982 tilepro_expand_high_multiply (rtx result, rtx op1, rtx op2, bool sign)
1983 {
1984   rtx tmp0 = gen_reg_rtx (SImode);
1985   rtx tmp1 = gen_reg_rtx (SImode);
1986   rtx tmp2 = gen_reg_rtx (SImode);
1987   rtx tmp3 = gen_reg_rtx (SImode);
1988   rtx tmp4 = gen_reg_rtx (SImode);
1989   rtx tmp5 = gen_reg_rtx (SImode);
1990   rtx tmp6 = gen_reg_rtx (SImode);
1991   rtx tmp7 = gen_reg_rtx (SImode);
1992   rtx tmp8 = gen_reg_rtx (SImode);
1993   rtx tmp9 = gen_reg_rtx (SImode);
1994   rtx tmp10 = gen_reg_rtx (SImode);
1995   rtx tmp11 = gen_reg_rtx (SImode);
1996   rtx tmp12 = gen_reg_rtx (SImode);
1997   rtx tmp13 = gen_reg_rtx (SImode);
1998   rtx result_lo = gen_reg_rtx (SImode);
1999 
2000   if (sign)
2001     {
2002       emit_insn (gen_insn_mulhl_su (tmp0, op1, op2));
2003       emit_insn (gen_insn_mulhl_su (tmp1, op2, op1));
2004       emit_insn (gen_insn_mulll_uu (tmp2, op1, op2));
2005       emit_insn (gen_insn_mulhh_ss (tmp3, op1, op2));
2006     }
2007   else
2008     {
2009       emit_insn (gen_insn_mulhl_uu (tmp0, op1, op2));
2010       emit_insn (gen_insn_mulhl_uu (tmp1, op2, op1));
2011       emit_insn (gen_insn_mulll_uu (tmp2, op1, op2));
2012       emit_insn (gen_insn_mulhh_uu (tmp3, op1, op2));
2013     }
2014 
2015   emit_move_insn (tmp4, (gen_rtx_ASHIFT (SImode, tmp0, GEN_INT (16))));
2016 
2017   emit_move_insn (tmp5, (gen_rtx_ASHIFT (SImode, tmp1, GEN_INT (16))));
2018 
2019   emit_move_insn (tmp6, (gen_rtx_PLUS (SImode, tmp4, tmp5)));
2020   emit_move_insn (result_lo, (gen_rtx_PLUS (SImode, tmp2, tmp6)));
2021 
2022   emit_move_insn (tmp7, gen_rtx_LTU (SImode, tmp6, tmp4));
2023   emit_move_insn (tmp8, gen_rtx_LTU (SImode, result_lo, tmp2));
2024 
2025   if (sign)
2026     {
2027       emit_move_insn (tmp9, (gen_rtx_ASHIFTRT (SImode, tmp0, GEN_INT (16))));
2028       emit_move_insn (tmp10, (gen_rtx_ASHIFTRT (SImode, tmp1, GEN_INT (16))));
2029     }
2030   else
2031     {
2032       emit_move_insn (tmp9, (gen_rtx_LSHIFTRT (SImode, tmp0, GEN_INT (16))));
2033       emit_move_insn (tmp10, (gen_rtx_LSHIFTRT (SImode, tmp1, GEN_INT (16))));
2034     }
2035 
2036   emit_move_insn (tmp11, (gen_rtx_PLUS (SImode, tmp3, tmp7)));
2037   emit_move_insn (tmp12, (gen_rtx_PLUS (SImode, tmp8, tmp9)));
2038   emit_move_insn (tmp13, (gen_rtx_PLUS (SImode, tmp11, tmp12)));
2039   emit_move_insn (result, (gen_rtx_PLUS (SImode, tmp13, tmp10)));
2040 }
2041 
2042 
2043 /* Implement smulsi3_highpart.  */
2044 void
2045 tilepro_expand_smulsi3_highpart (rtx op0, rtx op1, rtx op2)
2046 {
2047   tilepro_expand_high_multiply (op0, op1, op2, true);
2048 }
2049 
2050 
2051 /* Implement umulsi3_highpart.  */
2052 void
2053 tilepro_expand_umulsi3_highpart (rtx op0, rtx op1, rtx op2)
2054 {
2055   tilepro_expand_high_multiply (op0, op1, op2, false);
2056 }
2057 
2058 
2059 
2060 /* Compare and branches  */
2061 
2062 /* Helper function to handle DImode for tilepro_emit_setcc_internal.  */
2063 static bool
2064 tilepro_emit_setcc_internal_di (rtx res, enum rtx_code code, rtx op0, rtx op1)
2065 {
2066   rtx operands[2], lo_half[2], hi_half[2];
2067   rtx tmp, tmp0, tmp1, tmp2;
2068   bool swap = false;
2069 
2070   /* Reduce the number of cases we need to handle by reversing the
2071      operands.  */
2072   switch (code)
2073     {
2074     case EQ:
2075     case NE:
2076     case LE:
2077     case LT:
2078     case LEU:
2079     case LTU:
2080       /* We handle these compares directly.  */
2081       break;
2082 
2083     case GE:
2084     case GT:
2085     case GEU:
2086     case GTU:
2087       /* Reverse the operands.  */
2088       swap = true;
2089       break;
2090 
2091     default:
2092       /* We should not have called this with any other code.  */
2093       gcc_unreachable ();
2094     }
2095 
2096   if (swap)
2097     {
2098       code = swap_condition (code);
2099       tmp = op0, op0 = op1, op1 = tmp;
2100     }
2101 
2102   operands[0] = op0;
2103   operands[1] = op1;
2104 
2105   split_di (operands, 2, lo_half, hi_half);
2106 
2107   if (!reg_or_0_operand (lo_half[0], SImode))
2108     lo_half[0] = force_reg (SImode, lo_half[0]);
2109 
2110   if (!reg_or_0_operand (hi_half[0], SImode))
2111     hi_half[0] = force_reg (SImode, hi_half[0]);
2112 
2113   if (!CONST_INT_P (lo_half[1]) && !register_operand (lo_half[1], SImode))
2114     lo_half[1] = force_reg (SImode, lo_half[1]);
2115 
2116   if (!CONST_INT_P (hi_half[1]) && !register_operand (hi_half[1], SImode))
2117     hi_half[1] = force_reg (SImode, hi_half[1]);
2118 
2119   tmp0 = gen_reg_rtx (SImode);
2120   tmp1 = gen_reg_rtx (SImode);
2121   tmp2 = gen_reg_rtx (SImode);
2122 
2123   switch (code)
2124     {
2125     case EQ:
2126       emit_insn (gen_insn_seq (tmp0, lo_half[0], lo_half[1]));
2127       emit_insn (gen_insn_seq (tmp1, hi_half[0], hi_half[1]));
2128       emit_insn (gen_andsi3 (res, tmp0, tmp1));
2129       return true;
2130       break;
2131     case NE:
2132       emit_insn (gen_insn_sne (tmp0, lo_half[0], lo_half[1]));
2133       emit_insn (gen_insn_sne (tmp1, hi_half[0], hi_half[1]));
2134       emit_insn (gen_iorsi3 (res, tmp0, tmp1));
2135       return true;
2136       break;
2137     case LE:
2138       emit_insn (gen_insn_slte (tmp0, hi_half[0], hi_half[1]));
2139       emit_insn (gen_insn_seq (tmp1, hi_half[0], hi_half[1]));
2140       emit_insn (gen_insn_slte_u (tmp2, lo_half[0], lo_half[1]));
2141       emit_insn (gen_insn_mvnz (res, tmp0, tmp1, tmp2));
2142       return true;
2143     case LT:
2144       if (operands[1] == const0_rtx)
2145 	{
2146 	  emit_insn (gen_lshrsi3 (res, hi_half[0], GEN_INT (31)));
2147 	  return true;
2148 	}
2149       else
2150 	{
2151 	  emit_insn (gen_insn_slt (tmp0, hi_half[0], hi_half[1]));
2152 	  emit_insn (gen_insn_seq (tmp1, hi_half[0], hi_half[1]));
2153 	  emit_insn (gen_insn_slt_u (tmp2, lo_half[0], lo_half[1]));
2154 	  emit_insn (gen_insn_mvnz (res, tmp0, tmp1, tmp2));
2155 	}
2156       return true;
2157     case LEU:
2158       emit_insn (gen_insn_slte_u (tmp0, hi_half[0], hi_half[1]));
2159       emit_insn (gen_insn_seq (tmp1, hi_half[0], hi_half[1]));
2160       emit_insn (gen_insn_slte_u (tmp2, lo_half[0], lo_half[1]));
2161       emit_insn (gen_insn_mvnz (res, tmp0, tmp1, tmp2));
2162       return true;
2163     case LTU:
2164       emit_insn (gen_insn_slt_u (tmp0, hi_half[0], hi_half[1]));
2165       emit_insn (gen_insn_seq (tmp1, hi_half[0], hi_half[1]));
2166       emit_insn (gen_insn_slt_u (tmp2, lo_half[0], lo_half[1]));
2167       emit_insn (gen_insn_mvnz (res, tmp0, tmp1, tmp2));
2168       return true;
2169     default:
2170       gcc_unreachable ();
2171     }
2172 
2173   return false;
2174 }
2175 
2176 
2177 /* Certain simplifications can be done to make invalid setcc
2178    operations valid.  Return the final comparison, or NULL if we can't
2179    work.  */
2180 static bool
2181 tilepro_emit_setcc_internal (rtx res, enum rtx_code code, rtx op0, rtx op1,
2182 			     enum machine_mode cmp_mode)
2183 {
2184   rtx tmp;
2185   bool swap = false;
2186 
2187   if (cmp_mode == DImode)
2188     {
2189       return tilepro_emit_setcc_internal_di (res, code, op0, op1);
2190     }
2191 
2192   /* The general case: fold the comparison code to the types of
2193      compares that we have, choosing the branch as necessary.  */
2194 
2195   switch (code)
2196     {
2197     case EQ:
2198     case NE:
2199     case LE:
2200     case LT:
2201     case LEU:
2202     case LTU:
2203       /* We have these compares.  */
2204       break;
2205 
2206     case GE:
2207     case GT:
2208     case GEU:
2209     case GTU:
2210       /* We do not have these compares, so we reverse the
2211          operands.  */
2212       swap = true;
2213       break;
2214 
2215     default:
2216       /* We should not have called this with any other code.  */
2217       gcc_unreachable ();
2218     }
2219 
2220   if (swap)
2221     {
2222       code = swap_condition (code);
2223       tmp = op0, op0 = op1, op1 = tmp;
2224     }
2225 
2226   if (!reg_or_0_operand (op0, SImode))
2227     op0 = force_reg (SImode, op0);
2228 
2229   if (!CONST_INT_P (op1) && !register_operand (op1, SImode))
2230     op1 = force_reg (SImode, op1);
2231 
2232   /* Return the setcc comparison.  */
2233   emit_insn (gen_rtx_SET (VOIDmode, res,
2234 			  gen_rtx_fmt_ee (code, SImode, op0, op1)));
2235 
2236   return true;
2237 }
2238 
2239 
2240 /* Implement cstore patterns.  */
2241 bool
2242 tilepro_emit_setcc (rtx operands[], enum machine_mode cmp_mode)
2243 {
2244   return
2245     tilepro_emit_setcc_internal (operands[0], GET_CODE (operands[1]),
2246 				 operands[2], operands[3], cmp_mode);
2247 }
2248 
2249 
2250 /* Return whether CODE is a signed comparison.  */
2251 static bool
2252 signed_compare_p (enum rtx_code code)
2253 {
2254   return (code == EQ || code == NE || code == LT || code == LE
2255 	  || code == GT || code == GE);
2256 }
2257 
2258 
2259 /* Generate the comparison for an SImode conditional branch.  */
2260 static rtx
2261 tilepro_emit_cc_test (enum rtx_code code, rtx op0, rtx op1,
2262 		      enum machine_mode cmp_mode, bool eq_ne_only)
2263 {
2264   enum rtx_code branch_code;
2265   rtx temp;
2266 
2267   /* Check for a compare against zero using a comparison we can do
2268      directly.  */
2269   if (cmp_mode != DImode
2270       && op1 == const0_rtx
2271       && (code == EQ || code == NE
2272 	  || (!eq_ne_only && signed_compare_p (code))))
2273     {
2274       op0 = force_reg (SImode, op0);
2275       return gen_rtx_fmt_ee (code, VOIDmode, op0, const0_rtx);
2276     }
2277 
2278   /* The general case: fold the comparison code to the types of
2279      compares that we have, choosing the branch as necessary.  */
2280   switch (code)
2281     {
2282     case EQ:
2283     case LE:
2284     case LT:
2285     case LEU:
2286     case LTU:
2287       /* We have these compares.  */
2288       branch_code = NE;
2289       break;
2290 
2291     case NE:
2292     case GE:
2293     case GT:
2294     case GEU:
2295     case GTU:
2296       /* These must be reversed (except NE, but let's
2297          canonicalize).  */
2298       code = reverse_condition (code);
2299       branch_code = EQ;
2300       break;
2301 
2302     default:
2303       gcc_unreachable ();
2304     }
2305 
2306   if (cmp_mode != DImode
2307       && CONST_INT_P (op1) && (!satisfies_constraint_I (op1) || code == LEU))
2308     {
2309       HOST_WIDE_INT n = trunc_int_for_mode (INTVAL (op1), SImode);
2310 
2311       switch (code)
2312 	{
2313 	case EQ:
2314 	  /* Subtract off the value we want to compare against and see
2315 	     if we get zero.  This is cheaper than creating a constant
2316 	     in a register. Except that subtracting -128 is more
2317 	     expensive than seqi to -128, so we leave that alone.  */
2318 	  /* ??? Don't do this when comparing against symbols,
2319 	     otherwise we'll reduce (&x == 0x1234) to (&x-0x1234 ==
2320 	     0), which will be declared false out of hand (at least
2321 	     for non-weak).  */
2322 	  if (!(symbolic_operand (op0, VOIDmode)
2323 		|| (REG_P (op0) && REG_POINTER (op0))))
2324 	    {
2325 	      /* To compare against MIN_INT, we add MIN_INT and check
2326 	         for 0.  */
2327 	      HOST_WIDE_INT add;
2328 	      if (n != -2147483647 - 1)
2329 		add = -n;
2330 	      else
2331 		add = n;
2332 
2333 	      op0 = force_reg (SImode, op0);
2334 	      temp = gen_reg_rtx (SImode);
2335 	      emit_insn (gen_addsi3 (temp, op0, gen_int_si (add)));
2336 	      return gen_rtx_fmt_ee (reverse_condition (branch_code),
2337 				     VOIDmode, temp, const0_rtx);
2338 	    }
2339 	  break;
2340 
2341 	case LEU:
2342 	  if (n == -1)
2343 	    break;
2344 	  /* FALLTHRU */
2345 
2346 	case LTU:
2347 	  /* Change ((unsigned)x < 0x1000) into !((unsigned)x >> 12),
2348 	     etc.  */
2349 	  {
2350 	    int first = exact_log2 (code == LTU ? n : n + 1);
2351 	    if (first != -1)
2352 	      {
2353 		op0 = force_reg (SImode, op0);
2354 		temp = gen_reg_rtx (SImode);
2355 		emit_move_insn (temp,
2356 				gen_rtx_LSHIFTRT (SImode, op0,
2357 						  gen_int_si (first)));
2358 		return gen_rtx_fmt_ee (reverse_condition (branch_code),
2359 				       VOIDmode, temp, const0_rtx);
2360 	      }
2361 	  }
2362 	  break;
2363 
2364 	default:
2365 	  break;
2366 	}
2367     }
2368 
2369   /* Compute a flag saying whether we should branch.  */
2370   temp = gen_reg_rtx (SImode);
2371   tilepro_emit_setcc_internal (temp, code, op0, op1, cmp_mode);
2372 
2373   /* Return the branch comparison.  */
2374   return gen_rtx_fmt_ee (branch_code, VOIDmode, temp, const0_rtx);
2375 }
2376 
2377 
2378 /* Generate the comparison for a conditional branch.  */
2379 void
2380 tilepro_emit_conditional_branch (rtx operands[], enum machine_mode cmp_mode)
2381 {
2382   rtx cmp_rtx =
2383     tilepro_emit_cc_test (GET_CODE (operands[0]), operands[1], operands[2],
2384 			  cmp_mode, false);
2385   rtx branch_rtx = gen_rtx_SET (VOIDmode, pc_rtx,
2386 				gen_rtx_IF_THEN_ELSE (VOIDmode, cmp_rtx,
2387 						      gen_rtx_LABEL_REF
2388 						      (VOIDmode,
2389 						       operands[3]),
2390 						      pc_rtx));
2391   emit_jump_insn (branch_rtx);
2392 }
2393 
2394 
2395 /* Implement the movsicc pattern.  */
2396 rtx
2397 tilepro_emit_conditional_move (rtx cmp)
2398 {
2399   return
2400     tilepro_emit_cc_test (GET_CODE (cmp), XEXP (cmp, 0), XEXP (cmp, 1),
2401 			  GET_MODE (XEXP (cmp, 0)), true);
2402 }
2403 
2404 
2405 /* Return true if INSN is annotated with a REG_BR_PROB note that
2406    indicates it's a branch that's predicted taken.  */
2407 static bool
2408 cbranch_predicted_p (rtx insn)
2409 {
2410   rtx x = find_reg_note (insn, REG_BR_PROB, 0);
2411 
2412   if (x)
2413     {
2414       int pred_val = INTVAL (XEXP (x, 0));
2415 
2416       return pred_val >= REG_BR_PROB_BASE / 2;
2417     }
2418 
2419   return false;
2420 }
2421 
2422 
2423 /* Output assembly code for a specific branch instruction, appending
2424    the branch prediction flag to the opcode if appropriate.  */
2425 static const char *
2426 tilepro_output_simple_cbranch_with_opcode (rtx insn, const char *opcode,
2427 					   int regop, bool netreg_p,
2428 					   bool reverse_predicted)
2429 {
2430   static char buf[64];
2431   sprintf (buf, "%s%s\t%%%c%d, %%l0", opcode,
2432 	   (cbranch_predicted_p (insn) ^ reverse_predicted) ? "t" : "",
2433 	   netreg_p ? 'N' : 'r', regop);
2434   return buf;
2435 }
2436 
2437 
2438 /* Output assembly code for a specific branch instruction, appending
2439    the branch prediction flag to the opcode if appropriate.  */
2440 const char *
2441 tilepro_output_cbranch_with_opcode (rtx insn, rtx *operands,
2442 				    const char *opcode,
2443 				    const char *rev_opcode,
2444 				    int regop, bool netreg_p)
2445 {
2446   const char *branch_if_false;
2447   rtx taken, not_taken;
2448   bool is_simple_branch;
2449 
2450   gcc_assert (LABEL_P (operands[0]));
2451 
2452   is_simple_branch = true;
2453   if (INSN_ADDRESSES_SET_P ())
2454     {
2455       int from_addr = INSN_ADDRESSES (INSN_UID (insn));
2456       int to_addr = INSN_ADDRESSES (INSN_UID (operands[0]));
2457       int delta = to_addr - from_addr;
2458       is_simple_branch = IN_RANGE (delta, -524288, 524280);
2459     }
2460 
2461   if (is_simple_branch)
2462     {
2463       /* Just a simple conditional branch.  */
2464       return
2465 	tilepro_output_simple_cbranch_with_opcode (insn, opcode, regop,
2466 						   netreg_p, false);
2467     }
2468 
2469   /* Generate a reversed branch around a direct jump.  This fallback
2470      does not use branch-likely instructions.  */
2471   not_taken = gen_label_rtx ();
2472   taken = operands[0];
2473 
2474   /* Generate the reversed branch to NOT_TAKEN.  */
2475   operands[0] = not_taken;
2476   branch_if_false =
2477     tilepro_output_simple_cbranch_with_opcode (insn, rev_opcode, regop,
2478 					       netreg_p, true);
2479   output_asm_insn (branch_if_false, operands);
2480 
2481   output_asm_insn ("j\t%l0", &taken);
2482 
2483   /* Output NOT_TAKEN.  */
2484   targetm.asm_out.internal_label (asm_out_file, "L",
2485 				  CODE_LABEL_NUMBER (not_taken));
2486   return "";
2487 }
2488 
2489 
2490 /* Output assembly code for a conditional branch instruction.  */
2491 const char *
2492 tilepro_output_cbranch (rtx insn, rtx *operands, bool reversed)
2493 {
2494   enum rtx_code code = GET_CODE (operands[1]);
2495   const char *opcode;
2496   const char *rev_opcode;
2497 
2498   if (reversed)
2499     code = reverse_condition (code);
2500 
2501   switch (code)
2502     {
2503     case NE:
2504       opcode = "bnz";
2505       rev_opcode = "bz";
2506       break;
2507     case EQ:
2508       opcode = "bz";
2509       rev_opcode = "bnz";
2510       break;
2511     case GE:
2512       opcode = "bgez";
2513       rev_opcode = "blz";
2514       break;
2515     case GT:
2516       opcode = "bgz";
2517       rev_opcode = "blez";
2518       break;
2519     case LE:
2520       opcode = "blez";
2521       rev_opcode = "bgz";
2522       break;
2523     case LT:
2524       opcode = "blz";
2525       rev_opcode = "bgez";
2526       break;
2527     default:
2528       gcc_unreachable ();
2529     }
2530 
2531   return
2532     tilepro_output_cbranch_with_opcode (insn, operands, opcode, rev_opcode,
2533 					2, false);
2534 }
2535 
2536 
2537 /* Implement the tablejump pattern.  */
2538 void
2539 tilepro_expand_tablejump (rtx op0, rtx op1)
2540 {
2541   if (flag_pic)
2542     {
2543       rtx table = gen_rtx_LABEL_REF (Pmode, op1);
2544       rtx temp = gen_reg_rtx (Pmode);
2545       rtx text_label_symbol = tilepro_text_label_symbol ();
2546       rtx text_label_rtx = tilepro_text_label_rtx ();
2547 
2548       emit_insn (gen_addli_pcrel (temp, text_label_rtx,
2549 				  table, text_label_symbol));
2550       emit_insn (gen_auli_pcrel (temp, temp, table, text_label_symbol));
2551       emit_move_insn (temp,
2552 		      gen_rtx_PLUS (Pmode,
2553 				    convert_to_mode (Pmode, op0, false),
2554 				    temp));
2555       op0 = temp;
2556     }
2557 
2558   emit_jump_insn (gen_tablejump_aux (op0, op1));
2559 }
2560 
2561 
2562 /* Expand a builtin vector binary op, by calling gen function GEN with
2563    operands in the proper modes.  DEST is converted to DEST_MODE, and
2564    src0 and src1 (if DO_SRC1 is true) is converted to SRC_MODE.  */
2565 void
2566 tilepro_expand_builtin_vector_binop (rtx (*gen) (rtx, rtx, rtx),
2567 				     enum machine_mode dest_mode,
2568 				     rtx dest,
2569 				     enum machine_mode src_mode,
2570 				     rtx src0, rtx src1, bool do_src1)
2571 {
2572   dest = gen_lowpart (dest_mode, dest);
2573 
2574   if (src0 == const0_rtx)
2575     src0 = CONST0_RTX (src_mode);
2576   else
2577     src0 = gen_lowpart (src_mode, src0);
2578 
2579   if (do_src1)
2580     {
2581       if (src1 == const0_rtx)
2582 	src1 = CONST0_RTX (src_mode);
2583       else
2584 	src1 = gen_lowpart (src_mode, src1);
2585     }
2586 
2587   emit_insn ((*gen) (dest, src0, src1));
2588 }
2589 
2590 
2591 
2592 /* Intrinsics  */
2593 
2594 struct tile_builtin_info
2595 {
2596   enum insn_code icode;
2597   tree fndecl;
2598 };
2599 
2600 static struct tile_builtin_info tilepro_builtin_info[TILEPRO_BUILTIN_max] = {
2601   { CODE_FOR_addsi3,                    NULL }, /* add */
2602   { CODE_FOR_insn_addb,                 NULL }, /* addb */
2603   { CODE_FOR_insn_addbs_u,              NULL }, /* addbs_u */
2604   { CODE_FOR_insn_addh,                 NULL }, /* addh */
2605   { CODE_FOR_insn_addhs,                NULL }, /* addhs */
2606   { CODE_FOR_insn_addib,                NULL }, /* addib */
2607   { CODE_FOR_insn_addih,                NULL }, /* addih */
2608   { CODE_FOR_insn_addlis,               NULL }, /* addlis */
2609   { CODE_FOR_ssaddsi3,                  NULL }, /* adds */
2610   { CODE_FOR_insn_adiffb_u,             NULL }, /* adiffb_u */
2611   { CODE_FOR_insn_adiffh,               NULL }, /* adiffh */
2612   { CODE_FOR_andsi3,                    NULL }, /* and */
2613   { CODE_FOR_insn_auli,                 NULL }, /* auli */
2614   { CODE_FOR_insn_avgb_u,               NULL }, /* avgb_u */
2615   { CODE_FOR_insn_avgh,                 NULL }, /* avgh */
2616   { CODE_FOR_insn_bitx,                 NULL }, /* bitx */
2617   { CODE_FOR_bswapsi2,                  NULL }, /* bytex */
2618   { CODE_FOR_clzsi2,                    NULL }, /* clz */
2619   { CODE_FOR_insn_crc32_32,             NULL }, /* crc32_32 */
2620   { CODE_FOR_insn_crc32_8,              NULL }, /* crc32_8 */
2621   { CODE_FOR_ctzsi2,                    NULL }, /* ctz */
2622   { CODE_FOR_insn_drain,                NULL }, /* drain */
2623   { CODE_FOR_insn_dtlbpr,               NULL }, /* dtlbpr */
2624   { CODE_FOR_insn_dword_align,          NULL }, /* dword_align */
2625   { CODE_FOR_insn_finv,                 NULL }, /* finv */
2626   { CODE_FOR_insn_flush,                NULL }, /* flush */
2627   { CODE_FOR_insn_fnop,                 NULL }, /* fnop */
2628   { CODE_FOR_insn_icoh,                 NULL }, /* icoh */
2629   { CODE_FOR_insn_ill,                  NULL }, /* ill */
2630   { CODE_FOR_insn_info,                 NULL }, /* info */
2631   { CODE_FOR_insn_infol,                NULL }, /* infol */
2632   { CODE_FOR_insn_inthb,                NULL }, /* inthb */
2633   { CODE_FOR_insn_inthh,                NULL }, /* inthh */
2634   { CODE_FOR_insn_intlb,                NULL }, /* intlb */
2635   { CODE_FOR_insn_intlh,                NULL }, /* intlh */
2636   { CODE_FOR_insn_inv,                  NULL }, /* inv */
2637   { CODE_FOR_insn_lb,                   NULL }, /* lb */
2638   { CODE_FOR_insn_lb_u,                 NULL }, /* lb_u */
2639   { CODE_FOR_insn_lh,                   NULL }, /* lh */
2640   { CODE_FOR_insn_lh_u,                 NULL }, /* lh_u */
2641   { CODE_FOR_insn_lnk,                  NULL }, /* lnk */
2642   { CODE_FOR_insn_lw,                   NULL }, /* lw */
2643   { CODE_FOR_insn_lw_na,                NULL }, /* lw_na */
2644   { CODE_FOR_insn_lb_L2,                NULL }, /* lb_L2 */
2645   { CODE_FOR_insn_lb_u_L2,              NULL }, /* lb_u_L2 */
2646   { CODE_FOR_insn_lh_L2,                NULL }, /* lh_L2 */
2647   { CODE_FOR_insn_lh_u_L2,              NULL }, /* lh_u_L2 */
2648   { CODE_FOR_insn_lw_L2,                NULL }, /* lw_L2 */
2649   { CODE_FOR_insn_lw_na_L2,             NULL }, /* lw_na_L2 */
2650   { CODE_FOR_insn_lb_miss,              NULL }, /* lb_miss */
2651   { CODE_FOR_insn_lb_u_miss,            NULL }, /* lb_u_miss */
2652   { CODE_FOR_insn_lh_miss,              NULL }, /* lh_miss */
2653   { CODE_FOR_insn_lh_u_miss,            NULL }, /* lh_u_miss */
2654   { CODE_FOR_insn_lw_miss,              NULL }, /* lw_miss */
2655   { CODE_FOR_insn_lw_na_miss,           NULL }, /* lw_na_miss */
2656   { CODE_FOR_insn_maxb_u,               NULL }, /* maxb_u */
2657   { CODE_FOR_insn_maxh,                 NULL }, /* maxh */
2658   { CODE_FOR_insn_maxib_u,              NULL }, /* maxib_u */
2659   { CODE_FOR_insn_maxih,                NULL }, /* maxih */
2660   { CODE_FOR_memory_barrier,            NULL }, /* mf */
2661   { CODE_FOR_insn_mfspr,                NULL }, /* mfspr */
2662   { CODE_FOR_insn_minb_u,               NULL }, /* minb_u */
2663   { CODE_FOR_insn_minh,                 NULL }, /* minh */
2664   { CODE_FOR_insn_minib_u,              NULL }, /* minib_u */
2665   { CODE_FOR_insn_minih,                NULL }, /* minih */
2666   { CODE_FOR_insn_mm,                   NULL }, /* mm */
2667   { CODE_FOR_insn_mnz,                  NULL }, /* mnz */
2668   { CODE_FOR_insn_mnzb,                 NULL }, /* mnzb */
2669   { CODE_FOR_insn_mnzh,                 NULL }, /* mnzh */
2670   { CODE_FOR_movsi,                     NULL }, /* move */
2671   { CODE_FOR_insn_movelis,              NULL }, /* movelis */
2672   { CODE_FOR_insn_mtspr,                NULL }, /* mtspr */
2673   { CODE_FOR_insn_mulhh_ss,             NULL }, /* mulhh_ss */
2674   { CODE_FOR_insn_mulhh_su,             NULL }, /* mulhh_su */
2675   { CODE_FOR_insn_mulhh_uu,             NULL }, /* mulhh_uu */
2676   { CODE_FOR_insn_mulhha_ss,            NULL }, /* mulhha_ss */
2677   { CODE_FOR_insn_mulhha_su,            NULL }, /* mulhha_su */
2678   { CODE_FOR_insn_mulhha_uu,            NULL }, /* mulhha_uu */
2679   { CODE_FOR_insn_mulhhsa_uu,           NULL }, /* mulhhsa_uu */
2680   { CODE_FOR_insn_mulhl_ss,             NULL }, /* mulhl_ss */
2681   { CODE_FOR_insn_mulhl_su,             NULL }, /* mulhl_su */
2682   { CODE_FOR_insn_mulhl_us,             NULL }, /* mulhl_us */
2683   { CODE_FOR_insn_mulhl_uu,             NULL }, /* mulhl_uu */
2684   { CODE_FOR_insn_mulhla_ss,            NULL }, /* mulhla_ss */
2685   { CODE_FOR_insn_mulhla_su,            NULL }, /* mulhla_su */
2686   { CODE_FOR_insn_mulhla_us,            NULL }, /* mulhla_us */
2687   { CODE_FOR_insn_mulhla_uu,            NULL }, /* mulhla_uu */
2688   { CODE_FOR_insn_mulhlsa_uu,           NULL }, /* mulhlsa_uu */
2689   { CODE_FOR_insn_mulll_ss,             NULL }, /* mulll_ss */
2690   { CODE_FOR_insn_mulll_su,             NULL }, /* mulll_su */
2691   { CODE_FOR_insn_mulll_uu,             NULL }, /* mulll_uu */
2692   { CODE_FOR_insn_mullla_ss,            NULL }, /* mullla_ss */
2693   { CODE_FOR_insn_mullla_su,            NULL }, /* mullla_su */
2694   { CODE_FOR_insn_mullla_uu,            NULL }, /* mullla_uu */
2695   { CODE_FOR_insn_mulllsa_uu,           NULL }, /* mulllsa_uu */
2696   { CODE_FOR_insn_mvnz,                 NULL }, /* mvnz */
2697   { CODE_FOR_insn_mvz,                  NULL }, /* mvz */
2698   { CODE_FOR_insn_mz,                   NULL }, /* mz */
2699   { CODE_FOR_insn_mzb,                  NULL }, /* mzb */
2700   { CODE_FOR_insn_mzh,                  NULL }, /* mzh */
2701   { CODE_FOR_insn_nap,                  NULL }, /* nap */
2702   { CODE_FOR_nop,                       NULL }, /* nop */
2703   { CODE_FOR_insn_nor,                  NULL }, /* nor */
2704   { CODE_FOR_iorsi3,                    NULL }, /* or */
2705   { CODE_FOR_insn_packbs_u,             NULL }, /* packbs_u */
2706   { CODE_FOR_insn_packhb,               NULL }, /* packhb */
2707   { CODE_FOR_insn_packhs,               NULL }, /* packhs */
2708   { CODE_FOR_insn_packlb,               NULL }, /* packlb */
2709   { CODE_FOR_popcountsi2,               NULL }, /* pcnt */
2710   { CODE_FOR_insn_prefetch,             NULL }, /* prefetch */
2711   { CODE_FOR_insn_prefetch_L1,          NULL }, /* prefetch_L1 */
2712   { CODE_FOR_rotlsi3,                   NULL }, /* rl */
2713   { CODE_FOR_insn_s1a,                  NULL }, /* s1a */
2714   { CODE_FOR_insn_s2a,                  NULL }, /* s2a */
2715   { CODE_FOR_insn_s3a,                  NULL }, /* s3a */
2716   { CODE_FOR_insn_sadab_u,              NULL }, /* sadab_u */
2717   { CODE_FOR_insn_sadah,                NULL }, /* sadah */
2718   { CODE_FOR_insn_sadah_u,              NULL }, /* sadah_u */
2719   { CODE_FOR_insn_sadb_u,               NULL }, /* sadb_u */
2720   { CODE_FOR_insn_sadh,                 NULL }, /* sadh */
2721   { CODE_FOR_insn_sadh_u,               NULL }, /* sadh_u */
2722   { CODE_FOR_insn_sb,                   NULL }, /* sb */
2723   { CODE_FOR_insn_seq,                  NULL }, /* seq */
2724   { CODE_FOR_insn_seqb,                 NULL }, /* seqb */
2725   { CODE_FOR_insn_seqh,                 NULL }, /* seqh */
2726   { CODE_FOR_insn_seqib,                NULL }, /* seqib */
2727   { CODE_FOR_insn_seqih,                NULL }, /* seqih */
2728   { CODE_FOR_insn_sh,                   NULL }, /* sh */
2729   { CODE_FOR_ashlsi3,                   NULL }, /* shl */
2730   { CODE_FOR_insn_shlb,                 NULL }, /* shlb */
2731   { CODE_FOR_insn_shlh,                 NULL }, /* shlh */
2732   { CODE_FOR_insn_shlb,                 NULL }, /* shlib */
2733   { CODE_FOR_insn_shlh,                 NULL }, /* shlih */
2734   { CODE_FOR_lshrsi3,                   NULL }, /* shr */
2735   { CODE_FOR_insn_shrb,                 NULL }, /* shrb */
2736   { CODE_FOR_insn_shrh,                 NULL }, /* shrh */
2737   { CODE_FOR_insn_shrb,                 NULL }, /* shrib */
2738   { CODE_FOR_insn_shrh,                 NULL }, /* shrih */
2739   { CODE_FOR_insn_slt,                  NULL }, /* slt */
2740   { CODE_FOR_insn_slt_u,                NULL }, /* slt_u */
2741   { CODE_FOR_insn_sltb,                 NULL }, /* sltb */
2742   { CODE_FOR_insn_sltb_u,               NULL }, /* sltb_u */
2743   { CODE_FOR_insn_slte,                 NULL }, /* slte */
2744   { CODE_FOR_insn_slte_u,               NULL }, /* slte_u */
2745   { CODE_FOR_insn_slteb,                NULL }, /* slteb */
2746   { CODE_FOR_insn_slteb_u,              NULL }, /* slteb_u */
2747   { CODE_FOR_insn_slteh,                NULL }, /* slteh */
2748   { CODE_FOR_insn_slteh_u,              NULL }, /* slteh_u */
2749   { CODE_FOR_insn_slth,                 NULL }, /* slth */
2750   { CODE_FOR_insn_slth_u,               NULL }, /* slth_u */
2751   { CODE_FOR_insn_sltib,                NULL }, /* sltib */
2752   { CODE_FOR_insn_sltib_u,              NULL }, /* sltib_u */
2753   { CODE_FOR_insn_sltih,                NULL }, /* sltih */
2754   { CODE_FOR_insn_sltih_u,              NULL }, /* sltih_u */
2755   { CODE_FOR_insn_sne,                  NULL }, /* sne */
2756   { CODE_FOR_insn_sneb,                 NULL }, /* sneb */
2757   { CODE_FOR_insn_sneh,                 NULL }, /* sneh */
2758   { CODE_FOR_ashrsi3,                   NULL }, /* sra */
2759   { CODE_FOR_insn_srab,                 NULL }, /* srab */
2760   { CODE_FOR_insn_srah,                 NULL }, /* srah */
2761   { CODE_FOR_insn_srab,                 NULL }, /* sraib */
2762   { CODE_FOR_insn_srah,                 NULL }, /* sraih */
2763   { CODE_FOR_subsi3,                    NULL }, /* sub */
2764   { CODE_FOR_insn_subb,                 NULL }, /* subb */
2765   { CODE_FOR_insn_subbs_u,              NULL }, /* subbs_u */
2766   { CODE_FOR_insn_subh,                 NULL }, /* subh */
2767   { CODE_FOR_insn_subhs,                NULL }, /* subhs */
2768   { CODE_FOR_sssubsi3,                  NULL }, /* subs */
2769   { CODE_FOR_insn_sw,                   NULL }, /* sw */
2770   { CODE_FOR_insn_tblidxb0,             NULL }, /* tblidxb0 */
2771   { CODE_FOR_insn_tblidxb1,             NULL }, /* tblidxb1 */
2772   { CODE_FOR_insn_tblidxb2,             NULL }, /* tblidxb2 */
2773   { CODE_FOR_insn_tblidxb3,             NULL }, /* tblidxb3 */
2774   { CODE_FOR_insn_tns,                  NULL }, /* tns */
2775   { CODE_FOR_insn_wh64,                 NULL }, /* wh64 */
2776   { CODE_FOR_xorsi3,                    NULL }, /* xor */
2777   { CODE_FOR_tilepro_network_barrier,   NULL }, /* network_barrier */
2778   { CODE_FOR_tilepro_idn0_receive,      NULL }, /* idn0_receive */
2779   { CODE_FOR_tilepro_idn1_receive,      NULL }, /* idn1_receive */
2780   { CODE_FOR_tilepro_idn_send,          NULL }, /* idn_send */
2781   { CODE_FOR_tilepro_sn_receive,        NULL }, /* sn_receive */
2782   { CODE_FOR_tilepro_sn_send,           NULL }, /* sn_send */
2783   { CODE_FOR_tilepro_udn0_receive,      NULL }, /* udn0_receive */
2784   { CODE_FOR_tilepro_udn1_receive,      NULL }, /* udn1_receive */
2785   { CODE_FOR_tilepro_udn2_receive,      NULL }, /* udn2_receive */
2786   { CODE_FOR_tilepro_udn3_receive,      NULL }, /* udn3_receive */
2787   { CODE_FOR_tilepro_udn_send,          NULL }, /* udn_send */
2788 };
2789 
2790 
2791 struct tilepro_builtin_def
2792 {
2793   const char *name;
2794   enum tilepro_builtin code;
2795   bool is_const;
2796   /* The first character is the return type.  Subsequent characters
2797      are the argument types. See char_to_type.  */
2798   const char *type;
2799 };
2800 
2801 
2802 static const struct tilepro_builtin_def tilepro_builtins[] = {
2803   { "__insn_add",             TILEPRO_INSN_ADD,         true,  "lll"   },
2804   { "__insn_addb",            TILEPRO_INSN_ADDB,        true,  "lll"   },
2805   { "__insn_addbs_u",         TILEPRO_INSN_ADDBS_U,     false, "lll"   },
2806   { "__insn_addh",            TILEPRO_INSN_ADDH,        true,  "lll"   },
2807   { "__insn_addhs",           TILEPRO_INSN_ADDHS,       false, "lll"   },
2808   { "__insn_addi",            TILEPRO_INSN_ADD,         true,  "lll"   },
2809   { "__insn_addib",           TILEPRO_INSN_ADDIB,       true,  "lll"   },
2810   { "__insn_addih",           TILEPRO_INSN_ADDIH,       true,  "lll"   },
2811   { "__insn_addli",           TILEPRO_INSN_ADD,         true,  "lll"   },
2812   { "__insn_addlis",          TILEPRO_INSN_ADDLIS,      false, "lll"   },
2813   { "__insn_adds",            TILEPRO_INSN_ADDS,        false, "lll"   },
2814   { "__insn_adiffb_u",        TILEPRO_INSN_ADIFFB_U,    true,  "lll"   },
2815   { "__insn_adiffh",          TILEPRO_INSN_ADIFFH,      true,  "lll"   },
2816   { "__insn_and",             TILEPRO_INSN_AND,         true,  "lll"   },
2817   { "__insn_andi",            TILEPRO_INSN_AND,         true,  "lll"   },
2818   { "__insn_auli",            TILEPRO_INSN_AULI,        true,  "lll"   },
2819   { "__insn_avgb_u",          TILEPRO_INSN_AVGB_U,      true,  "lll"   },
2820   { "__insn_avgh",            TILEPRO_INSN_AVGH,        true,  "lll"   },
2821   { "__insn_bitx",            TILEPRO_INSN_BITX,        true,  "ll"    },
2822   { "__insn_bytex",           TILEPRO_INSN_BYTEX,       true,  "ll"    },
2823   { "__insn_clz",             TILEPRO_INSN_CLZ,         true,  "ll"    },
2824   { "__insn_crc32_32",        TILEPRO_INSN_CRC32_32,    true,  "lll"   },
2825   { "__insn_crc32_8",         TILEPRO_INSN_CRC32_8,     true,  "lll"   },
2826   { "__insn_ctz",             TILEPRO_INSN_CTZ,         true,  "ll"    },
2827   { "__insn_drain",           TILEPRO_INSN_DRAIN,       false, "v"     },
2828   { "__insn_dtlbpr",          TILEPRO_INSN_DTLBPR,      false, "vl"    },
2829   { "__insn_dword_align",     TILEPRO_INSN_DWORD_ALIGN, true,  "lllk"  },
2830   { "__insn_finv",            TILEPRO_INSN_FINV,        false, "vk"    },
2831   { "__insn_flush",           TILEPRO_INSN_FLUSH,       false, "vk"    },
2832   { "__insn_fnop",            TILEPRO_INSN_FNOP,        false, "v"     },
2833   { "__insn_icoh",            TILEPRO_INSN_ICOH,        false, "vk"    },
2834   { "__insn_ill",             TILEPRO_INSN_ILL,         false, "v"     },
2835   { "__insn_info",            TILEPRO_INSN_INFO,        false, "vl"    },
2836   { "__insn_infol",           TILEPRO_INSN_INFOL,       false, "vl"    },
2837   { "__insn_inthb",           TILEPRO_INSN_INTHB,       true,  "lll"   },
2838   { "__insn_inthh",           TILEPRO_INSN_INTHH,       true,  "lll"   },
2839   { "__insn_intlb",           TILEPRO_INSN_INTLB,       true,  "lll"   },
2840   { "__insn_intlh",           TILEPRO_INSN_INTLH,       true,  "lll"   },
2841   { "__insn_inv",             TILEPRO_INSN_INV,         false, "vp"    },
2842   { "__insn_lb",              TILEPRO_INSN_LB,          false, "lk"    },
2843   { "__insn_lb_u",            TILEPRO_INSN_LB_U,        false, "lk"    },
2844   { "__insn_lh",              TILEPRO_INSN_LH,          false, "lk"    },
2845   { "__insn_lh_u",            TILEPRO_INSN_LH_U,        false, "lk"    },
2846   { "__insn_lnk",             TILEPRO_INSN_LNK,         true,  "l"     },
2847   { "__insn_lw",              TILEPRO_INSN_LW,          false, "lk"    },
2848   { "__insn_lw_na",           TILEPRO_INSN_LW_NA,       false, "lk"    },
2849   { "__insn_lb_L2",           TILEPRO_INSN_LB_L2,       false, "lk"    },
2850   { "__insn_lb_u_L2",         TILEPRO_INSN_LB_U_L2,     false, "lk"    },
2851   { "__insn_lh_L2",           TILEPRO_INSN_LH_L2,       false, "lk"    },
2852   { "__insn_lh_u_L2",         TILEPRO_INSN_LH_U_L2,     false, "lk"    },
2853   { "__insn_lw_L2",           TILEPRO_INSN_LW_L2,       false, "lk"    },
2854   { "__insn_lw_na_L2",        TILEPRO_INSN_LW_NA_L2,    false, "lk"    },
2855   { "__insn_lb_miss",         TILEPRO_INSN_LB_MISS,     false, "lk"    },
2856   { "__insn_lb_u_miss",       TILEPRO_INSN_LB_U_MISS,   false, "lk"    },
2857   { "__insn_lh_miss",         TILEPRO_INSN_LH_MISS,     false, "lk"    },
2858   { "__insn_lh_u_miss",       TILEPRO_INSN_LH_U_MISS,   false, "lk"    },
2859   { "__insn_lw_miss",         TILEPRO_INSN_LW_MISS,     false, "lk"    },
2860   { "__insn_lw_na_miss",      TILEPRO_INSN_LW_NA_MISS,  false, "lk"    },
2861   { "__insn_maxb_u",          TILEPRO_INSN_MAXB_U,      true,  "lll"   },
2862   { "__insn_maxh",            TILEPRO_INSN_MAXH,        true,  "lll"   },
2863   { "__insn_maxib_u",         TILEPRO_INSN_MAXIB_U,     true,  "lll"   },
2864   { "__insn_maxih",           TILEPRO_INSN_MAXIH,       true,  "lll"   },
2865   { "__insn_mf",              TILEPRO_INSN_MF,          false, "v"     },
2866   { "__insn_mfspr",           TILEPRO_INSN_MFSPR,       false, "ll"    },
2867   { "__insn_minb_u",          TILEPRO_INSN_MINB_U,      true,  "lll"   },
2868   { "__insn_minh",            TILEPRO_INSN_MINH,        true,  "lll"   },
2869   { "__insn_minib_u",         TILEPRO_INSN_MINIB_U,     true,  "lll"   },
2870   { "__insn_minih",           TILEPRO_INSN_MINIH,       true,  "lll"   },
2871   { "__insn_mm",              TILEPRO_INSN_MM,          true,  "lllll" },
2872   { "__insn_mnz",             TILEPRO_INSN_MNZ,         true,  "lll"   },
2873   { "__insn_mnzb",            TILEPRO_INSN_MNZB,        true,  "lll"   },
2874   { "__insn_mnzh",            TILEPRO_INSN_MNZH,        true,  "lll"   },
2875   { "__insn_move",            TILEPRO_INSN_MOVE,        true,  "ll"    },
2876   { "__insn_movei",           TILEPRO_INSN_MOVE,        true,  "ll"    },
2877   { "__insn_moveli",          TILEPRO_INSN_MOVE,        true,  "ll"    },
2878   { "__insn_movelis",         TILEPRO_INSN_MOVELIS,     false, "ll"    },
2879   { "__insn_mtspr",           TILEPRO_INSN_MTSPR,       false, "vll"   },
2880   { "__insn_mulhh_ss",        TILEPRO_INSN_MULHH_SS,    true,  "lll"   },
2881   { "__insn_mulhh_su",        TILEPRO_INSN_MULHH_SU,    true,  "lll"   },
2882   { "__insn_mulhh_uu",        TILEPRO_INSN_MULHH_UU,    true,  "lll"   },
2883   { "__insn_mulhha_ss",       TILEPRO_INSN_MULHHA_SS,   true,  "llll"  },
2884   { "__insn_mulhha_su",       TILEPRO_INSN_MULHHA_SU,   true,  "llll"  },
2885   { "__insn_mulhha_uu",       TILEPRO_INSN_MULHHA_UU,   true,  "llll"  },
2886   { "__insn_mulhhsa_uu",      TILEPRO_INSN_MULHHSA_UU,  true,  "llll"  },
2887   { "__insn_mulhl_ss",        TILEPRO_INSN_MULHL_SS,    true,  "lll"   },
2888   { "__insn_mulhl_su",        TILEPRO_INSN_MULHL_SU,    true,  "lll"   },
2889   { "__insn_mulhl_us",        TILEPRO_INSN_MULHL_US,    true,  "lll"   },
2890   { "__insn_mulhl_uu",        TILEPRO_INSN_MULHL_UU,    true,  "lll"   },
2891   { "__insn_mulhla_ss",       TILEPRO_INSN_MULHLA_SS,   true,  "llll"  },
2892   { "__insn_mulhla_su",       TILEPRO_INSN_MULHLA_SU,   true,  "llll"  },
2893   { "__insn_mulhla_us",       TILEPRO_INSN_MULHLA_US,   true,  "llll"  },
2894   { "__insn_mulhla_uu",       TILEPRO_INSN_MULHLA_UU,   true,  "llll"  },
2895   { "__insn_mulhlsa_uu",      TILEPRO_INSN_MULHLSA_UU,  true,  "llll"  },
2896   { "__insn_mulll_ss",        TILEPRO_INSN_MULLL_SS,    true,  "lll"   },
2897   { "__insn_mulll_su",        TILEPRO_INSN_MULLL_SU,    true,  "lll"   },
2898   { "__insn_mulll_uu",        TILEPRO_INSN_MULLL_UU,    true,  "lll"   },
2899   { "__insn_mullla_ss",       TILEPRO_INSN_MULLLA_SS,   true,  "llll"  },
2900   { "__insn_mullla_su",       TILEPRO_INSN_MULLLA_SU,   true,  "llll"  },
2901   { "__insn_mullla_uu",       TILEPRO_INSN_MULLLA_UU,   true,  "llll"  },
2902   { "__insn_mulllsa_uu",      TILEPRO_INSN_MULLLSA_UU,  true,  "llll"  },
2903   { "__insn_mvnz",            TILEPRO_INSN_MVNZ,        true,  "llll"  },
2904   { "__insn_mvz",             TILEPRO_INSN_MVZ,         true,  "llll"  },
2905   { "__insn_mz",              TILEPRO_INSN_MZ,          true,  "lll"   },
2906   { "__insn_mzb",             TILEPRO_INSN_MZB,         true,  "lll"   },
2907   { "__insn_mzh",             TILEPRO_INSN_MZH,         true,  "lll"   },
2908   { "__insn_nap",             TILEPRO_INSN_NAP,         false, "v"     },
2909   { "__insn_nop",             TILEPRO_INSN_NOP,         true,  "v"     },
2910   { "__insn_nor",             TILEPRO_INSN_NOR,         true,  "lll"   },
2911   { "__insn_or",              TILEPRO_INSN_OR,          true,  "lll"   },
2912   { "__insn_ori",             TILEPRO_INSN_OR,          true,  "lll"   },
2913   { "__insn_packbs_u",        TILEPRO_INSN_PACKBS_U,    false, "lll"   },
2914   { "__insn_packhb",          TILEPRO_INSN_PACKHB,      true,  "lll"   },
2915   { "__insn_packhs",          TILEPRO_INSN_PACKHS,      false, "lll"   },
2916   { "__insn_packlb",          TILEPRO_INSN_PACKLB,      true,  "lll"   },
2917   { "__insn_pcnt",            TILEPRO_INSN_PCNT,        true,  "ll"    },
2918   { "__insn_prefetch",        TILEPRO_INSN_PREFETCH,    false, "vk"    },
2919   { "__insn_prefetch_L1",     TILEPRO_INSN_PREFETCH_L1, false, "vk"    },
2920   { "__insn_rl",              TILEPRO_INSN_RL,          true,  "lll"   },
2921   { "__insn_rli",             TILEPRO_INSN_RL,          true,  "lll"   },
2922   { "__insn_s1a",             TILEPRO_INSN_S1A,         true,  "lll"   },
2923   { "__insn_s2a",             TILEPRO_INSN_S2A,         true,  "lll"   },
2924   { "__insn_s3a",             TILEPRO_INSN_S3A,         true,  "lll"   },
2925   { "__insn_sadab_u",         TILEPRO_INSN_SADAB_U,     true,  "llll"  },
2926   { "__insn_sadah",           TILEPRO_INSN_SADAH,       true,  "llll"  },
2927   { "__insn_sadah_u",         TILEPRO_INSN_SADAH_U,     true,  "llll"  },
2928   { "__insn_sadb_u",          TILEPRO_INSN_SADB_U,      true,  "lll"   },
2929   { "__insn_sadh",            TILEPRO_INSN_SADH,        true,  "lll"   },
2930   { "__insn_sadh_u",          TILEPRO_INSN_SADH_U,      true,  "lll"   },
2931   { "__insn_sb",              TILEPRO_INSN_SB,          false, "vpl"   },
2932   { "__insn_seq",             TILEPRO_INSN_SEQ,         true,  "lll"   },
2933   { "__insn_seqb",            TILEPRO_INSN_SEQB,        true,  "lll"   },
2934   { "__insn_seqh",            TILEPRO_INSN_SEQH,        true,  "lll"   },
2935   { "__insn_seqi",            TILEPRO_INSN_SEQ,         true,  "lll"   },
2936   { "__insn_seqib",           TILEPRO_INSN_SEQIB,       true,  "lll"   },
2937   { "__insn_seqih",           TILEPRO_INSN_SEQIH,       true,  "lll"   },
2938   { "__insn_sh",              TILEPRO_INSN_SH,          false, "vpl"   },
2939   { "__insn_shl",             TILEPRO_INSN_SHL,         true,  "lll"   },
2940   { "__insn_shlb",            TILEPRO_INSN_SHLB,        true,  "lll"   },
2941   { "__insn_shlh",            TILEPRO_INSN_SHLH,        true,  "lll"   },
2942   { "__insn_shli",            TILEPRO_INSN_SHL,         true,  "lll"   },
2943   { "__insn_shlib",           TILEPRO_INSN_SHLIB,       true,  "lll"   },
2944   { "__insn_shlih",           TILEPRO_INSN_SHLIH,       true,  "lll"   },
2945   { "__insn_shr",             TILEPRO_INSN_SHR,         true,  "lll"   },
2946   { "__insn_shrb",            TILEPRO_INSN_SHRB,        true,  "lll"   },
2947   { "__insn_shrh",            TILEPRO_INSN_SHRH,        true,  "lll"   },
2948   { "__insn_shri",            TILEPRO_INSN_SHR,         true,  "lll"   },
2949   { "__insn_shrib",           TILEPRO_INSN_SHRIB,       true,  "lll"   },
2950   { "__insn_shrih",           TILEPRO_INSN_SHRIH,       true,  "lll"   },
2951   { "__insn_slt",             TILEPRO_INSN_SLT,         true,  "lll"   },
2952   { "__insn_slt_u",           TILEPRO_INSN_SLT_U,       true,  "lll"   },
2953   { "__insn_sltb",            TILEPRO_INSN_SLTB,        true,  "lll"   },
2954   { "__insn_sltb_u",          TILEPRO_INSN_SLTB_U,      true,  "lll"   },
2955   { "__insn_slte",            TILEPRO_INSN_SLTE,        true,  "lll"   },
2956   { "__insn_slte_u",          TILEPRO_INSN_SLTE_U,      true,  "lll"   },
2957   { "__insn_slteb",           TILEPRO_INSN_SLTEB,       true,  "lll"   },
2958   { "__insn_slteb_u",         TILEPRO_INSN_SLTEB_U,     true,  "lll"   },
2959   { "__insn_slteh",           TILEPRO_INSN_SLTEH,       true,  "lll"   },
2960   { "__insn_slteh_u",         TILEPRO_INSN_SLTEH_U,     true,  "lll"   },
2961   { "__insn_slth",            TILEPRO_INSN_SLTH,        true,  "lll"   },
2962   { "__insn_slth_u",          TILEPRO_INSN_SLTH_U,      true,  "lll"   },
2963   { "__insn_slti",            TILEPRO_INSN_SLT,         true,  "lll"   },
2964   { "__insn_slti_u",          TILEPRO_INSN_SLT_U,       true,  "lll"   },
2965   { "__insn_sltib",           TILEPRO_INSN_SLTIB,       true,  "lll"   },
2966   { "__insn_sltib_u",         TILEPRO_INSN_SLTIB_U,     true,  "lll"   },
2967   { "__insn_sltih",           TILEPRO_INSN_SLTIH,       true,  "lll"   },
2968   { "__insn_sltih_u",         TILEPRO_INSN_SLTIH_U,     true,  "lll"   },
2969   { "__insn_sne",             TILEPRO_INSN_SNE,         true,  "lll"   },
2970   { "__insn_sneb",            TILEPRO_INSN_SNEB,        true,  "lll"   },
2971   { "__insn_sneh",            TILEPRO_INSN_SNEH,        true,  "lll"   },
2972   { "__insn_sra",             TILEPRO_INSN_SRA,         true,  "lll"   },
2973   { "__insn_srab",            TILEPRO_INSN_SRAB,        true,  "lll"   },
2974   { "__insn_srah",            TILEPRO_INSN_SRAH,        true,  "lll"   },
2975   { "__insn_srai",            TILEPRO_INSN_SRA,         true,  "lll"   },
2976   { "__insn_sraib",           TILEPRO_INSN_SRAIB,       true,  "lll"   },
2977   { "__insn_sraih",           TILEPRO_INSN_SRAIH,       true,  "lll"   },
2978   { "__insn_sub",             TILEPRO_INSN_SUB,         true,  "lll"   },
2979   { "__insn_subb",            TILEPRO_INSN_SUBB,        true,  "lll"   },
2980   { "__insn_subbs_u",         TILEPRO_INSN_SUBBS_U,     false, "lll"   },
2981   { "__insn_subh",            TILEPRO_INSN_SUBH,        true,  "lll"   },
2982   { "__insn_subhs",           TILEPRO_INSN_SUBHS,       false, "lll"   },
2983   { "__insn_subs",            TILEPRO_INSN_SUBS,        false, "lll"   },
2984   { "__insn_sw",              TILEPRO_INSN_SW,          false, "vpl"   },
2985   { "__insn_tblidxb0",        TILEPRO_INSN_TBLIDXB0,    true,  "lll"   },
2986   { "__insn_tblidxb1",        TILEPRO_INSN_TBLIDXB1,    true,  "lll"   },
2987   { "__insn_tblidxb2",        TILEPRO_INSN_TBLIDXB2,    true,  "lll"   },
2988   { "__insn_tblidxb3",        TILEPRO_INSN_TBLIDXB3,    true,  "lll"   },
2989   { "__insn_tns",             TILEPRO_INSN_TNS,         false, "lp"    },
2990   { "__insn_wh64",            TILEPRO_INSN_WH64,        false, "vp"    },
2991   { "__insn_xor",             TILEPRO_INSN_XOR,         true,  "lll"   },
2992   { "__insn_xori",            TILEPRO_INSN_XOR,         true,  "lll"   },
2993   { "__tile_network_barrier", TILEPRO_NETWORK_BARRIER,  false, "v"     },
2994   { "__tile_idn0_receive",    TILEPRO_IDN0_RECEIVE,     false, "l"     },
2995   { "__tile_idn1_receive",    TILEPRO_IDN1_RECEIVE,     false, "l"     },
2996   { "__tile_idn_send",        TILEPRO_IDN_SEND,         false, "vl"    },
2997   { "__tile_sn_receive",      TILEPRO_SN_RECEIVE,       false, "l"     },
2998   { "__tile_sn_send",         TILEPRO_SN_SEND,          false, "vl"    },
2999   { "__tile_udn0_receive",    TILEPRO_UDN0_RECEIVE,     false, "l"     },
3000   { "__tile_udn1_receive",    TILEPRO_UDN1_RECEIVE,     false, "l"     },
3001   { "__tile_udn2_receive",    TILEPRO_UDN2_RECEIVE,     false, "l"     },
3002   { "__tile_udn3_receive",    TILEPRO_UDN3_RECEIVE,     false, "l"     },
3003   { "__tile_udn_send",        TILEPRO_UDN_SEND,         false, "vl"    },
3004 };
3005 
3006 
3007 /* Convert a character in a builtin type string to a tree type.  */
3008 static tree
3009 char_to_type (char c)
3010 {
3011   static tree volatile_ptr_type_node = NULL;
3012   static tree volatile_const_ptr_type_node = NULL;
3013 
3014   if (volatile_ptr_type_node == NULL)
3015     {
3016       volatile_ptr_type_node =
3017 	build_pointer_type (build_qualified_type (void_type_node,
3018 						  TYPE_QUAL_VOLATILE));
3019       volatile_const_ptr_type_node =
3020 	build_pointer_type (build_qualified_type (void_type_node,
3021 						  TYPE_QUAL_CONST
3022 						  | TYPE_QUAL_VOLATILE));
3023     }
3024 
3025   switch (c)
3026     {
3027     case 'v':
3028       return void_type_node;
3029     case 'l':
3030       return long_unsigned_type_node;
3031     case 'p':
3032       return volatile_ptr_type_node;
3033     case 'k':
3034       return volatile_const_ptr_type_node;
3035     default:
3036       gcc_unreachable ();
3037     }
3038 }
3039 
3040 
3041 /* Implement TARGET_INIT_BUILTINS.  */
3042 static void
3043 tilepro_init_builtins (void)
3044 {
3045   size_t i;
3046 
3047   for (i = 0; i < ARRAY_SIZE (tilepro_builtins); i++)
3048     {
3049       const struct tilepro_builtin_def *p = &tilepro_builtins[i];
3050       tree ftype, ret_type, arg_type_list = void_list_node;
3051       tree decl;
3052       int j;
3053 
3054       for (j = strlen (p->type) - 1; j > 0; j--)
3055 	{
3056 	  arg_type_list =
3057 	    tree_cons (NULL_TREE, char_to_type (p->type[j]), arg_type_list);
3058 	}
3059 
3060       ret_type = char_to_type (p->type[0]);
3061 
3062       ftype = build_function_type (ret_type, arg_type_list);
3063 
3064       decl = add_builtin_function (p->name, ftype, p->code, BUILT_IN_MD,
3065 				   NULL, NULL);
3066 
3067       if (p->is_const)
3068 	TREE_READONLY (decl) = 1;
3069       TREE_NOTHROW (decl) = 1;
3070 
3071       if (tilepro_builtin_info[p->code].fndecl == NULL)
3072 	tilepro_builtin_info[p->code].fndecl = decl;
3073     }
3074 }
3075 
3076 
3077 /* Implement TARGET_EXPAND_BUILTIN.  */
3078 static rtx
3079 tilepro_expand_builtin (tree exp,
3080 			rtx target,
3081 			rtx subtarget ATTRIBUTE_UNUSED,
3082 			enum machine_mode mode ATTRIBUTE_UNUSED,
3083 			int ignore ATTRIBUTE_UNUSED)
3084 {
3085 #define MAX_BUILTIN_ARGS 4
3086 
3087   tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
3088   unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
3089   tree arg;
3090   call_expr_arg_iterator iter;
3091   enum insn_code icode;
3092   rtx op[MAX_BUILTIN_ARGS + 1], pat;
3093   int opnum;
3094   bool nonvoid;
3095   insn_gen_fn fn;
3096 
3097   if (fcode >= TILEPRO_BUILTIN_max)
3098     internal_error ("bad builtin fcode");
3099   icode = tilepro_builtin_info[fcode].icode;
3100   if (icode == 0)
3101     internal_error ("bad builtin icode");
3102 
3103   nonvoid = TREE_TYPE (TREE_TYPE (fndecl)) != void_type_node;
3104 
3105   opnum = nonvoid;
3106   FOR_EACH_CALL_EXPR_ARG (arg, iter, exp)
3107   {
3108     const struct insn_operand_data *insn_op;
3109 
3110     if (arg == error_mark_node)
3111       return NULL_RTX;
3112     if (opnum > MAX_BUILTIN_ARGS)
3113       return NULL_RTX;
3114 
3115     insn_op = &insn_data[icode].operand[opnum];
3116 
3117     op[opnum] = expand_expr (arg, NULL_RTX, insn_op->mode, EXPAND_NORMAL);
3118 
3119     if (!(*insn_op->predicate) (op[opnum], insn_op->mode))
3120       op[opnum] = copy_to_mode_reg (insn_op->mode, op[opnum]);
3121 
3122     if (!(*insn_op->predicate) (op[opnum], insn_op->mode))
3123       {
3124 	/* We still failed to meet the predicate even after moving
3125 	   into a register. Assume we needed an immediate.  */
3126 	error_at (EXPR_LOCATION (exp),
3127 		  "operand must be an immediate of the right size");
3128 	return const0_rtx;
3129       }
3130 
3131     opnum++;
3132   }
3133 
3134   if (nonvoid)
3135     {
3136       enum machine_mode tmode = insn_data[icode].operand[0].mode;
3137       if (!target
3138 	  || GET_MODE (target) != tmode
3139 	  || !(*insn_data[icode].operand[0].predicate) (target, tmode))
3140 	target = gen_reg_rtx (tmode);
3141       op[0] = target;
3142     }
3143 
3144   fn = GEN_FCN (icode);
3145   switch (opnum)
3146     {
3147     case 0:
3148       pat = fn (NULL_RTX);
3149       break;
3150     case 1:
3151       pat = fn (op[0]);
3152       break;
3153     case 2:
3154       pat = fn (op[0], op[1]);
3155       break;
3156     case 3:
3157       pat = fn (op[0], op[1], op[2]);
3158       break;
3159     case 4:
3160       pat = fn (op[0], op[1], op[2], op[3]);
3161       break;
3162     case 5:
3163       pat = fn (op[0], op[1], op[2], op[3], op[4]);
3164       break;
3165     default:
3166       gcc_unreachable ();
3167     }
3168   if (!pat)
3169     return NULL_RTX;
3170 
3171   /* If we are generating a prefetch, tell the scheduler not to move
3172      it around.  */
3173   if (GET_CODE (pat) == PREFETCH)
3174     PREFETCH_SCHEDULE_BARRIER_P (pat) = true;
3175 
3176   emit_insn (pat);
3177 
3178   if (nonvoid)
3179     return target;
3180   else
3181     return const0_rtx;
3182 }
3183 
3184 
3185 /* Implement TARGET_BUILTIN_DECL.  */
3186 static tree
3187 tilepro_builtin_decl (unsigned code, bool initialize_p ATTRIBUTE_UNUSED)
3188 {
3189   if (code >= TILEPRO_BUILTIN_max)
3190     return error_mark_node;
3191 
3192   return tilepro_builtin_info[code].fndecl;
3193 }
3194 
3195 
3196 
3197 /* Stack frames  */
3198 
3199 /* Return whether REGNO needs to be saved in the stack frame.  */
3200 static bool
3201 need_to_save_reg (unsigned int regno)
3202 {
3203   if (!fixed_regs[regno] && !call_used_regs[regno]
3204       && df_regs_ever_live_p (regno))
3205     return true;
3206 
3207   if (flag_pic
3208       && (regno == PIC_OFFSET_TABLE_REGNUM
3209 	  || regno == TILEPRO_PIC_TEXT_LABEL_REGNUM)
3210       && (crtl->uses_pic_offset_table || crtl->saves_all_registers))
3211     return true;
3212 
3213   if (crtl->calls_eh_return)
3214     {
3215       unsigned i;
3216       for (i = 0; EH_RETURN_DATA_REGNO (i) != INVALID_REGNUM; i++)
3217 	{
3218 	  if (regno == EH_RETURN_DATA_REGNO (i))
3219 	    return true;
3220 	}
3221     }
3222 
3223   return false;
3224 }
3225 
3226 
3227 /* Return the size of the register savev area.  This function is only
3228    correct starting with local register allocation */
3229 static int
3230 tilepro_saved_regs_size (void)
3231 {
3232   int reg_save_size = 0;
3233   int regno;
3234   int offset_to_frame;
3235   int align_mask;
3236 
3237   for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
3238     if (need_to_save_reg (regno))
3239       reg_save_size += UNITS_PER_WORD;
3240 
3241   /* Pad out the register save area if necessary to make
3242      frame_pointer_rtx be as aligned as the stack pointer.  */
3243   offset_to_frame = crtl->args.pretend_args_size + reg_save_size;
3244   align_mask = (STACK_BOUNDARY / BITS_PER_UNIT) - 1;
3245   reg_save_size += (-offset_to_frame) & align_mask;
3246 
3247   return reg_save_size;
3248 }
3249 
3250 
3251 /* Round up frame size SIZE.  */
3252 static int
3253 round_frame_size (int size)
3254 {
3255   return ((size + STACK_BOUNDARY / BITS_PER_UNIT - 1)
3256 	  & -STACK_BOUNDARY / BITS_PER_UNIT);
3257 }
3258 
3259 
3260 /* Emit a store in the stack frame to save REGNO at address ADDR, and
3261    emit the corresponding REG_CFA_OFFSET note described by CFA and
3262    CFA_OFFSET.  Return the emitted insn.  */
3263 static rtx
3264 frame_emit_store (int regno, int regno_note, rtx addr, rtx cfa,
3265 		  int cfa_offset)
3266 {
3267   rtx reg = gen_rtx_REG (Pmode, regno);
3268   rtx mem = gen_frame_mem (Pmode, addr);
3269   rtx mov = gen_movsi (mem, reg);
3270 
3271   /* Describe what just happened in a way that dwarf understands.  We
3272      use temporary registers to hold the address to make scheduling
3273      easier, and use the REG_CFA_OFFSET to describe the address as an
3274      offset from the CFA.  */
3275   rtx reg_note = gen_rtx_REG (Pmode, regno_note);
3276   rtx cfa_relative_addr = gen_rtx_PLUS (Pmode, cfa, gen_int_si (cfa_offset));
3277   rtx cfa_relative_mem = gen_frame_mem (Pmode, cfa_relative_addr);
3278   rtx real = gen_rtx_SET (VOIDmode, cfa_relative_mem, reg_note);
3279   add_reg_note (mov, REG_CFA_OFFSET, real);
3280 
3281   return emit_insn (mov);
3282 }
3283 
3284 
3285 /* Emit a load in the stack frame to load REGNO from address ADDR.
3286    Add a REG_CFA_RESTORE note to CFA_RESTORES if CFA_RESTORES is
3287    non-null.  Return the emitted insn.  */
3288 static rtx
3289 frame_emit_load (int regno, rtx addr, rtx *cfa_restores)
3290 {
3291   rtx reg = gen_rtx_REG (Pmode, regno);
3292   rtx mem = gen_frame_mem (Pmode, addr);
3293   if (cfa_restores)
3294     *cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg, *cfa_restores);
3295   return emit_insn (gen_movsi (reg, mem));
3296 }
3297 
3298 
3299 /* Helper function to set RTX_FRAME_RELATED_P on instructions,
3300    including sequences.  */
3301 static rtx
3302 set_frame_related_p (void)
3303 {
3304   rtx seq = get_insns ();
3305   rtx insn;
3306 
3307   end_sequence ();
3308 
3309   if (!seq)
3310     return NULL_RTX;
3311 
3312   if (INSN_P (seq))
3313     {
3314       insn = seq;
3315       while (insn != NULL_RTX)
3316 	{
3317 	  RTX_FRAME_RELATED_P (insn) = 1;
3318 	  insn = NEXT_INSN (insn);
3319 	}
3320       seq = emit_insn (seq);
3321     }
3322   else
3323     {
3324       seq = emit_insn (seq);
3325       RTX_FRAME_RELATED_P (seq) = 1;
3326     }
3327   return seq;
3328 }
3329 
3330 
3331 #define FRP(exp)  (start_sequence (), exp, set_frame_related_p ())
3332 
3333 /* This emits code for 'sp += offset'.
3334 
3335    The ABI only allows us to modify 'sp' in a single 'addi' or
3336    'addli', so the backtracer understands it. Larger amounts cannot
3337    use those instructions, so are added by placing the offset into a
3338    large register and using 'add'.
3339 
3340    This happens after reload, so we need to expand it ourselves.  */
3341 static rtx
3342 emit_sp_adjust (int offset, int *next_scratch_regno, bool frame_related,
3343 		rtx reg_notes)
3344 {
3345   rtx to_add;
3346   rtx imm_rtx = gen_int_si (offset);
3347 
3348   rtx insn;
3349   if (satisfies_constraint_J (imm_rtx))
3350     {
3351       /* We can add this using a single addi or addli.  */
3352       to_add = imm_rtx;
3353     }
3354   else
3355     {
3356       rtx tmp = gen_rtx_REG (Pmode, (*next_scratch_regno)--);
3357       tilepro_expand_set_const32 (tmp, imm_rtx);
3358       to_add = tmp;
3359     }
3360 
3361   /* Actually adjust the stack pointer.  */
3362   insn = emit_insn (gen_sp_adjust (stack_pointer_rtx, stack_pointer_rtx,
3363 				   to_add));
3364   REG_NOTES (insn) = reg_notes;
3365 
3366   /* Describe what just happened in a way that dwarf understands.  */
3367   if (frame_related)
3368     {
3369       rtx real = gen_rtx_SET (VOIDmode, stack_pointer_rtx,
3370 			      gen_rtx_PLUS (Pmode, stack_pointer_rtx,
3371 					    imm_rtx));
3372       RTX_FRAME_RELATED_P (insn) = 1;
3373       add_reg_note (insn, REG_CFA_ADJUST_CFA, real);
3374     }
3375 
3376   return insn;
3377 }
3378 
3379 
3380 /* Return whether the current function is leaf.  This takes into
3381    account whether the function calls tls_get_addr.  */
3382 static bool
3383 tilepro_current_function_is_leaf (void)
3384 {
3385   return crtl->is_leaf && !cfun->machine->calls_tls_get_addr;
3386 }
3387 
3388 
3389 /* Return the frame size.  */
3390 static int
3391 compute_total_frame_size (void)
3392 {
3393   int total_size = (get_frame_size () + tilepro_saved_regs_size ()
3394 		    + crtl->outgoing_args_size
3395 		    + crtl->args.pretend_args_size);
3396 
3397   if (!tilepro_current_function_is_leaf () || cfun->calls_alloca)
3398     {
3399       /* Make room for save area in callee.  */
3400       total_size += STACK_POINTER_OFFSET;
3401     }
3402 
3403   return round_frame_size (total_size);
3404 }
3405 
3406 
3407 /* Return nonzero if this function is known to have a null epilogue.
3408    This allows the optimizer to omit jumps to jumps if no stack was
3409    created.  */
3410 bool
3411 tilepro_can_use_return_insn_p (void)
3412 {
3413   return (reload_completed
3414 	  && cfun->static_chain_decl == 0
3415 	  && compute_total_frame_size () == 0
3416 	  && tilepro_current_function_is_leaf ()
3417 	  && !crtl->profile && !df_regs_ever_live_p (TILEPRO_LINK_REGNUM));
3418 }
3419 
3420 
3421 /* Returns an rtx for a stack slot at 'FP + offset_from_fp'.  If there
3422    is a frame pointer, it computes the value relative to
3423    that. Otherwise it uses the stack pointer.  */
3424 static rtx
3425 compute_frame_addr (int offset_from_fp, int *next_scratch_regno)
3426 {
3427   rtx base_reg_rtx, tmp_reg_rtx, offset_rtx;
3428   int offset_from_base;
3429 
3430   if (frame_pointer_needed)
3431     {
3432       base_reg_rtx = hard_frame_pointer_rtx;
3433       offset_from_base = offset_from_fp;
3434     }
3435   else
3436     {
3437       int offset_from_sp = compute_total_frame_size () + offset_from_fp;
3438       base_reg_rtx = stack_pointer_rtx;
3439       offset_from_base = offset_from_sp;
3440     }
3441 
3442   if (offset_from_base == 0)
3443     return base_reg_rtx;
3444 
3445   /* Compute the new value of the stack pointer.  */
3446   tmp_reg_rtx = gen_rtx_REG (Pmode, (*next_scratch_regno)--);
3447   offset_rtx = gen_int_si (offset_from_base);
3448 
3449   if (!tilepro_expand_addsi (tmp_reg_rtx, base_reg_rtx, offset_rtx))
3450     {
3451       emit_insn (gen_rtx_SET (VOIDmode, tmp_reg_rtx,
3452 			      gen_rtx_PLUS (Pmode, base_reg_rtx,
3453 					    offset_rtx)));
3454     }
3455 
3456   return tmp_reg_rtx;
3457 }
3458 
3459 
3460 /* The stack frame looks like this:
3461          +-------------+
3462          |    ...      |
3463          |  incoming   |
3464          | stack args  |
3465    AP -> +-------------+
3466          | caller's HFP|
3467          +-------------+
3468          | lr save     |
3469   HFP -> +-------------+
3470          |  var args   |
3471          |  reg save   | crtl->args.pretend_args_size bytes
3472          +-------------+
3473          |    ...      |
3474          | saved regs  | tilepro_saved_regs_size() bytes
3475    FP -> +-------------+
3476          |    ...      |
3477          |   vars      | get_frame_size() bytes
3478          +-------------+
3479          |    ...      |
3480          |  outgoing   |
3481          |  stack args | crtl->outgoing_args_size bytes
3482          +-------------+
3483          | HFP         | 4 bytes (only here if nonleaf / alloca)
3484          +-------------+
3485          | callee lr   | 4 bytes (only here if nonleaf / alloca)
3486          | save        |
3487    SP -> +-------------+
3488 
3489   HFP == incoming SP.
3490 
3491   For functions with a frame larger than 32767 bytes, or which use
3492   alloca (), r52 is used as a frame pointer.  Otherwise there is no
3493   frame pointer.
3494 
3495   FP is saved at SP+4 before calling a subroutine so the
3496   callee can chain.  */
3497 void
3498 tilepro_expand_prologue (void)
3499 {
3500 #define ROUND_ROBIN_SIZE 4
3501   /* We round-robin through four scratch registers to hold temporary
3502      addresses for saving registers, to make instruction scheduling
3503      easier.  */
3504   rtx reg_save_addr[ROUND_ROBIN_SIZE] = {
3505     NULL_RTX, NULL_RTX, NULL_RTX, NULL_RTX
3506   };
3507   rtx insn, cfa;
3508   unsigned int which_scratch;
3509   int offset, start_offset, regno;
3510 
3511   /* A register that holds a copy of the incoming fp.  */
3512   int fp_copy_regno = -1;
3513 
3514   /* A register that holds a copy of the incoming sp.  */
3515   int sp_copy_regno = -1;
3516 
3517   /* Next scratch register number to hand out (postdecrementing).  */
3518   int next_scratch_regno = 29;
3519 
3520   int total_size = compute_total_frame_size ();
3521 
3522   if (flag_stack_usage_info)
3523     current_function_static_stack_size = total_size;
3524 
3525   /* Save lr first in its special location because code after this
3526      might use the link register as a scratch register.  */
3527   if (df_regs_ever_live_p (TILEPRO_LINK_REGNUM) || crtl->calls_eh_return)
3528     FRP (frame_emit_store (TILEPRO_LINK_REGNUM, TILEPRO_LINK_REGNUM,
3529 			   stack_pointer_rtx, stack_pointer_rtx, 0));
3530 
3531   if (total_size == 0)
3532     {
3533       /* Load the PIC register if needed.  */
3534       if (flag_pic && crtl->uses_pic_offset_table)
3535 	load_pic_register (false);
3536 
3537       return;
3538     }
3539 
3540   cfa = stack_pointer_rtx;
3541 
3542   if (frame_pointer_needed)
3543     {
3544       fp_copy_regno = next_scratch_regno--;
3545 
3546       /* Copy the old frame pointer aside so we can save it later.  */
3547       insn = FRP (emit_move_insn (gen_rtx_REG (word_mode, fp_copy_regno),
3548 				  hard_frame_pointer_rtx));
3549       add_reg_note (insn, REG_CFA_REGISTER, NULL_RTX);
3550 
3551       /* Set up the frame pointer.  */
3552       insn = FRP (emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx));
3553       add_reg_note (insn, REG_CFA_DEF_CFA, hard_frame_pointer_rtx);
3554       cfa = hard_frame_pointer_rtx;
3555       REGNO_POINTER_ALIGN (HARD_FRAME_POINTER_REGNUM) = STACK_BOUNDARY;
3556 
3557       /* fp holds a copy of the incoming sp, in case we need to store
3558          it.  */
3559       sp_copy_regno = HARD_FRAME_POINTER_REGNUM;
3560     }
3561   else if (!tilepro_current_function_is_leaf ())
3562     {
3563       /* Copy the old stack pointer aside so we can save it later.  */
3564       sp_copy_regno = next_scratch_regno--;
3565       emit_move_insn (gen_rtx_REG (Pmode, sp_copy_regno),
3566 		      stack_pointer_rtx);
3567     }
3568 
3569   if (tilepro_current_function_is_leaf ())
3570     {
3571       /* No need to store chain pointer to caller's frame.  */
3572       emit_sp_adjust (-total_size, &next_scratch_regno,
3573 		      !frame_pointer_needed, NULL_RTX);
3574     }
3575   else
3576     {
3577       /* Save the frame pointer (incoming sp value) to support
3578          backtracing.  First we need to create an rtx with the store
3579          address.  */
3580       rtx chain_addr = gen_rtx_REG (Pmode, next_scratch_regno--);
3581       rtx size_rtx = gen_int_si (-(total_size - UNITS_PER_WORD));
3582 
3583       if (add_operand (size_rtx, Pmode))
3584 	{
3585 	  /* Expose more parallelism by computing this value from the
3586 	     original stack pointer, not the one after we have pushed
3587 	     the frame.  */
3588 	  rtx p = gen_rtx_PLUS (Pmode, stack_pointer_rtx, size_rtx);
3589 	  emit_insn (gen_rtx_SET (VOIDmode, chain_addr, p));
3590 	  emit_sp_adjust (-total_size, &next_scratch_regno,
3591 			  !frame_pointer_needed, NULL_RTX);
3592 	}
3593       else
3594 	{
3595 	  /* The stack frame is large, so just store the incoming sp
3596 	     value at *(new_sp + UNITS_PER_WORD).  */
3597 	  rtx p;
3598 	  emit_sp_adjust (-total_size, &next_scratch_regno,
3599 			  !frame_pointer_needed, NULL_RTX);
3600 	  p = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
3601 			    GEN_INT (UNITS_PER_WORD));
3602 	  emit_insn (gen_rtx_SET (VOIDmode, chain_addr, p));
3603 	}
3604 
3605       /* Save our frame pointer for backtrace chaining.  */
3606       emit_insn (gen_movsi (gen_frame_mem (SImode, chain_addr),
3607 			    gen_rtx_REG (SImode, sp_copy_regno)));
3608     }
3609 
3610   /* Compute where to start storing registers we need to save.  */
3611   start_offset = -crtl->args.pretend_args_size - UNITS_PER_WORD;
3612   offset = start_offset;
3613 
3614   /* Store all registers that need saving.  */
3615   which_scratch = 0;
3616   for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; regno--)
3617     if (need_to_save_reg (regno))
3618       {
3619 	rtx r = reg_save_addr[which_scratch];
3620 	int from_regno;
3621 	int cfa_offset = frame_pointer_needed ? offset : total_size + offset;
3622 
3623 	if (r == NULL_RTX)
3624 	  {
3625 	    rtx p = compute_frame_addr (offset, &next_scratch_regno);
3626 	    r = gen_rtx_REG (word_mode, next_scratch_regno--);
3627 	    reg_save_addr[which_scratch] = r;
3628 
3629 	    emit_insn (gen_rtx_SET (VOIDmode, r, p));
3630 	  }
3631 	else
3632 	  {
3633 	    /* Advance to the next stack slot to store this register.  */
3634 	    int stride = ROUND_ROBIN_SIZE * -UNITS_PER_WORD;
3635 	    rtx p = gen_rtx_PLUS (Pmode, r, GEN_INT (stride));
3636 	    emit_insn (gen_rtx_SET (VOIDmode, r, p));
3637 	  }
3638 
3639 	/* Save this register to the stack (but use the old fp value
3640 	   we copied aside if appropriate).  */
3641 	from_regno = (fp_copy_regno >= 0
3642 		      && regno ==
3643 		      HARD_FRAME_POINTER_REGNUM) ? fp_copy_regno : regno;
3644 	FRP (frame_emit_store (from_regno, regno, r, cfa, cfa_offset));
3645 
3646 	offset -= UNITS_PER_WORD;
3647 	which_scratch = (which_scratch + 1) % ROUND_ROBIN_SIZE;
3648       }
3649 
3650   /* If profiling, force that to happen after the frame is set up.  */
3651   if (crtl->profile)
3652     emit_insn (gen_blockage ());
3653 
3654   /* Load the PIC register if needed.  */
3655   if (flag_pic && crtl->uses_pic_offset_table)
3656     load_pic_register (false);
3657 }
3658 
3659 
3660 /* Implement the epilogue and sibcall_epilogue patterns.  SIBCALL_P is
3661    true for a sibcall_epilogue pattern, and false for an epilogue
3662    pattern.  */
3663 void
3664 tilepro_expand_epilogue (bool sibcall_p)
3665 {
3666   /* We round-robin through four scratch registers to hold temporary
3667      addresses for saving registers, to make instruction scheduling
3668      easier.  */
3669   rtx reg_save_addr[ROUND_ROBIN_SIZE] = {
3670     NULL_RTX, NULL_RTX, NULL_RTX, NULL_RTX
3671   };
3672   rtx last_insn, insn;
3673   unsigned int which_scratch;
3674   int offset, start_offset, regno;
3675   rtx cfa_restores = NULL_RTX;
3676 
3677   /* A register that holds a copy of the incoming fp.  */
3678   int fp_copy_regno = -1;
3679 
3680   /* Next scratch register number to hand out (postdecrementing).  */
3681   int next_scratch_regno = 29;
3682 
3683   int total_size = compute_total_frame_size ();
3684 
3685   last_insn = get_last_insn ();
3686 
3687   /* Load lr first since we are going to need it first.  */
3688   insn = NULL;
3689   if (df_regs_ever_live_p (TILEPRO_LINK_REGNUM))
3690     {
3691       insn = frame_emit_load (TILEPRO_LINK_REGNUM,
3692 			      compute_frame_addr (0, &next_scratch_regno),
3693 			      &cfa_restores);
3694     }
3695 
3696   if (total_size == 0)
3697     {
3698       if (insn)
3699 	{
3700 	  RTX_FRAME_RELATED_P (insn) = 1;
3701 	  REG_NOTES (insn) = cfa_restores;
3702 	}
3703       goto done;
3704     }
3705 
3706   /* Compute where to start restoring registers.  */
3707   start_offset = -crtl->args.pretend_args_size - UNITS_PER_WORD;
3708   offset = start_offset;
3709 
3710   if (frame_pointer_needed)
3711     fp_copy_regno = next_scratch_regno--;
3712 
3713   /* Restore all callee-saved registers.  */
3714   which_scratch = 0;
3715   for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; regno--)
3716     if (need_to_save_reg (regno))
3717       {
3718 	rtx r = reg_save_addr[which_scratch];
3719 	if (r == NULL_RTX)
3720 	  {
3721 	    r = compute_frame_addr (offset, &next_scratch_regno);
3722 	    reg_save_addr[which_scratch] = r;
3723 	  }
3724 	else
3725 	  {
3726 	    /* Advance to the next stack slot to store this
3727 	       register.  */
3728 	    int stride = ROUND_ROBIN_SIZE * -UNITS_PER_WORD;
3729 	    rtx p = gen_rtx_PLUS (Pmode, r, GEN_INT (stride));
3730 	    emit_insn (gen_rtx_SET (VOIDmode, r, p));
3731 	  }
3732 
3733 	if (fp_copy_regno >= 0 && regno == HARD_FRAME_POINTER_REGNUM)
3734 	  frame_emit_load (fp_copy_regno, r, NULL);
3735 	else
3736 	  frame_emit_load (regno, r, &cfa_restores);
3737 
3738 	offset -= UNITS_PER_WORD;
3739 	which_scratch = (which_scratch + 1) % ROUND_ROBIN_SIZE;
3740       }
3741 
3742   if (!tilepro_current_function_is_leaf ())
3743     cfa_restores =
3744       alloc_reg_note (REG_CFA_RESTORE, stack_pointer_rtx, cfa_restores);
3745 
3746   emit_insn (gen_blockage ());
3747 
3748   if (frame_pointer_needed)
3749     {
3750       /* Restore the old stack pointer by copying from the frame
3751          pointer.  */
3752       insn = emit_insn (gen_sp_restore (stack_pointer_rtx,
3753 					hard_frame_pointer_rtx));
3754       RTX_FRAME_RELATED_P (insn) = 1;
3755       REG_NOTES (insn) = cfa_restores;
3756       add_reg_note (insn, REG_CFA_DEF_CFA, stack_pointer_rtx);
3757     }
3758   else
3759     {
3760       insn = emit_sp_adjust (total_size, &next_scratch_regno, true,
3761 			     cfa_restores);
3762     }
3763 
3764   if (crtl->calls_eh_return)
3765     emit_insn (gen_sp_adjust (stack_pointer_rtx, stack_pointer_rtx,
3766 			      EH_RETURN_STACKADJ_RTX));
3767 
3768   /* Restore the old frame pointer.  */
3769   if (frame_pointer_needed)
3770     {
3771       insn = emit_move_insn (hard_frame_pointer_rtx,
3772 			     gen_rtx_REG (Pmode, fp_copy_regno));
3773       add_reg_note (insn, REG_CFA_RESTORE, hard_frame_pointer_rtx);
3774     }
3775 
3776   /* Mark the pic registers as live outside of the function.  */
3777   if (flag_pic)
3778     {
3779       emit_use (cfun->machine->text_label_rtx);
3780       emit_use (cfun->machine->got_rtx);
3781     }
3782 
3783 done:
3784   if (!sibcall_p)
3785     {
3786       /* Emit the actual 'return' instruction.  */
3787       emit_jump_insn (gen__return ());
3788     }
3789   else
3790     {
3791       emit_use (gen_rtx_REG (Pmode, TILEPRO_LINK_REGNUM));
3792     }
3793 
3794   /* Mark all insns we just emitted as frame-related.  */
3795   for (; last_insn != NULL_RTX; last_insn = next_insn (last_insn))
3796     RTX_FRAME_RELATED_P (last_insn) = 1;
3797 }
3798 
3799 #undef ROUND_ROBIN_SIZE
3800 
3801 
3802 /* Implement INITIAL_ELIMINATION_OFFSET.  */
3803 int
3804 tilepro_initial_elimination_offset (int from, int to)
3805 {
3806   int total_size = compute_total_frame_size ();
3807 
3808   if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
3809     {
3810       return (total_size - crtl->args.pretend_args_size
3811 	      - tilepro_saved_regs_size ());
3812     }
3813   else if (from == FRAME_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM)
3814     {
3815       return -(crtl->args.pretend_args_size + tilepro_saved_regs_size ());
3816     }
3817   else if (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
3818     {
3819       return STACK_POINTER_OFFSET + total_size;
3820     }
3821   else if (from == ARG_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM)
3822     {
3823       return STACK_POINTER_OFFSET;
3824     }
3825   else
3826     gcc_unreachable ();
3827 }
3828 
3829 
3830 /* Return an RTX indicating where the return address to the
3831    calling function can be found.  */
3832 rtx
3833 tilepro_return_addr (int count, rtx frame ATTRIBUTE_UNUSED)
3834 {
3835   if (count != 0)
3836     return const0_rtx;
3837 
3838   return get_hard_reg_initial_val (Pmode, TILEPRO_LINK_REGNUM);
3839 }
3840 
3841 
3842 /* Implement EH_RETURN_HANDLER_RTX.  */
3843 rtx
3844 tilepro_eh_return_handler_rtx (void)
3845 {
3846   /* The MEM needs to be volatile to prevent it from being
3847      deleted.  */
3848   rtx tmp = gen_frame_mem (Pmode, hard_frame_pointer_rtx);
3849   MEM_VOLATILE_P (tmp) = true;
3850   return tmp;
3851 }
3852 
3853 
3854 
3855 /* Registers  */
3856 
3857 /* Implemnet TARGET_CONDITIONAL_REGISTER_USAGE.  */
3858 static void
3859 tilepro_conditional_register_usage (void)
3860 {
3861   global_regs[TILEPRO_NETORDER_REGNUM] = 1;
3862   /* TILEPRO_PIC_TEXT_LABEL_REGNUM is conditionally used.  It is a
3863      member of fixed_regs, and therefore must be member of
3864      call_used_regs, but it is not a member of call_really_used_regs[]
3865      because it is not clobbered by a call.  */
3866   if (TILEPRO_PIC_TEXT_LABEL_REGNUM != INVALID_REGNUM)
3867     {
3868       fixed_regs[TILEPRO_PIC_TEXT_LABEL_REGNUM] = 1;
3869       call_used_regs[TILEPRO_PIC_TEXT_LABEL_REGNUM] = 1;
3870     }
3871   if (PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM)
3872     {
3873       fixed_regs[PIC_OFFSET_TABLE_REGNUM] = 1;
3874       call_used_regs[PIC_OFFSET_TABLE_REGNUM] = 1;
3875     }
3876 }
3877 
3878 
3879 /* Implement TARGET_FRAME_POINTER_REQUIRED.  */
3880 static bool
3881 tilepro_frame_pointer_required (void)
3882 {
3883   return crtl->calls_eh_return || cfun->calls_alloca;
3884 }
3885 
3886 
3887 
3888 /* Scheduling and reorg  */
3889 
3890 /* Return the length of INSN.  LENGTH is the initial length computed
3891    by attributes in the machine-description file.  This is where we
3892    account for bundles.  */
3893 int
3894 tilepro_adjust_insn_length (rtx insn, int length)
3895 {
3896   enum machine_mode mode = GET_MODE (insn);
3897 
3898   /* A non-termininating instruction in a bundle has length 0.  */
3899   if (mode == SImode)
3900     return 0;
3901 
3902   /* By default, there is not length adjustment.  */
3903   return length;
3904 }
3905 
3906 
3907 /* Implement TARGET_SCHED_ISSUE_RATE.  */
3908 static int
3909 tilepro_issue_rate (void)
3910 {
3911   return 3;
3912 }
3913 
3914 
3915 /* Return the rtx for the jump target.  */
3916 static rtx
3917 get_jump_target (rtx branch)
3918 {
3919   if (CALL_P (branch))
3920     {
3921       rtx call;
3922       call = PATTERN (branch);
3923 
3924       if (GET_CODE (call) == PARALLEL)
3925 	call = XVECEXP (call, 0, 0);
3926 
3927       if (GET_CODE (call) == SET)
3928 	call = SET_SRC (call);
3929 
3930       if (GET_CODE (call) == CALL)
3931 	return XEXP (XEXP (call, 0), 0);
3932     }
3933   return 0;
3934 }
3935 
3936 /* Implement TARGET_SCHED_ADJUST_COST.  */
3937 static int
3938 tilepro_sched_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost)
3939 {
3940   /* If we have a true dependence, INSN is a call, and DEP_INSN
3941      defines a register that is needed by the call (argument or stack
3942      pointer), set its latency to 0 so that it can be bundled with
3943      the call.  Explicitly check for and exclude the case when
3944      DEP_INSN defines the target of the jump.  */
3945   if (CALL_P (insn) && REG_NOTE_KIND (link) == REG_DEP_TRUE)
3946     {
3947       rtx target = get_jump_target (insn);
3948       if (!REG_P (target) || !set_of (target, dep_insn))
3949 	return 0;
3950     }
3951 
3952   return cost;
3953 }
3954 
3955 
3956 /* Skip over irrelevant NOTEs and such and look for the next insn we
3957    would consider bundling.  */
3958 static rtx
3959 next_insn_to_bundle (rtx r, rtx end)
3960 {
3961   for (; r != end; r = NEXT_INSN (r))
3962     {
3963       if (NONDEBUG_INSN_P (r)
3964 	  && GET_CODE (PATTERN (r)) != USE
3965 	  && GET_CODE (PATTERN (r)) != CLOBBER)
3966 	return r;
3967     }
3968 
3969   return NULL_RTX;
3970 }
3971 
3972 
3973 /* Go through all insns, and use the information generated during
3974    scheduling to generate SEQUENCEs to represent bundles of
3975    instructions issued simultaneously.  */
3976 static void
3977 tilepro_gen_bundles (void)
3978 {
3979   basic_block bb;
3980   FOR_EACH_BB (bb)
3981   {
3982     rtx insn, next;
3983     rtx end = NEXT_INSN (BB_END (bb));
3984 
3985     for (insn = next_insn_to_bundle (BB_HEAD (bb), end); insn; insn = next)
3986       {
3987 	next = next_insn_to_bundle (NEXT_INSN (insn), end);
3988 
3989 	/* Never wrap {} around inline asm.  */
3990 	if (GET_CODE (PATTERN (insn)) != ASM_INPUT)
3991 	  {
3992 	    if (next == NULL_RTX || GET_MODE (next) == TImode
3993 		/* NOTE: The scheduler incorrectly believes a call
3994 		   insn can execute in the same cycle as the insn
3995 		   after the call.  This is of course impossible.
3996 		   Really we need to fix the scheduler somehow, so
3997 		   the code after the call gets scheduled
3998 		   optimally.  */
3999 		|| CALL_P (insn))
4000 	      {
4001 		/* Mark current insn as the end of a bundle.  */
4002 		PUT_MODE (insn, QImode);
4003 	      }
4004 	    else
4005 	      {
4006 		/* Mark it as part of a bundle.  */
4007 		PUT_MODE (insn, SImode);
4008 	      }
4009 	  }
4010       }
4011   }
4012 }
4013 
4014 
4015 /* Helper function for tilepro_fixup_pcrel_references.  */
4016 static void
4017 replace_pc_relative_symbol_ref (rtx insn, rtx opnds[4], bool first_insn_p)
4018 {
4019   rtx new_insns;
4020 
4021   start_sequence ();
4022 
4023   if (flag_pic == 1)
4024     {
4025       if (!first_insn_p)
4026 	{
4027 	  emit_insn (gen_add_got16 (opnds[0], tilepro_got_rtx (),
4028 				    opnds[2]));
4029 	  emit_insn (gen_insn_lw (opnds[0], opnds[0]));
4030 	}
4031     }
4032   else
4033     {
4034       if (first_insn_p)
4035 	{
4036 	  emit_insn (gen_addhi_got32 (opnds[0], tilepro_got_rtx (),
4037 				      opnds[2]));
4038 	}
4039       else
4040 	{
4041 	  emit_insn (gen_addlo_got32 (opnds[0], opnds[1], opnds[2]));
4042 	  emit_insn (gen_insn_lw (opnds[0], opnds[0]));
4043 	}
4044     }
4045 
4046   new_insns = get_insns ();
4047   end_sequence ();
4048 
4049   if (new_insns)
4050     emit_insn_before (new_insns, insn);
4051 
4052   delete_insn (insn);
4053 }
4054 
4055 
4056 /* Returns whether INSN is a pc-relative addli insn.   */
4057 static bool
4058 match_addli_pcrel (rtx insn)
4059 {
4060   rtx pattern = PATTERN (insn);
4061   rtx unspec;
4062 
4063   if (GET_CODE (pattern) != SET)
4064     return false;
4065 
4066   if (GET_CODE (SET_SRC (pattern)) != LO_SUM)
4067     return false;
4068 
4069   if (GET_CODE (XEXP (SET_SRC (pattern), 1)) != CONST)
4070     return false;
4071 
4072   unspec = XEXP (XEXP (SET_SRC (pattern), 1), 0);
4073 
4074   return (GET_CODE (unspec) == UNSPEC
4075 	  && XINT (unspec, 1) == UNSPEC_PCREL_SYM);
4076 }
4077 
4078 
4079 /* Helper function for tilepro_fixup_pcrel_references.  */
4080 static void
4081 replace_addli_pcrel (rtx insn)
4082 {
4083   rtx pattern = PATTERN (insn);
4084   rtx set_src;
4085   rtx unspec;
4086   rtx opnds[4];
4087   bool first_insn_p;
4088 
4089   gcc_assert (GET_CODE (pattern) == SET);
4090   opnds[0] = SET_DEST (pattern);
4091 
4092   set_src = SET_SRC (pattern);
4093   gcc_assert (GET_CODE (set_src) == LO_SUM);
4094   gcc_assert (GET_CODE (XEXP (set_src, 1)) == CONST);
4095   opnds[1] = XEXP (set_src, 0);
4096 
4097   unspec = XEXP (XEXP (set_src, 1), 0);
4098   gcc_assert (GET_CODE (unspec) == UNSPEC);
4099   gcc_assert (XINT (unspec, 1) == UNSPEC_PCREL_SYM);
4100   opnds[2] = XVECEXP (unspec, 0, 0);
4101   opnds[3] = XVECEXP (unspec, 0, 1);
4102 
4103   /* We only need to replace SYMBOL_REFs, not LABEL_REFs.  */
4104   if (GET_CODE (opnds[2]) != SYMBOL_REF)
4105     return;
4106 
4107   first_insn_p = (opnds[1] == tilepro_text_label_rtx ());
4108 
4109   replace_pc_relative_symbol_ref (insn, opnds, first_insn_p);
4110 }
4111 
4112 
4113 /* Returns whether INSN is a pc-relative auli insn.   */
4114 static bool
4115 match_auli_pcrel (rtx insn)
4116 {
4117   rtx pattern = PATTERN (insn);
4118   rtx high;
4119   rtx unspec;
4120 
4121   if (GET_CODE (pattern) != SET)
4122     return false;
4123 
4124   if (GET_CODE (SET_SRC (pattern)) != PLUS)
4125     return false;
4126 
4127   high = XEXP (SET_SRC (pattern), 1);
4128 
4129   if (GET_CODE (high) != HIGH
4130       || GET_CODE (XEXP (high, 0)) != CONST)
4131     return false;
4132 
4133   unspec = XEXP (XEXP (high, 0), 0);
4134 
4135   return (GET_CODE (unspec) == UNSPEC
4136 	  && XINT (unspec, 1) == UNSPEC_PCREL_SYM);
4137 }
4138 
4139 
4140 /* Helper function for tilepro_fixup_pcrel_references.  */
4141 static void
4142 replace_auli_pcrel (rtx insn)
4143 {
4144   rtx pattern = PATTERN (insn);
4145   rtx set_src;
4146   rtx high;
4147   rtx unspec;
4148   rtx opnds[4];
4149   bool first_insn_p;
4150 
4151   gcc_assert (GET_CODE (pattern) == SET);
4152   opnds[0] = SET_DEST (pattern);
4153 
4154   set_src = SET_SRC (pattern);
4155   gcc_assert (GET_CODE (set_src) == PLUS);
4156   opnds[1] = XEXP (set_src, 0);
4157 
4158   high = XEXP (set_src, 1);
4159   gcc_assert (GET_CODE (high) == HIGH);
4160   gcc_assert (GET_CODE (XEXP (high, 0)) == CONST);
4161 
4162   unspec = XEXP (XEXP (high, 0), 0);
4163   gcc_assert (GET_CODE (unspec) == UNSPEC);
4164   gcc_assert (XINT (unspec, 1) == UNSPEC_PCREL_SYM);
4165   opnds[2] = XVECEXP (unspec, 0, 0);
4166   opnds[3] = XVECEXP (unspec, 0, 1);
4167 
4168   /* We only need to replace SYMBOL_REFs, not LABEL_REFs.  */
4169   if (GET_CODE (opnds[2]) != SYMBOL_REF)
4170     return;
4171 
4172   first_insn_p = (opnds[1] == tilepro_text_label_rtx ());
4173 
4174   replace_pc_relative_symbol_ref (insn, opnds, first_insn_p);
4175 }
4176 
4177 
4178 /* We generate PC relative SYMBOL_REFs as an optimization, to avoid
4179    going through the GOT when the symbol is local to the compilation
4180    unit.  But such a symbol requires that the common text_label that
4181    we generate at the beginning of the function be in the same section
4182    as the reference to the SYMBOL_REF.  This may not be true if we
4183    generate hot/cold sections.  This function looks for such cases and
4184    replaces such references with the longer sequence going through the
4185    GOT.
4186 
4187    We expect one of the following two instruction sequences:
4188    addli tmp1, txt_label_reg, lo16(sym - txt_label)
4189    auli  tmp2,          tmp1, ha16(sym - txt_label)
4190 
4191    auli  tmp1, txt_label_reg, ha16(sym - txt_label)
4192    addli tmp2,          tmp1, lo16(sym - txt_label)
4193 
4194    If we're compiling -fpic, we replace the first instruction with
4195    nothing, and the second instruction with:
4196 
4197    addli tmp2, got_rtx, got(sym)
4198    lw    tmp2,    tmp2
4199 
4200    If we're compiling -fPIC, we replace the first instruction with:
4201 
4202    auli  tmp1, got_rtx, got_ha16(sym)
4203 
4204    and the second instruction with:
4205 
4206    addli tmp2,    tmp1, got_lo16(sym)
4207    lw    tmp2,    tmp2
4208 
4209    Note that we're careful to disturb the instruction sequence as
4210    little as possible, since it's very late in the compilation
4211    process.
4212 */
4213 static void
4214 tilepro_fixup_pcrel_references (void)
4215 {
4216   rtx insn, next_insn;
4217   bool same_section_as_entry = true;
4218 
4219   for (insn = get_insns (); insn; insn = next_insn)
4220     {
4221       next_insn = NEXT_INSN (insn);
4222 
4223       if (NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_SWITCH_TEXT_SECTIONS)
4224 	{
4225 	  same_section_as_entry = !same_section_as_entry;
4226 	  continue;
4227 	}
4228 
4229       if (same_section_as_entry)
4230       	continue;
4231 
4232       if (!(INSN_P (insn)
4233 	    && GET_CODE (PATTERN (insn)) != USE
4234 	    && GET_CODE (PATTERN (insn)) != CLOBBER))
4235 	continue;
4236 
4237       if (match_addli_pcrel (insn))
4238 	replace_addli_pcrel (insn);
4239       else if (match_auli_pcrel (insn))
4240 	replace_auli_pcrel (insn);
4241     }
4242 }
4243 
4244 
4245 /* Ensure that no var tracking notes are emitted in the middle of a
4246    three-instruction bundle.  */
4247 static void
4248 reorder_var_tracking_notes (void)
4249 {
4250   basic_block bb;
4251   FOR_EACH_BB (bb)
4252   {
4253     rtx insn, next;
4254     rtx queue = NULL_RTX;
4255     bool in_bundle = false;
4256 
4257     for (insn = BB_HEAD (bb); insn != BB_END (bb); insn = next)
4258       {
4259 	next = NEXT_INSN (insn);
4260 
4261 	if (INSN_P (insn))
4262 	  {
4263 	    /* Emit queued up notes at the last instruction of a bundle.  */
4264 	    if (GET_MODE (insn) == QImode)
4265 	      {
4266 		while (queue)
4267 		  {
4268 		    rtx next_queue = PREV_INSN (queue);
4269 		    PREV_INSN (NEXT_INSN (insn)) = queue;
4270 		    NEXT_INSN (queue) = NEXT_INSN (insn);
4271 		    NEXT_INSN (insn) = queue;
4272 		    PREV_INSN (queue) = insn;
4273 		    queue = next_queue;
4274 		  }
4275 		in_bundle = false;
4276 	      }
4277 	    else if (GET_MODE (insn) == SImode)
4278 	      in_bundle = true;
4279 	  }
4280 	else if (NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_VAR_LOCATION)
4281 	  {
4282 	    if (in_bundle)
4283 	      {
4284 		rtx prev = PREV_INSN (insn);
4285 		PREV_INSN (next) = prev;
4286 		NEXT_INSN (prev) = next;
4287 
4288 		PREV_INSN (insn) = queue;
4289 		queue = insn;
4290 	      }
4291 	  }
4292       }
4293   }
4294 }
4295 
4296 
4297 /* Perform machine dependent operations on the rtl chain INSNS.  */
4298 static void
4299 tilepro_reorg (void)
4300 {
4301   /* We are freeing block_for_insn in the toplev to keep compatibility
4302      with old MDEP_REORGS that are not CFG based.  Recompute it
4303      now.  */
4304   compute_bb_for_insn ();
4305 
4306   if (flag_reorder_blocks_and_partition)
4307     {
4308       tilepro_fixup_pcrel_references ();
4309     }
4310 
4311   if (flag_schedule_insns_after_reload)
4312     {
4313       split_all_insns ();
4314 
4315       timevar_push (TV_SCHED2);
4316       schedule_insns ();
4317       timevar_pop (TV_SCHED2);
4318 
4319       /* Examine the schedule to group into bundles.  */
4320       tilepro_gen_bundles ();
4321     }
4322 
4323   df_analyze ();
4324 
4325   if (flag_var_tracking)
4326     {
4327       timevar_push (TV_VAR_TRACKING);
4328       variable_tracking_main ();
4329       reorder_var_tracking_notes ();
4330       timevar_pop (TV_VAR_TRACKING);
4331     }
4332 
4333   df_finish_pass (false);
4334 }
4335 
4336 
4337 
4338 /* Assembly  */
4339 
4340 /* Select a format to encode pointers in exception handling data.
4341    CODE is 0 for data, 1 for code labels, 2 for function pointers.
4342    GLOBAL is true if the symbol may be affected by dynamic
4343    relocations.  */
4344 int
4345 tilepro_asm_preferred_eh_data_format (int code ATTRIBUTE_UNUSED, int global)
4346 {
4347   return (global ? DW_EH_PE_indirect : 0) | DW_EH_PE_pcrel | DW_EH_PE_sdata4;
4348 }
4349 
4350 
4351 /* Implement TARGET_ASM_OUTPUT_MI_THUNK.  */
4352 static void
4353 tilepro_asm_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
4354 			     HOST_WIDE_INT delta, HOST_WIDE_INT vcall_offset,
4355 			     tree function)
4356 {
4357   rtx this_rtx, insn, funexp;
4358 
4359   /* Pretend to be a post-reload pass while generating rtl.  */
4360   reload_completed = 1;
4361 
4362   /* Mark the end of the (empty) prologue.  */
4363   emit_note (NOTE_INSN_PROLOGUE_END);
4364 
4365   /* Find the "this" pointer.  If the function returns a structure,
4366      the structure return pointer is in $1.  */
4367   if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function))
4368     this_rtx = gen_rtx_REG (Pmode, 1);
4369   else
4370     this_rtx = gen_rtx_REG (Pmode, 0);
4371 
4372   /* Add DELTA to THIS_RTX.  */
4373   emit_insn (gen_addsi3 (this_rtx, this_rtx, GEN_INT (delta)));
4374 
4375   /* If needed, add *(*THIS_RTX + VCALL_OFFSET) to THIS_RTX.  */
4376   if (vcall_offset)
4377     {
4378       rtx tmp;
4379 
4380       tmp = gen_rtx_REG (Pmode, 29);
4381       emit_move_insn (tmp, gen_rtx_MEM (Pmode, this_rtx));
4382 
4383       emit_insn (gen_addsi3 (tmp, tmp, GEN_INT (vcall_offset)));
4384 
4385       emit_move_insn (tmp, gen_rtx_MEM (Pmode, tmp));
4386 
4387       emit_insn (gen_addsi3 (this_rtx, this_rtx, tmp));
4388     }
4389 
4390   /* Generate a tail call to the target function.  */
4391   if (!TREE_USED (function))
4392     {
4393       assemble_external (function);
4394       TREE_USED (function) = 1;
4395     }
4396   funexp = XEXP (DECL_RTL (function), 0);
4397   funexp = gen_rtx_MEM (FUNCTION_MODE, funexp);
4398   insn = emit_call_insn (gen_sibcall (funexp, const0_rtx));
4399   SIBLING_CALL_P (insn) = 1;
4400 
4401   /* Run just enough of rest_of_compilation to get the insns emitted.
4402      There's not really enough bulk here to make other passes such as
4403      instruction scheduling worth while.  Note that use_thunk calls
4404      assemble_start_function and assemble_end_function.
4405 
4406      We don't currently bundle, but the instruciton sequence is all
4407      serial except for the tail call, so we're only wasting one cycle.
4408    */
4409   insn = get_insns ();
4410   shorten_branches (insn);
4411   final_start_function (insn, file, 1);
4412   final (insn, file, 1);
4413   final_end_function ();
4414 
4415   /* Stop pretending to be a post-reload pass.  */
4416   reload_completed = 0;
4417 }
4418 
4419 
4420 /* Implement TARGET_ASM_TRAMPOLINE_TEMPLATE.  */
4421 static void
4422 tilepro_asm_trampoline_template (FILE *file)
4423 {
4424   fprintf (file, "\tlnk   r10\n");
4425   fprintf (file, "\taddi  r10, r10, 32\n");
4426   fprintf (file, "\tlwadd r11, r10, %d\n", GET_MODE_SIZE (ptr_mode));
4427   fprintf (file, "\tlw    r10, r10\n");
4428   fprintf (file, "\tjr    r11\n");
4429   fprintf (file, "\t.word 0 # <function address>\n");
4430   fprintf (file, "\t.word 0 # <static chain value>\n");
4431 }
4432 
4433 
4434 /* Implement TARGET_TRAMPOLINE_INIT.  */
4435 static void
4436 tilepro_trampoline_init (rtx m_tramp, tree fndecl, rtx static_chain)
4437 {
4438   rtx fnaddr, chaddr;
4439   rtx mem;
4440   rtx begin_addr, end_addr;
4441   int ptr_mode_size = GET_MODE_SIZE (ptr_mode);
4442 
4443   fnaddr = copy_to_reg (XEXP (DECL_RTL (fndecl), 0));
4444   chaddr = copy_to_reg (static_chain);
4445 
4446   emit_block_move (m_tramp, assemble_trampoline_template (),
4447 		   GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NORMAL);
4448 
4449   mem = adjust_address (m_tramp, ptr_mode,
4450 			TRAMPOLINE_SIZE - 2 * ptr_mode_size);
4451   emit_move_insn (mem, fnaddr);
4452   mem = adjust_address (m_tramp, ptr_mode,
4453 			TRAMPOLINE_SIZE - ptr_mode_size);
4454   emit_move_insn (mem, chaddr);
4455 
4456   /* Get pointers to the beginning and end of the code block.  */
4457   begin_addr = force_reg (Pmode, XEXP (m_tramp, 0));
4458   end_addr = force_reg (Pmode, plus_constant (Pmode, XEXP (m_tramp, 0),
4459 					      TRAMPOLINE_SIZE));
4460 
4461   emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__clear_cache"),
4462 		     LCT_NORMAL, VOIDmode, 2, begin_addr, Pmode,
4463 		     end_addr, Pmode);
4464 }
4465 
4466 
4467 /* Implement TARGET_PRINT_OPERAND.  */
4468 static void
4469 tilepro_print_operand (FILE *file, rtx x, int code)
4470 {
4471   switch (code)
4472     {
4473     case 'c':
4474       /* Print the compare operator opcode for conditional moves. */
4475       switch (GET_CODE (x))
4476 	{
4477 	case EQ:
4478 	  fputs ("z", file);
4479 	  break;
4480 	case NE:
4481 	  fputs ("nz", file);
4482 	  break;
4483 	default:
4484 	  output_operand_lossage ("invalid %%c operand");
4485 	}
4486       return;
4487 
4488     case 'C':
4489       /* Print the compare operator opcode for conditional moves. */
4490       switch (GET_CODE (x))
4491 	{
4492 	case EQ:
4493 	  fputs ("nz", file);
4494 	  break;
4495 	case NE:
4496 	  fputs ("z", file);
4497 	  break;
4498 	default:
4499 	  output_operand_lossage ("invalid %%C operand");
4500 	}
4501       return;
4502 
4503     case 'h':
4504       {
4505 	/* Print the high 16 bits of a 32-bit constant.  */
4506 	HOST_WIDE_INT i;
4507 	if (CONST_INT_P (x))
4508 	  i = INTVAL (x);
4509 	else if (GET_CODE (x) == CONST_DOUBLE)
4510 	  i = CONST_DOUBLE_LOW (x);
4511 	else
4512 	  {
4513 	    output_operand_lossage ("invalid %%h operand");
4514 	    return;
4515 	  }
4516 	i = trunc_int_for_mode (i >> 16, HImode);
4517 	fprintf (file, HOST_WIDE_INT_PRINT_DEC, i);
4518 	return;
4519       }
4520 
4521     case 'H':
4522       {
4523 	rtx addr = NULL;
4524 	const char *opstr = NULL;
4525 	bool pcrel = false;
4526 	if (GET_CODE (x) == CONST
4527 	    && GET_CODE (XEXP (x, 0)) == UNSPEC)
4528 	  {
4529 	    addr = XVECEXP (XEXP (x, 0), 0, 0);
4530 	    switch (XINT (XEXP (x, 0), 1))
4531 	    {
4532 	    case UNSPEC_GOT32_SYM:
4533 	      opstr = "got_ha16";
4534 	      break;
4535 	    case UNSPEC_PCREL_SYM:
4536 	      opstr = "ha16";
4537 	      pcrel = true;
4538 	      break;
4539 	    case UNSPEC_TLS_GD:
4540 	      opstr = "tls_gd_ha16";
4541 	      break;
4542 	    case UNSPEC_TLS_IE:
4543 	      opstr = "tls_ie_ha16";
4544 	      break;
4545 	    case UNSPEC_TLS_LE:
4546 	      opstr = "tls_le_ha16";
4547 	      break;
4548 	    default:
4549 	      output_operand_lossage ("invalid %%H operand");
4550 	    }
4551 	  }
4552 	else
4553 	  {
4554 	    addr = x;
4555 	    opstr = "ha16";
4556 	  }
4557 
4558 	fputs (opstr, file);
4559 	fputc ('(', file);
4560 	output_addr_const (file, addr);
4561 
4562 	if (pcrel)
4563 	  {
4564 	    rtx addr2 = XVECEXP (XEXP (x, 0), 0, 1);
4565 	    fputs (" - " , file);
4566 	    output_addr_const (file, addr2);
4567 	  }
4568 
4569 	fputc (')', file);
4570 	return;
4571       }
4572 
4573     case 'I':
4574       /* Print an auto-inc memory operand.  */
4575       if (!MEM_P (x))
4576 	{
4577 	  output_operand_lossage ("invalid %%I operand");
4578 	  return;
4579 	}
4580 
4581       output_memory_reference_mode = GET_MODE (x);
4582       output_memory_autoinc_first = true;
4583       output_address (XEXP (x, 0));
4584       output_memory_reference_mode = VOIDmode;
4585       return;
4586 
4587     case 'i':
4588       /* Print an auto-inc memory operand.  */
4589       if (!MEM_P (x))
4590 	{
4591 	  output_operand_lossage ("invalid %%i operand");
4592 	  return;
4593 	}
4594 
4595       output_memory_reference_mode = GET_MODE (x);
4596       output_memory_autoinc_first = false;
4597       output_address (XEXP (x, 0));
4598       output_memory_reference_mode = VOIDmode;
4599       return;
4600 
4601     case 'j':
4602       {
4603 	/* Print the low 8 bits of a constant.  */
4604 	HOST_WIDE_INT i;
4605 	if (CONST_INT_P (x))
4606 	  i = INTVAL (x);
4607 	else if (GET_CODE (x) == CONST_DOUBLE)
4608 	  i = CONST_DOUBLE_LOW (x);
4609 	else if (GET_CODE (x) == CONST_VECTOR
4610 		 && CONST_INT_P (CONST_VECTOR_ELT (x, 0)))
4611 	  i = INTVAL (CONST_VECTOR_ELT (x, 0));
4612 	else
4613 	  {
4614 	    output_operand_lossage ("invalid %%j operand");
4615 	    return;
4616 	  }
4617 	i = trunc_int_for_mode (i, QImode);
4618 	fprintf (file, HOST_WIDE_INT_PRINT_DEC, i);
4619 	return;
4620       }
4621 
4622     case 'L':
4623       {
4624 	rtx addr = NULL;
4625 	const char *opstr = NULL;
4626 	bool pcrel = false;
4627 	if (GET_CODE (x) == CONST
4628 	    && GET_CODE (XEXP (x, 0)) == UNSPEC)
4629 	  {
4630 	    addr = XVECEXP (XEXP (x, 0), 0, 0);
4631 	    switch (XINT (XEXP (x, 0), 1))
4632 	    {
4633 	    case UNSPEC_GOT16_SYM:
4634 	      opstr = "got";
4635 	      break;
4636 	    case UNSPEC_GOT32_SYM:
4637 	      opstr = "got_lo16";
4638 	      break;
4639 	    case UNSPEC_PCREL_SYM:
4640 	      opstr = "lo16";
4641 	      pcrel = true;
4642 	      break;
4643 	    case UNSPEC_TLS_GD:
4644 	      opstr = "tls_gd_lo16";
4645 	      break;
4646 	    case UNSPEC_TLS_IE:
4647 	      opstr = "tls_ie_lo16";
4648 	      break;
4649 	    case UNSPEC_TLS_LE:
4650 	      opstr = "tls_le_lo16";
4651 	      break;
4652 	    default:
4653 	      output_operand_lossage ("invalid %%L operand");
4654 	    }
4655 	  }
4656 	else
4657 	  {
4658 	    addr = x;
4659 	    opstr = "lo16";
4660 	  }
4661 
4662 	fputs (opstr, file);
4663 	fputc ('(', file);
4664 	output_addr_const (file, addr);
4665 
4666 	if (pcrel)
4667 	  {
4668 	    rtx addr2 = XVECEXP (XEXP (x, 0), 0, 1);
4669 	    fputs (" - " , file);
4670 	    output_addr_const (file, addr2);
4671 	  }
4672 
4673 	fputc (')', file);
4674 	return;
4675       }
4676 
4677     case 'p':
4678       if (GET_CODE (x) == SYMBOL_REF)
4679 	{
4680 	  if (flag_pic && !SYMBOL_REF_LOCAL_P (x))
4681 	    fprintf (file, "plt(");
4682 	  output_addr_const (file, x);
4683 	  if (flag_pic && !SYMBOL_REF_LOCAL_P (x))
4684 	    fprintf (file, ")");
4685 	}
4686       else
4687 	output_addr_const (file, x);
4688       return;
4689 
4690     case 'P':
4691       {
4692 	/* Print a 32-bit constant plus one.  */
4693 	HOST_WIDE_INT i;
4694 	if (!CONST_INT_P (x))
4695 	  {
4696 	    output_operand_lossage ("invalid %%P operand");
4697 	    return;
4698 	  }
4699 	i = trunc_int_for_mode (INTVAL (x) + 1, SImode);
4700 	fprintf (file, HOST_WIDE_INT_PRINT_DEC, i);
4701 	return;
4702       }
4703 
4704     case 'M':
4705       {
4706 	/* Print an mm-style bit range.  */
4707 	int first_bit, last_bit;
4708 
4709 	if (!CONST_INT_P (x)
4710 	    || !tilepro_bitfield_operand_p (INTVAL (x), &first_bit,
4711 					    &last_bit))
4712 	  {
4713 	    output_operand_lossage ("invalid %%M operand");
4714 	    return;
4715 	  }
4716 
4717 	fprintf (file, "%d, %d", first_bit, last_bit);
4718 	return;
4719       }
4720 
4721     case 'N':
4722       {
4723 	const char *reg = NULL;
4724 
4725 	/* Print a network register.  */
4726 	if (!CONST_INT_P (x))
4727 	  {
4728 	    output_operand_lossage ("invalid %%N operand");
4729 	    return;
4730 	  }
4731 
4732 	switch (INTVAL (x))
4733 	  {
4734 	  case TILEPRO_NETREG_IDN0: reg = "idn0"; break;
4735 	  case TILEPRO_NETREG_IDN1: reg = "idn1"; break;
4736 	  case TILEPRO_NETREG_SN:   reg = "sn";   break;
4737 	  case TILEPRO_NETREG_UDN0: reg = "udn0"; break;
4738 	  case TILEPRO_NETREG_UDN1: reg = "udn1"; break;
4739 	  case TILEPRO_NETREG_UDN2: reg = "udn2"; break;
4740 	  case TILEPRO_NETREG_UDN3: reg = "udn3"; break;
4741 	  default: gcc_unreachable ();
4742 	  }
4743 
4744 	fprintf (file, reg);
4745 	return;
4746       }
4747 
4748     case 't':
4749       {
4750 	/* Log base 2 of a power of two.  */
4751 	HOST_WIDE_INT i;
4752 	HOST_WIDE_INT n;
4753 
4754 	if (!CONST_INT_P (x))
4755 	  {
4756 	    output_operand_lossage ("invalid %%t operand");
4757 	    return;
4758 	  }
4759 	n = trunc_int_for_mode (INTVAL (x), SImode);
4760 	i = exact_log2 (n);
4761 	if (i < 0)
4762 	  {
4763 	    output_operand_lossage ("invalid %%t operand '"
4764 				    HOST_WIDE_INT_PRINT_DEC "'", n);
4765 	    return;
4766 	  }
4767 
4768 	fprintf (file, HOST_WIDE_INT_PRINT_DEC, i);
4769 	return;
4770       }
4771       break;
4772 
4773     case 'r':
4774       /* In this case we need a register.  Use 'zero' if the
4775          operand is const0_rtx.  */
4776       if (x == const0_rtx
4777 	  || (GET_MODE (x) != VOIDmode && x == CONST0_RTX (GET_MODE (x))))
4778 	{
4779 	  fputs ("zero", file);
4780 	  return;
4781 	}
4782       else if (!REG_P (x))
4783 	{
4784 	  output_operand_lossage ("invalid %%r operand");
4785 	  return;
4786 	}
4787       /* FALLTHRU */
4788 
4789     case 0:
4790       if (REG_P (x))
4791 	{
4792 	  fprintf (file, "%s", reg_names[REGNO (x)]);
4793 	  return;
4794 	}
4795       else if (MEM_P (x))
4796 	{
4797 	  output_memory_reference_mode = VOIDmode;
4798 	  output_address (XEXP (x, 0));
4799 	  return;
4800 	}
4801       else
4802 	{
4803 	  output_addr_const (file, x);
4804 	  return;
4805 	}
4806       break;
4807     }
4808 
4809   debug_rtx (x);
4810   output_operand_lossage ("unable to print out operand yet; code == %d (%c)",
4811 			  code, code);
4812 }
4813 
4814 
4815 /* Implement TARGET_PRINT_OPERAND_ADDRESS.  */
4816 static void
4817 tilepro_print_operand_address (FILE *file, rtx addr)
4818 {
4819   if (GET_CODE (addr) == POST_DEC
4820       || GET_CODE (addr) == POST_INC)
4821     {
4822       int offset = GET_MODE_SIZE (output_memory_reference_mode);
4823 
4824       gcc_assert (output_memory_reference_mode != VOIDmode);
4825 
4826       if (output_memory_autoinc_first)
4827 	fprintf (file, "%s", reg_names[REGNO (XEXP (addr, 0))]);
4828       else
4829 	fprintf (file, "%d",
4830 		 GET_CODE (addr) == POST_DEC ? -offset : offset);
4831     }
4832   else if (GET_CODE (addr) == POST_MODIFY)
4833     {
4834       gcc_assert (output_memory_reference_mode != VOIDmode);
4835 
4836       gcc_assert (GET_CODE (XEXP (addr, 1)) == PLUS);
4837 
4838       if (output_memory_autoinc_first)
4839 	fprintf (file, "%s", reg_names[REGNO (XEXP (addr, 0))]);
4840       else
4841 	fprintf (file, HOST_WIDE_INT_PRINT_DEC,
4842 		 INTVAL (XEXP (XEXP (addr, 1), 1)));
4843     }
4844   else
4845     tilepro_print_operand (file, addr, 'r');
4846 }
4847 
4848 
4849 /* Machine mode of current insn, for determining curly brace
4850    placement.  */
4851 static enum machine_mode insn_mode;
4852 
4853 
4854 /* Implement FINAL_PRESCAN_INSN.  This is used to emit bundles.  */
4855 void
4856 tilepro_final_prescan_insn (rtx insn)
4857 {
4858   /* Record this for tilepro_asm_output_opcode to examine.  */
4859   insn_mode = GET_MODE (insn);
4860 }
4861 
4862 
4863 /* While emitting asm, are we currently inside '{' for a bundle? */
4864 static bool tilepro_in_bundle = false;
4865 
4866 /* Implement ASM_OUTPUT_OPCODE.  Prepend/append curly braces as
4867    appropriate given the bundling information recorded by
4868    tilepro_gen_bundles.  */
4869 const char *
4870 tilepro_asm_output_opcode (FILE *stream, const char *code)
4871 {
4872   bool pseudo = !strcmp (code, "pseudo");
4873 
4874   if (!tilepro_in_bundle && insn_mode == SImode)
4875     {
4876       /* Start a new bundle.  */
4877       fprintf (stream, "{\n\t");
4878       tilepro_in_bundle = true;
4879     }
4880 
4881   if (tilepro_in_bundle && insn_mode == QImode)
4882     {
4883       /* Close an existing bundle.  */
4884       static char buf[100];
4885 
4886       gcc_assert (strlen (code) + 3 + 1 < sizeof (buf));
4887 
4888       strcpy (buf, pseudo ? "" : code);
4889       strcat (buf, "\n\t}");
4890       tilepro_in_bundle = false;
4891 
4892       return buf;
4893     }
4894   else
4895     {
4896       return pseudo ? "" : code;
4897     }
4898 }
4899 
4900 
4901 /* Output assembler code to FILE to increment profiler label # LABELNO
4902    for profiling a function entry.  */
4903 void
4904 tilepro_function_profiler (FILE *file, int labelno ATTRIBUTE_UNUSED)
4905 {
4906   if (tilepro_in_bundle)
4907     {
4908       fprintf (file, "\t}\n");
4909     }
4910 
4911   if (flag_pic)
4912     {
4913       fprintf (file,
4914 	       "\t{\n"
4915 	       "\tmove\tr10, lr\n"
4916 	       "\tjal\tplt(%s)\n"
4917 	       "\t}\n", MCOUNT_NAME);
4918     }
4919   else
4920     {
4921       fprintf (file,
4922 	       "\t{\n"
4923 	       "\tmove\tr10, lr\n"
4924 	       "\tjal\t%s\n"
4925 	       "\t}\n", MCOUNT_NAME);
4926     }
4927 
4928   tilepro_in_bundle = false;
4929 }
4930 
4931 
4932 /* Implement TARGET_ASM_FILE_END.  */
4933 static void
4934 tilepro_file_end (void)
4935 {
4936   if (NEED_INDICATE_EXEC_STACK)
4937     file_end_indicate_exec_stack ();
4938 }
4939 
4940 
4941 #undef  TARGET_HAVE_TLS
4942 #define TARGET_HAVE_TLS HAVE_AS_TLS
4943 
4944 #undef  TARGET_OPTION_OVERRIDE
4945 #define TARGET_OPTION_OVERRIDE tilepro_option_override
4946 
4947 #undef  TARGET_SCALAR_MODE_SUPPORTED_P
4948 #define TARGET_SCALAR_MODE_SUPPORTED_P tilepro_scalar_mode_supported_p
4949 
4950 #undef  TARGET_VECTOR_MODE_SUPPORTED_P
4951 #define TARGET_VECTOR_MODE_SUPPORTED_P tile_vector_mode_supported_p
4952 
4953 #undef  TARGET_CANNOT_FORCE_CONST_MEM
4954 #define TARGET_CANNOT_FORCE_CONST_MEM tilepro_cannot_force_const_mem
4955 
4956 #undef  TARGET_FUNCTION_OK_FOR_SIBCALL
4957 #define TARGET_FUNCTION_OK_FOR_SIBCALL tilepro_function_ok_for_sibcall
4958 
4959 #undef  TARGET_PASS_BY_REFERENCE
4960 #define TARGET_PASS_BY_REFERENCE tilepro_pass_by_reference
4961 
4962 #undef  TARGET_RETURN_IN_MEMORY
4963 #define TARGET_RETURN_IN_MEMORY tilepro_return_in_memory
4964 
4965 #undef  TARGET_FUNCTION_ARG_BOUNDARY
4966 #define TARGET_FUNCTION_ARG_BOUNDARY tilepro_function_arg_boundary
4967 
4968 #undef  TARGET_FUNCTION_ARG
4969 #define TARGET_FUNCTION_ARG tilepro_function_arg
4970 
4971 #undef  TARGET_FUNCTION_ARG_ADVANCE
4972 #define TARGET_FUNCTION_ARG_ADVANCE tilepro_function_arg_advance
4973 
4974 #undef  TARGET_FUNCTION_VALUE
4975 #define TARGET_FUNCTION_VALUE tilepro_function_value
4976 
4977 #undef  TARGET_LIBCALL_VALUE
4978 #define TARGET_LIBCALL_VALUE tilepro_libcall_value
4979 
4980 #undef  TARGET_FUNCTION_VALUE_REGNO_P
4981 #define TARGET_FUNCTION_VALUE_REGNO_P tilepro_function_value_regno_p
4982 
4983 #undef  TARGET_PROMOTE_FUNCTION_MODE
4984 #define TARGET_PROMOTE_FUNCTION_MODE \
4985   default_promote_function_mode_always_promote
4986 
4987 #undef  TARGET_PROMOTE_PROTOTYPES
4988 #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_false
4989 
4990 #undef  TARGET_BUILD_BUILTIN_VA_LIST
4991 #define TARGET_BUILD_BUILTIN_VA_LIST tilepro_build_builtin_va_list
4992 
4993 #undef  TARGET_EXPAND_BUILTIN_VA_START
4994 #define TARGET_EXPAND_BUILTIN_VA_START tilepro_va_start
4995 
4996 #undef  TARGET_SETUP_INCOMING_VARARGS
4997 #define TARGET_SETUP_INCOMING_VARARGS tilepro_setup_incoming_varargs
4998 
4999 #undef  TARGET_GIMPLIFY_VA_ARG_EXPR
5000 #define TARGET_GIMPLIFY_VA_ARG_EXPR tilepro_gimplify_va_arg_expr
5001 
5002 #undef  TARGET_RTX_COSTS
5003 #define TARGET_RTX_COSTS tilepro_rtx_costs
5004 
5005 /* Limit to what we can reach in one addli.  */
5006 #undef  TARGET_MIN_ANCHOR_OFFSET
5007 #define TARGET_MIN_ANCHOR_OFFSET -32768
5008 #undef  TARGET_MAX_ANCHOR_OFFSET
5009 #define TARGET_MAX_ANCHOR_OFFSET 32767
5010 
5011 #undef  TARGET_LEGITIMATE_CONSTANT_P
5012 #define TARGET_LEGITIMATE_CONSTANT_P tilepro_legitimate_constant_p
5013 
5014 #undef  TARGET_LEGITIMATE_ADDRESS_P
5015 #define TARGET_LEGITIMATE_ADDRESS_P tilepro_legitimate_address_p
5016 
5017 #undef  TARGET_LEGITIMIZE_ADDRESS
5018 #define TARGET_LEGITIMIZE_ADDRESS tilepro_legitimize_address
5019 
5020 #undef  TARGET_DELEGITIMIZE_ADDRESS
5021 #define TARGET_DELEGITIMIZE_ADDRESS tilepro_delegitimize_address
5022 
5023 #undef  TARGET_INIT_BUILTINS
5024 #define TARGET_INIT_BUILTINS  tilepro_init_builtins
5025 
5026 #undef  TARGET_BUILTIN_DECL
5027 #define TARGET_BUILTIN_DECL tilepro_builtin_decl
5028 
5029 #undef  TARGET_EXPAND_BUILTIN
5030 #define TARGET_EXPAND_BUILTIN tilepro_expand_builtin
5031 
5032 #undef  TARGET_CONDITIONAL_REGISTER_USAGE
5033 #define TARGET_CONDITIONAL_REGISTER_USAGE tilepro_conditional_register_usage
5034 
5035 #undef  TARGET_FRAME_POINTER_REQUIRED
5036 #define TARGET_FRAME_POINTER_REQUIRED tilepro_frame_pointer_required
5037 
5038 #undef  TARGET_DELAY_SCHED2
5039 #define TARGET_DELAY_SCHED2 true
5040 
5041 #undef  TARGET_DELAY_VARTRACK
5042 #define TARGET_DELAY_VARTRACK true
5043 
5044 #undef  TARGET_SCHED_ISSUE_RATE
5045 #define TARGET_SCHED_ISSUE_RATE tilepro_issue_rate
5046 
5047 #undef  TARGET_SCHED_ADJUST_COST
5048 #define TARGET_SCHED_ADJUST_COST tilepro_sched_adjust_cost
5049 
5050 #undef  TARGET_MACHINE_DEPENDENT_REORG
5051 #define TARGET_MACHINE_DEPENDENT_REORG tilepro_reorg
5052 
5053 #undef  TARGET_ASM_CAN_OUTPUT_MI_THUNK
5054 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK \
5055   hook_bool_const_tree_hwi_hwi_const_tree_true
5056 
5057 #undef  TARGET_ASM_OUTPUT_MI_THUNK
5058 #define TARGET_ASM_OUTPUT_MI_THUNK tilepro_asm_output_mi_thunk
5059 
5060 #undef  TARGET_ASM_TRAMPOLINE_TEMPLATE
5061 #define TARGET_ASM_TRAMPOLINE_TEMPLATE tilepro_asm_trampoline_template
5062 
5063 #undef  TARGET_TRAMPOLINE_INIT
5064 #define TARGET_TRAMPOLINE_INIT tilepro_trampoline_init
5065 
5066 #undef  TARGET_PRINT_OPERAND
5067 #define TARGET_PRINT_OPERAND tilepro_print_operand
5068 
5069 #undef  TARGET_PRINT_OPERAND_ADDRESS
5070 #define TARGET_PRINT_OPERAND_ADDRESS tilepro_print_operand_address
5071 
5072 #undef  TARGET_ASM_FILE_END
5073 #define TARGET_ASM_FILE_END tilepro_file_end
5074 
5075 
5076 struct gcc_target targetm = TARGET_INITIALIZER;
5077 
5078 #include "gt-tilepro.h"
5079