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