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