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