1/* Subroutines used for code generation on the Tilera TILE-Gx.
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 "tm_p.h"
70#include "tm-constrs.h"
71#include "target.h"
72#include "target-def.h"
73#include "dwarf2.h"
74#include "timevar.h"
75#include "fold-const.h"
76#include "hash-table.h"
77#include "ggc.h"
78#include "tree-ssa-alias.h"
79#include "internal-fn.h"
80#include "gimple-fold.h"
81#include "tree-eh.h"
82#include "gimple-expr.h"
83#include "is-a.h"
84#include "gimple.h"
85#include "stringpool.h"
86#include "stor-layout.h"
87#include "gimplify.h"
88#include "cfgloop.h"
89#include "tilegx-builtins.h"
90#include "tilegx-multiply.h"
91#include "diagnostic.h"
92#include "builtins.h"
93
94/* SYMBOL_REF for GOT */
95static GTY(()) rtx g_got_symbol = NULL;
96
97/* In case of a POST_INC or POST_DEC memory reference, we must report
98   the mode of the memory reference from TARGET_PRINT_OPERAND to
99   TARGET_PRINT_OPERAND_ADDRESS.  */
100static machine_mode output_memory_reference_mode;
101
102/* Report whether we're printing out the first address fragment of a
103   POST_INC or POST_DEC memory reference, from TARGET_PRINT_OPERAND to
104   TARGET_PRINT_OPERAND_ADDRESS.  */
105static bool output_memory_autoinc_first;
106
107
108
109/* Option handling  */
110
111/* Implement TARGET_OPTION_OVERRIDE.  */
112static void
113tilegx_option_override (void)
114{
115  if (global_options_set.x_tilegx_cmodel)
116    {
117      switch (tilegx_cmodel)
118	{
119	case CM_SMALL:
120	case CM_SMALL_PIC:
121	  if (flag_pic)
122	    tilegx_cmodel = CM_SMALL_PIC;
123	  break;
124
125	case CM_LARGE:
126	case CM_LARGE_PIC:
127	  if (flag_pic)
128	    tilegx_cmodel = CM_LARGE_PIC;
129	  break;
130
131	default:
132	  gcc_unreachable ();
133	}
134    }
135  else
136    tilegx_cmodel = flag_pic ? CM_SMALL_PIC : CM_SMALL;
137
138  /* When modulo scheduling is enabled, we still rely on regular
139     scheduler for bundling.  */
140  if (flag_modulo_sched)
141    flag_resched_modulo_sched = 1;
142}
143
144
145
146/* Implement TARGET_SCALAR_MODE_SUPPORTED_P.  */
147static bool
148tilegx_scalar_mode_supported_p (machine_mode mode)
149{
150  switch (mode)
151    {
152    case QImode:
153    case HImode:
154    case SImode:
155    case DImode:
156    case TImode:
157      return true;
158
159    case SFmode:
160    case DFmode:
161      return true;
162
163    default:
164      return false;
165    }
166}
167
168
169/* Implement TARGET_VECTOR_MODE_SUPPORTED_P.  */
170static bool
171tilegx_vector_mode_supported_p (machine_mode mode)
172{
173  return mode == V8QImode || mode == V4HImode || mode == V2SImode;
174}
175
176
177/* Implement TARGET_CANNOT_FORCE_CONST_MEM.  */
178static bool
179tilegx_cannot_force_const_mem (machine_mode mode ATTRIBUTE_UNUSED,
180			       rtx x ATTRIBUTE_UNUSED)
181{
182  return true;
183}
184
185
186/* Implement TARGET_FUNCTION_OK_FOR_SIBCALL.  */
187static bool
188tilegx_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED)
189{
190  return (tilegx_cmodel != CM_LARGE && tilegx_cmodel != CM_LARGE_PIC
191	  && (decl != NULL));
192}
193
194
195/* Implement TARGET_PASS_BY_REFERENCE.  Variable sized types are
196   passed by reference.  */
197static bool
198tilegx_pass_by_reference (cumulative_args_t cum ATTRIBUTE_UNUSED,
199			  machine_mode mode ATTRIBUTE_UNUSED,
200			  const_tree type, bool named ATTRIBUTE_UNUSED)
201{
202  return (type && TYPE_SIZE (type)
203	  && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST);
204}
205
206
207/* Implement TARGET_RETURN_IN_MSB.  We return a value in the most
208   significant part of a register if:
209   - the target is big-endian; and
210   - the value has an aggregate type (e.g., structure or union).  */
211static bool
212tilegx_return_in_msb (const_tree valtype)
213{
214  return (TARGET_BIG_ENDIAN && AGGREGATE_TYPE_P (valtype));
215}
216
217
218/* Implement TARGET_RETURN_IN_MEMORY.  */
219static bool
220tilegx_return_in_memory (const_tree type, const_tree fndecl ATTRIBUTE_UNUSED)
221{
222  return !IN_RANGE (int_size_in_bytes (type),
223		    0, TILEGX_NUM_RETURN_REGS * UNITS_PER_WORD);
224}
225
226
227/* Implement TARGET_MODE_REP_EXTENDED.  */
228static int
229tilegx_mode_rep_extended (machine_mode mode, machine_mode mode_rep)
230{
231  /* SImode register values are sign-extended to DImode.  */
232  if (mode == SImode && mode_rep == DImode)
233    return SIGN_EXTEND;
234
235  return UNKNOWN;
236}
237
238
239/* Implement TARGET_FUNCTION_ARG_BOUNDARY.  */
240static unsigned int
241tilegx_function_arg_boundary (machine_mode mode, const_tree type)
242{
243  unsigned int alignment;
244
245  alignment = type ? TYPE_ALIGN (type) : GET_MODE_ALIGNMENT (mode);
246  if (alignment < PARM_BOUNDARY)
247    alignment = PARM_BOUNDARY;
248  if (alignment > STACK_BOUNDARY)
249    alignment = STACK_BOUNDARY;
250  return alignment;
251}
252
253
254/* Implement TARGET_FUNCTION_ARG.  */
255static rtx
256tilegx_function_arg (cumulative_args_t cum_v,
257		     machine_mode mode,
258		     const_tree type, bool named ATTRIBUTE_UNUSED)
259{
260  CUMULATIVE_ARGS cum = *get_cumulative_args (cum_v);
261  int byte_size = ((mode == BLKmode)
262		   ? int_size_in_bytes (type) : GET_MODE_SIZE (mode));
263  bool doubleword_aligned_p;
264
265  if (cum >= TILEGX_NUM_ARG_REGS)
266    return NULL_RTX;
267
268  /* See whether the argument has doubleword alignment.  */
269  doubleword_aligned_p =
270    tilegx_function_arg_boundary (mode, type) > BITS_PER_WORD;
271
272  if (doubleword_aligned_p)
273    cum += cum & 1;
274
275  /* The ABI does not allow parameters to be passed partially in reg
276     and partially in stack.  */
277  if ((cum + (byte_size + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
278      > TILEGX_NUM_ARG_REGS)
279    return NULL_RTX;
280
281  return gen_rtx_REG (mode, cum);
282}
283
284
285/* Implement TARGET_FUNCTION_ARG_ADVANCE.  */
286static void
287tilegx_function_arg_advance (cumulative_args_t cum_v,
288			     machine_mode mode,
289			     const_tree type, bool named ATTRIBUTE_UNUSED)
290{
291  CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
292
293  int byte_size = ((mode == BLKmode)
294		   ? int_size_in_bytes (type) : GET_MODE_SIZE (mode));
295  int word_size = (byte_size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
296  bool doubleword_aligned_p;
297
298  /* See whether the argument has doubleword alignment.  */
299  doubleword_aligned_p =
300    tilegx_function_arg_boundary (mode, type) > BITS_PER_WORD;
301
302  if (doubleword_aligned_p)
303    *cum += *cum & 1;
304
305  /* If the current argument does not fit in the pretend_args space,
306     skip over it.  */
307  if (*cum < TILEGX_NUM_ARG_REGS
308      && *cum + word_size > TILEGX_NUM_ARG_REGS)
309    *cum = TILEGX_NUM_ARG_REGS;
310
311  *cum += word_size;
312}
313
314
315/* Implement TARGET_FUNCTION_VALUE.  */
316static rtx
317tilegx_function_value (const_tree valtype, const_tree fn_decl_or_type,
318		       bool outgoing ATTRIBUTE_UNUSED)
319{
320  machine_mode mode;
321  int unsigned_p;
322
323  mode = TYPE_MODE (valtype);
324  unsigned_p = TYPE_UNSIGNED (valtype);
325
326  mode = promote_function_mode (valtype, mode, &unsigned_p,
327				fn_decl_or_type, 1);
328
329  return gen_rtx_REG (mode, 0);
330}
331
332
333/* Implement TARGET_LIBCALL_VALUE.  */
334static rtx
335tilegx_libcall_value (machine_mode mode,
336		       const_rtx fun ATTRIBUTE_UNUSED)
337{
338  return gen_rtx_REG (mode, 0);
339}
340
341
342/* Implement FUNCTION_VALUE_REGNO_P.  */
343static bool
344tilegx_function_value_regno_p (const unsigned int regno)
345{
346  return regno < TILEGX_NUM_RETURN_REGS;
347}
348
349
350/* Implement TARGET_BUILD_BUILTIN_VA_LIST.  */
351static tree
352tilegx_build_builtin_va_list (void)
353{
354  tree f_args, f_skip, record, type_decl;
355  bool owp;
356
357  record = lang_hooks.types.make_type (RECORD_TYPE);
358
359  type_decl = build_decl (BUILTINS_LOCATION, TYPE_DECL,
360			  get_identifier ("__va_list_tag"), record);
361
362  f_args = build_decl (BUILTINS_LOCATION, FIELD_DECL,
363		       get_identifier ("__args"), ptr_type_node);
364  f_skip = build_decl (BUILTINS_LOCATION, FIELD_DECL,
365		       get_identifier ("__skip"), ptr_type_node);
366
367  DECL_FIELD_CONTEXT (f_args) = record;
368
369  DECL_FIELD_CONTEXT (f_skip) = record;
370
371  TREE_CHAIN (record) = type_decl;
372  TYPE_NAME (record) = type_decl;
373  TYPE_FIELDS (record) = f_args;
374  TREE_CHAIN (f_args) = f_skip;
375
376  /* We know this is being padded and we want it too.  It is an
377     internal type so hide the warnings from the user.  */
378  owp = warn_padded;
379  warn_padded = false;
380
381  layout_type (record);
382
383  warn_padded = owp;
384
385  /* The correct type is an array type of one element.  */
386  return record;
387}
388
389
390/* Implement TARGET_EXPAND_BUILTIN_VA_START.  */
391static void
392tilegx_va_start (tree valist, rtx nextarg ATTRIBUTE_UNUSED)
393{
394  tree f_args, f_skip;
395  tree args, skip, t;
396
397  f_args = TYPE_FIELDS (TREE_TYPE (valist));
398  f_skip = TREE_CHAIN (f_args);
399
400  args =
401    build3 (COMPONENT_REF, TREE_TYPE (f_args), valist, f_args, NULL_TREE);
402  skip =
403    build3 (COMPONENT_REF, TREE_TYPE (f_skip), valist, f_skip, NULL_TREE);
404
405  /* Find the __args area.  */
406  t = make_tree (TREE_TYPE (args), virtual_incoming_args_rtx);
407  t = fold_build_pointer_plus_hwi (t,
408				   UNITS_PER_WORD *
409				   (crtl->args.info - TILEGX_NUM_ARG_REGS));
410
411  if (crtl->args.pretend_args_size > 0)
412    t = fold_build_pointer_plus_hwi (t, -STACK_POINTER_OFFSET);
413
414  t = build2 (MODIFY_EXPR, TREE_TYPE (args), args, t);
415  TREE_SIDE_EFFECTS (t) = 1;
416  expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
417
418  /* Find the __skip area.  */
419  t = make_tree (TREE_TYPE (skip), virtual_incoming_args_rtx);
420  t = fold_build_pointer_plus_hwi (t, -STACK_POINTER_OFFSET);
421  t = build2 (MODIFY_EXPR, TREE_TYPE (skip), skip, t);
422  TREE_SIDE_EFFECTS (t) = 1;
423  expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
424}
425
426
427/* Implement TARGET_SETUP_INCOMING_VARARGS.  */
428static void
429tilegx_setup_incoming_varargs (cumulative_args_t cum,
430			       machine_mode mode,
431			       tree type, int *pretend_args, int no_rtl)
432{
433  CUMULATIVE_ARGS local_cum = *get_cumulative_args (cum);
434  int first_reg;
435
436  /* The caller has advanced CUM up to, but not beyond, the last named
437     argument.  Advance a local copy of CUM past the last "real" named
438     argument, to find out how many registers are left over.  */
439  targetm.calls.function_arg_advance (pack_cumulative_args (&local_cum),
440				      mode, type, true);
441  first_reg = local_cum;
442
443  if (local_cum < TILEGX_NUM_ARG_REGS)
444    {
445      *pretend_args = UNITS_PER_WORD * (TILEGX_NUM_ARG_REGS - first_reg);
446
447      if (!no_rtl)
448	{
449	  alias_set_type set = get_varargs_alias_set ();
450	  rtx tmp =
451	    gen_rtx_MEM (BLKmode, plus_constant (Pmode,
452						 virtual_incoming_args_rtx,
453						 -STACK_POINTER_OFFSET -
454						 UNITS_PER_WORD *
455						 (TILEGX_NUM_ARG_REGS -
456						  first_reg)));
457	  MEM_NOTRAP_P (tmp) = 1;
458	  set_mem_alias_set (tmp, set);
459	  move_block_from_reg (first_reg, tmp,
460			       TILEGX_NUM_ARG_REGS - first_reg);
461	}
462    }
463  else
464    *pretend_args = 0;
465}
466
467
468/* Implement TARGET_GIMPLIFY_VA_ARG_EXPR.  Gimplify va_arg by updating
469   the va_list structure VALIST as required to retrieve an argument of
470   type TYPE, and returning that argument.
471
472   ret = va_arg(VALIST, TYPE);
473
474   generates code equivalent to:
475
476    paddedsize = (sizeof(TYPE) + 7) & -8;
477    if (  (VALIST.__args + paddedsize > VALIST.__skip)
478	& (VALIST.__args <= VALIST.__skip))
479      addr = VALIST.__skip + STACK_POINTER_OFFSET;
480    else
481      addr = VALIST.__args;
482    VALIST.__args = addr + paddedsize;
483    if (BYTES_BIG_ENDIAN)
484      ret = *(TYPE *)(addr + paddedsize - sizeof(TYPE));
485    else
486      ret = *(TYPE *)addr;
487 */
488static tree
489tilegx_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p,
490			     gimple_seq *post_p ATTRIBUTE_UNUSED)
491{
492  tree f_args, f_skip;
493  tree args, skip;
494  HOST_WIDE_INT size, rsize;
495  tree addr, tmp;
496  bool pass_by_reference_p;
497
498  f_args = TYPE_FIELDS (va_list_type_node);
499  f_skip = TREE_CHAIN (f_args);
500
501  args =
502    build3 (COMPONENT_REF, TREE_TYPE (f_args), valist, f_args, NULL_TREE);
503  skip =
504    build3 (COMPONENT_REF, TREE_TYPE (f_skip), valist, f_skip, NULL_TREE);
505
506  addr = create_tmp_var (ptr_type_node, "va_arg");
507
508  /* If an object is dynamically sized, a pointer to it is passed
509     instead of the object itself.  */
510  pass_by_reference_p = pass_by_reference (NULL, TYPE_MODE (type), type,
511					   false);
512
513  if (pass_by_reference_p)
514    type = build_pointer_type (type);
515
516  size = int_size_in_bytes (type);
517  rsize = ((size + UNITS_PER_WORD - 1) / UNITS_PER_WORD) * UNITS_PER_WORD;
518
519  /* If the alignment of the type is greater than the default for a
520     parameter, align to the STACK_BOUNDARY. */
521  if (TYPE_ALIGN (type) > PARM_BOUNDARY)
522    {
523      /* Assert the only case we generate code for: when
524	 stack boundary = 2 * parm boundary. */
525      gcc_assert (STACK_BOUNDARY == PARM_BOUNDARY * 2);
526
527      tmp = build2 (BIT_AND_EXPR, sizetype,
528		    fold_convert (sizetype, unshare_expr (args)),
529		    size_int (PARM_BOUNDARY / 8));
530      tmp = build2 (POINTER_PLUS_EXPR, ptr_type_node,
531		    unshare_expr (args), tmp);
532
533      gimplify_assign (unshare_expr (args), tmp, pre_p);
534    }
535
536  /* Build conditional expression to calculate addr. The expression
537     will be gimplified later.  */
538  tmp = fold_build_pointer_plus_hwi (unshare_expr (args), rsize);
539  tmp = build2 (TRUTH_AND_EXPR, boolean_type_node,
540		build2 (GT_EXPR, boolean_type_node, tmp, unshare_expr (skip)),
541		build2 (LE_EXPR, boolean_type_node, unshare_expr (args),
542			unshare_expr (skip)));
543
544  tmp = build3 (COND_EXPR, ptr_type_node, tmp,
545		build2 (POINTER_PLUS_EXPR, ptr_type_node, unshare_expr (skip),
546			size_int (STACK_POINTER_OFFSET)),
547		unshare_expr (args));
548
549  /* Adjust the address of va_arg if it is in big endian mode.  */
550  if (BYTES_BIG_ENDIAN && rsize > size)
551    tmp = fold_build_pointer_plus_hwi (tmp, rsize - size);
552  gimplify_assign (addr, tmp, pre_p);
553
554  /* Update VALIST.__args.  */
555
556  if (BYTES_BIG_ENDIAN && rsize > size)
557    tmp = fold_build_pointer_plus_hwi (addr, size);
558  else
559    tmp = fold_build_pointer_plus_hwi (addr, rsize);
560  gimplify_assign (unshare_expr (args), tmp, pre_p);
561
562  addr = fold_convert (build_pointer_type (type), addr);
563
564  if (pass_by_reference_p)
565    addr = build_va_arg_indirect_ref (addr);
566
567  return build_va_arg_indirect_ref (addr);
568}
569
570
571
572/* Implement TARGET_RTX_COSTS.  */
573static bool
574tilegx_rtx_costs (rtx x, int code, int outer_code, int opno, int *total,
575		  bool speed)
576{
577  switch (code)
578    {
579    case CONST_INT:
580      /* If this is an 8-bit constant, return zero since it can be
581	 used nearly anywhere with no cost.  If it is a valid operand
582	 for an ADD or AND, likewise return 0 if we know it will be
583	 used in that context.  Otherwise, return 2 since it might be
584	 used there later.  All other constants take at least two
585	 insns.  */
586      if (satisfies_constraint_I (x))
587	{
588	  *total = 0;
589	  return true;
590	}
591      else if (outer_code == PLUS && add_operand (x, VOIDmode))
592	{
593	  /* Slightly penalize large constants even though we can add
594	     them in one instruction, because it forces the use of
595	     2-wide bundling mode.  */
596	  *total = 1;
597	  return true;
598	}
599      else if (move_operand (x, SImode))
600	{
601	  /* We can materialize in one move.  */
602	  *total = COSTS_N_INSNS (1);
603	  return true;
604	}
605      else
606	{
607	  /* We can materialize in two moves.  */
608	  *total = COSTS_N_INSNS (2);
609	  return true;
610	}
611
612      return false;
613
614    case CONST:
615    case LABEL_REF:
616    case SYMBOL_REF:
617      *total = COSTS_N_INSNS (2);
618      return true;
619
620    case CONST_DOUBLE:
621      *total = COSTS_N_INSNS (4);
622      return true;
623
624    case HIGH:
625      *total = 0;
626      return true;
627
628    case MEM:
629      /* If outer-code was a sign or zero extension, a cost of
630	 COSTS_N_INSNS (1) was already added in, so account for
631	 that.  */
632      if (outer_code == ZERO_EXTEND || outer_code == SIGN_EXTEND)
633	*total = COSTS_N_INSNS (1);
634      else
635	*total = COSTS_N_INSNS (2);
636      return true;
637
638    case PLUS:
639      /* Convey that shl[123]add are efficient.  */
640      if (GET_CODE (XEXP (x, 0)) == MULT
641	  && cint_248_operand (XEXP (XEXP (x, 0), 1), VOIDmode))
642	{
643	  *total = (rtx_cost (XEXP (XEXP (x, 0), 0),
644			      (enum rtx_code) outer_code, opno, speed)
645		    + rtx_cost (XEXP (x, 1),
646				(enum rtx_code) outer_code, opno, speed)
647		    + COSTS_N_INSNS (1));
648	  return true;
649	}
650      return false;
651
652    case MULT:
653      *total = COSTS_N_INSNS (2);
654      return false;
655
656    case DIV:
657    case UDIV:
658    case MOD:
659    case UMOD:
660      /* These are handled by software and are very expensive.  */
661      *total = COSTS_N_INSNS (100);
662      return false;
663
664    case UNSPEC:
665    case UNSPEC_VOLATILE:
666      {
667	int num = XINT (x, 1);
668
669	if (num <= TILEGX_LAST_LATENCY_1_INSN)
670	  *total = COSTS_N_INSNS (1);
671	else if (num <= TILEGX_LAST_LATENCY_2_INSN)
672	  *total = COSTS_N_INSNS (2);
673	else if (num > TILEGX_LAST_LATENCY_INSN)
674	  {
675	    if (num == UNSPEC_NON_TEMPORAL)
676	      {
677		/* These are basically loads.  */
678		if (outer_code == ZERO_EXTEND || outer_code == SIGN_EXTEND)
679		  *total = COSTS_N_INSNS (1);
680		else
681		  *total = COSTS_N_INSNS (2);
682	      }
683	    else
684	      {
685		if (outer_code == PLUS)
686		  *total = 0;
687		else
688		  *total = COSTS_N_INSNS (1);
689	      }
690	  }
691	else
692	  {
693	    switch (num)
694	      {
695	      case UNSPEC_BLOCKAGE:
696	      case UNSPEC_NETWORK_BARRIER:
697	      case UNSPEC_ATOMIC:
698		*total = 0;
699		break;
700
701	      case UNSPEC_LNK_AND_LABEL:
702	      case UNSPEC_MF:
703	      case UNSPEC_MOV_PCREL_STEP3:
704	      case UNSPEC_NETWORK_RECEIVE:
705	      case UNSPEC_NETWORK_SEND:
706	      case UNSPEC_SPR_MOVE:
707	      case UNSPEC_TLS_GD_ADD:
708		*total = COSTS_N_INSNS (1);
709		break;
710
711	      case UNSPEC_TLS_IE_LOAD:
712	      case UNSPEC_XCHG:
713		*total = COSTS_N_INSNS (2);
714		break;
715
716	      case UNSPEC_SP_SET:
717		*total = COSTS_N_INSNS (3);
718		break;
719
720	      case UNSPEC_SP_TEST:
721		*total = COSTS_N_INSNS (4);
722		break;
723
724	      case UNSPEC_CMPXCHG:
725	      case UNSPEC_INSN_CMPEXCH:
726	      case UNSPEC_LATENCY_L2:
727		*total = COSTS_N_INSNS (11);
728		break;
729
730	      case UNSPEC_TLS_GD_CALL:
731		*total = COSTS_N_INSNS (30);
732		break;
733
734	      case UNSPEC_LATENCY_MISS:
735		*total = COSTS_N_INSNS (80);
736		break;
737
738	      default:
739		*total = COSTS_N_INSNS (1);
740	      }
741	  }
742	return true;
743      }
744
745    default:
746      return false;
747    }
748}
749
750
751
752/* Rtl lowering.  */
753
754/* Create a temporary variable to hold a partial result, to enable
755   CSE.  */
756static rtx
757create_temp_reg_if_possible (machine_mode mode, rtx default_reg)
758{
759  return can_create_pseudo_p () ? gen_reg_rtx (mode) : default_reg;
760}
761
762
763/* Functions to save and restore machine-specific function data.  */
764static struct machine_function *
765tilegx_init_machine_status (void)
766{
767  return ggc_cleared_alloc<machine_function> ();
768}
769
770
771/* Do anything needed before RTL is emitted for each function.  */
772void
773tilegx_init_expanders (void)
774{
775  /* Arrange to initialize and mark the machine per-function
776     status.  */
777  init_machine_status = tilegx_init_machine_status;
778
779  if (cfun && cfun->machine && flag_pic)
780    {
781      static int label_num = 0;
782
783      char text_label_name[32];
784
785      struct machine_function *machine = cfun->machine;
786
787      ASM_GENERATE_INTERNAL_LABEL (text_label_name, "L_PICLNK", label_num++);
788
789      machine->text_label_symbol =
790	gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (text_label_name));
791
792      machine->text_label_rtx =
793	gen_rtx_REG (Pmode, TILEGX_PIC_TEXT_LABEL_REGNUM);
794
795      machine->got_rtx = gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM);
796
797      machine->calls_tls_get_addr = false;
798    }
799}
800
801
802/* Implement TARGET_EXPAND_TO_RTL_HOOK.  */
803static void
804tilegx_expand_to_rtl_hook (void)
805{
806  /* Exclude earlier sets of crtl->uses_pic_offset_table, because we
807     only care about uses actually emitted.  */
808  crtl->uses_pic_offset_table = 0;
809}
810
811
812/* Implement TARGET_SHIFT_TRUNCATION_MASK.  DImode shifts use the mode
813   matching insns and therefore guarantee that the shift count is
814   modulo 64.  SImode shifts sometimes use the 64 bit version so do
815   not hold such guarantee.  */
816static unsigned HOST_WIDE_INT
817tilegx_shift_truncation_mask (machine_mode mode)
818{
819  return mode == DImode ? 63 : 0;
820}
821
822
823/* Implement TARGET_INIT_LIBFUNCS.  */
824static void
825tilegx_init_libfuncs (void)
826{
827  /* We need to explicitly generate these libfunc's to support
828     conversion of divide by constant to multiply (the divide stubs in
829     tilegx.md exist also for this reason).  Normally we'd expect gcc
830     to lazily generate them when they are needed, but for some reason
831     it's set up to only generate them if the mode is the word
832     mode.  */
833  set_optab_libfunc (sdiv_optab, SImode, "__divsi3");
834  set_optab_libfunc (udiv_optab, SImode, "__udivsi3");
835  set_optab_libfunc (smod_optab, SImode, "__modsi3");
836  set_optab_libfunc (umod_optab, SImode, "__umodsi3");
837}
838
839
840/* Return true if X contains a thread-local symbol.  */
841static bool
842tilegx_tls_referenced_p (rtx x)
843{
844  if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == PLUS)
845    x = XEXP (XEXP (x, 0), 0);
846
847  if (GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (x))
848    return true;
849
850  /* That's all we handle in tilegx_legitimize_tls_address for
851     now.  */
852  return false;
853}
854
855
856/* Return true if X requires a scratch register.  It is given that
857   flag_pic is on and that X satisfies CONSTANT_P.  */
858static int
859tilegx_pic_address_needs_scratch (rtx x)
860{
861  if (GET_CODE (x) == CONST
862      && GET_CODE (XEXP (x, 0)) == PLUS
863      && (GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF
864	  || GET_CODE (XEXP (XEXP (x, 0), 0)) == LABEL_REF)
865      && (CONST_INT_P (XEXP (XEXP (x, 0), 1))))
866    return true;
867
868  return false;
869}
870
871
872/* Implement TARGET_LEGITIMATE_CONSTANT_P.  This is all constants for
873   which we are willing to load the value into a register via a move
874   pattern.  TLS cannot be treated as a constant because it can
875   include a function call.  */
876static bool
877tilegx_legitimate_constant_p (machine_mode mode ATTRIBUTE_UNUSED, rtx x)
878{
879  switch (GET_CODE (x))
880    {
881    case CONST:
882    case SYMBOL_REF:
883      return !tilegx_tls_referenced_p (x);
884
885    default:
886      return true;
887    }
888}
889
890
891/* Return true if the constant value X is a legitimate general operand
892   when generating PIC code.  It is given that flag_pic is on and that
893   X satisfies CONSTANT_P.  */
894bool
895tilegx_legitimate_pic_operand_p (rtx x)
896{
897  if (tilegx_pic_address_needs_scratch (x))
898    return false;
899
900  if (tilegx_tls_referenced_p (x))
901    return false;
902
903  return true;
904}
905
906
907/* Return true if the rtx X can be used as an address operand.  */
908static bool
909tilegx_legitimate_address_p (machine_mode ARG_UNUSED (mode), rtx x,
910			     bool strict)
911{
912  if (GET_CODE (x) == SUBREG)
913    x = SUBREG_REG (x);
914
915  switch (GET_CODE (x))
916    {
917    case POST_INC:
918    case POST_DEC:
919      if (GET_MODE_SIZE (GET_MODE (x)) > UNITS_PER_WORD)
920	return false;
921
922      x = XEXP (x, 0);
923      break;
924
925    case POST_MODIFY:
926      if (GET_MODE_SIZE (GET_MODE (x)) > UNITS_PER_WORD)
927	return false;
928
929      if (GET_CODE (XEXP (x, 1)) != PLUS)
930	return false;
931
932      if (!rtx_equal_p (XEXP (x, 0), XEXP (XEXP (x, 1), 0)))
933	return false;
934
935      if (!satisfies_constraint_I (XEXP (XEXP (x, 1), 1)))
936	return false;
937
938      x = XEXP (x, 0);
939      break;
940
941    case REG:
942      break;
943
944    default:
945      return false;
946    }
947
948  /* Check if x is a valid reg.  */
949  if (!REG_P (x))
950    return false;
951
952  if (strict)
953    return REGNO_OK_FOR_BASE_P (REGNO (x));
954  else
955    return true;
956}
957
958
959/* Return the rtx containing SYMBOL_REF to the text label.  */
960static rtx
961tilegx_text_label_symbol (void)
962{
963  return cfun->machine->text_label_symbol;
964}
965
966
967/* Return the register storing the value of the text label.  */
968static rtx
969tilegx_text_label_rtx (void)
970{
971  return cfun->machine->text_label_rtx;
972}
973
974
975/* Return the register storing the value of the global offset
976   table.  */
977static rtx
978tilegx_got_rtx (void)
979{
980  return cfun->machine->got_rtx;
981}
982
983
984/* Return the SYMBOL_REF for _GLOBAL_OFFSET_TABLE_.  */
985static rtx
986tilegx_got_symbol (void)
987{
988  if (g_got_symbol == NULL)
989    g_got_symbol = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");
990
991  return g_got_symbol;
992}
993
994
995/* Return a reference to the got to be used by tls references.  */
996static rtx
997tilegx_tls_got (void)
998{
999  rtx temp;
1000  if (flag_pic)
1001    {
1002      crtl->uses_pic_offset_table = 1;
1003      return tilegx_got_rtx ();
1004    }
1005
1006  temp = gen_reg_rtx (Pmode);
1007  emit_move_insn (temp, tilegx_got_symbol ());
1008
1009  return temp;
1010}
1011
1012
1013/* ADDR contains a thread-local SYMBOL_REF.  Generate code to compute
1014   this (thread-local) address.  */
1015static rtx
1016tilegx_legitimize_tls_address (rtx addr)
1017{
1018  rtx ret;
1019
1020  gcc_assert (can_create_pseudo_p ());
1021
1022  if (GET_CODE (addr) == SYMBOL_REF)
1023    switch (SYMBOL_REF_TLS_MODEL (addr))
1024      {
1025      case TLS_MODEL_GLOBAL_DYNAMIC:
1026      case TLS_MODEL_LOCAL_DYNAMIC:
1027	{
1028	  rtx r0, temp, temp2, temp3, got, last;
1029
1030	  ret = gen_reg_rtx (Pmode);
1031	  r0 = gen_rtx_REG (Pmode, 0);
1032	  temp = gen_reg_rtx (Pmode);
1033	  temp2 = gen_reg_rtx (Pmode);
1034	  temp3 = gen_reg_rtx (Pmode);
1035
1036	  got = tilegx_tls_got ();
1037	  if (TARGET_32BIT)
1038	    {
1039	      emit_insn (gen_mov_tls_gd_step1_32bit (temp, addr));
1040	      emit_insn (gen_mov_tls_gd_step2_32bit (temp2, temp, addr));
1041	      emit_insn (gen_tls_add_32bit (temp2, got, temp2, addr));
1042	    }
1043	  else
1044	    {
1045	      emit_insn (gen_mov_tls_gd_step1 (temp, addr));
1046	      emit_insn (gen_mov_tls_gd_step2 (temp2, temp, addr));
1047	      emit_insn (gen_tls_add (temp2, got, temp2, addr));
1048	    }
1049
1050	  emit_move_insn (r0, temp2);
1051
1052	  if (TARGET_32BIT)
1053	    {
1054	      emit_insn (gen_tls_gd_call_32bit (addr));
1055	    }
1056	  else
1057	    {
1058	      emit_insn (gen_tls_gd_call (addr));
1059	    }
1060
1061	  emit_move_insn (temp3, r0);
1062
1063	  if (TARGET_32BIT)
1064	    last = emit_insn (gen_tls_gd_add_32bit (ret, temp3, addr));
1065	  else
1066	    last = emit_insn (gen_tls_gd_add (ret, temp3, addr));
1067
1068	  set_unique_reg_note (last, REG_EQUAL, copy_rtx (addr));
1069	  break;
1070	}
1071      case TLS_MODEL_INITIAL_EXEC:
1072	{
1073	  rtx temp, temp2, temp3, got;
1074	  rtx_insn *last;
1075
1076	  ret = gen_reg_rtx (Pmode);
1077	  temp = gen_reg_rtx (Pmode);
1078	  temp2 = gen_reg_rtx (Pmode);
1079	  temp3 = gen_reg_rtx (Pmode);
1080
1081	  got = tilegx_tls_got ();
1082	  if (TARGET_32BIT)
1083	    {
1084	      emit_insn (gen_mov_tls_ie_step1_32bit (temp, addr));
1085	      emit_insn (gen_mov_tls_ie_step2_32bit (temp2, temp, addr));
1086	      emit_insn (gen_tls_add_32bit (temp2, got, temp2, addr));
1087	      emit_insn (gen_tls_ie_load_32bit (temp3, temp2, addr));
1088	    }
1089	  else
1090	    {
1091	      emit_insn (gen_mov_tls_ie_step1 (temp, addr));
1092	      emit_insn (gen_mov_tls_ie_step2 (temp2, temp, addr));
1093	      emit_insn (gen_tls_add (temp2, got, temp2, addr));
1094	      emit_insn (gen_tls_ie_load (temp3, temp2, addr));
1095	    }
1096
1097	  last =
1098	    emit_move_insn(ret,
1099			   gen_rtx_PLUS (Pmode,
1100					 gen_rtx_REG (Pmode,
1101						      THREAD_POINTER_REGNUM),
1102					 temp3));
1103	  set_unique_reg_note (last, REG_EQUAL, copy_rtx (addr));
1104	  break;
1105	}
1106      case TLS_MODEL_LOCAL_EXEC:
1107	{
1108	  rtx temp, temp2;
1109	  rtx_insn *last;
1110
1111	  ret = gen_reg_rtx (Pmode);
1112	  temp = gen_reg_rtx (Pmode);
1113	  temp2 = gen_reg_rtx (Pmode);
1114
1115	  if (TARGET_32BIT)
1116	    {
1117	      emit_insn (gen_mov_tls_le_step1_32bit (temp, addr));
1118	      emit_insn (gen_mov_tls_le_step2_32bit (temp2, temp, addr));
1119	    }
1120	  else
1121	    {
1122	      emit_insn (gen_mov_tls_le_step1 (temp, addr));
1123	      emit_insn (gen_mov_tls_le_step2 (temp2, temp, addr));
1124	    }
1125
1126	  last =
1127	    emit_move_insn (ret,
1128			    gen_rtx_PLUS (Pmode,
1129					  gen_rtx_REG (Pmode,
1130						       THREAD_POINTER_REGNUM),
1131					  temp2));
1132	  set_unique_reg_note (last, REG_EQUAL, copy_rtx (addr));
1133	  break;
1134	}
1135      default:
1136	gcc_unreachable ();
1137      }
1138  else if (GET_CODE (addr) == CONST)
1139    {
1140      rtx base, offset;
1141
1142      gcc_assert (GET_CODE (XEXP (addr, 0)) == PLUS);
1143
1144      base = tilegx_legitimize_tls_address (XEXP (XEXP (addr, 0), 0));
1145      offset = XEXP (XEXP (addr, 0), 1);
1146
1147      base = force_operand (base, NULL_RTX);
1148      ret = force_reg (Pmode, gen_rtx_PLUS (Pmode, base, offset));
1149    }
1150  else
1151    gcc_unreachable ();
1152
1153  return ret;
1154}
1155
1156
1157/* Returns a register that points to ADDR, a symbolic address, by
1158   computing its address relative to tilegx_text_label_symbol.  */
1159void
1160tilegx_compute_pcrel_address (rtx result, rtx addr)
1161{
1162  rtx text_label_symbol = tilegx_text_label_symbol ();
1163  rtx text_label_rtx = tilegx_text_label_rtx ();
1164  rtx temp, temp2, temp3;
1165
1166  temp = create_temp_reg_if_possible (Pmode, result);
1167  temp2 = create_temp_reg_if_possible (Pmode, result);
1168
1169  if (TARGET_32BIT)
1170    {
1171      emit_insn (gen_mov_pcrel_step1_32bit (temp, addr, text_label_symbol));
1172      emit_insn (gen_mov_pcrel_step2_32bit (temp2, temp, addr,
1173					    text_label_symbol));
1174      emit_insn (gen_mov_pcrel_step3_32bit (result, temp2,
1175					    text_label_rtx,
1176					    addr, text_label_symbol));
1177    }
1178  else if (tilegx_cmodel == CM_LARGE_PIC)
1179    {
1180      temp3 = create_temp_reg_if_possible (Pmode, result);
1181      emit_insn (gen_mov_large_pcrel_step1 (temp, addr, text_label_symbol));
1182      emit_insn (gen_mov_large_pcrel_step2 (temp2, temp, addr,
1183					    text_label_symbol));
1184      emit_insn (gen_mov_large_pcrel_step3 (temp3, temp2, addr,
1185					    text_label_symbol));
1186      emit_insn (gen_mov_large_pcrel_step4 (result, temp3,
1187					    text_label_rtx,
1188					    addr, text_label_symbol));
1189    }
1190  else
1191    {
1192      emit_insn (gen_mov_pcrel_step1 (temp, addr, text_label_symbol));
1193      emit_insn (gen_mov_pcrel_step2 (temp2, temp, addr, text_label_symbol));
1194      emit_insn (gen_mov_pcrel_step3 (result, temp2,
1195				      text_label_rtx,
1196				      addr, text_label_symbol));
1197    }
1198}
1199
1200
1201/* Returns a register that points to the plt entry of ADDR, a symbolic
1202   address, by computing its address relative to
1203   tilegx_text_label_symbol.  */
1204void
1205tilegx_compute_pcrel_plt_address (rtx result, rtx addr)
1206{
1207  rtx text_label_symbol = tilegx_text_label_symbol ();
1208  rtx text_label_rtx = tilegx_text_label_rtx ();
1209  rtx temp, temp2, temp3;
1210
1211  temp = create_temp_reg_if_possible (Pmode, result);
1212  temp2 = create_temp_reg_if_possible (Pmode, result);
1213
1214  if (TARGET_32BIT)
1215    {
1216      emit_insn (gen_mov_plt_pcrel_step1_32bit (temp, addr,
1217						text_label_symbol));
1218      emit_insn (gen_mov_plt_pcrel_step2_32bit (temp2, temp, addr,
1219						text_label_symbol));
1220      emit_move_insn (result, gen_rtx_PLUS (Pmode, temp2, text_label_rtx));
1221    }
1222  else
1223    {
1224      temp3 = create_temp_reg_if_possible (Pmode, result);
1225
1226      emit_insn (gen_mov_plt_pcrel_step1 (temp, addr, text_label_symbol));
1227      emit_insn (gen_mov_plt_pcrel_step2 (temp2, temp, addr,
1228					  text_label_symbol));
1229      emit_insn (gen_mov_plt_pcrel_step3 (temp3, temp2, addr,
1230					  text_label_symbol));
1231      emit_move_insn (result, gen_rtx_PLUS (Pmode, temp3, text_label_rtx));
1232    }
1233}
1234
1235
1236/* Legitimize PIC addresses.  If the address is already
1237   position-independent, we return ORIG.  Newly generated
1238   position-independent addresses go into a reg.  This is REG if
1239   nonzero, otherwise we allocate register(s) as necessary.  */
1240static rtx
1241tilegx_legitimize_pic_address (rtx orig,
1242			       machine_mode mode ATTRIBUTE_UNUSED,
1243			       rtx reg)
1244{
1245  if (GET_CODE (orig) == SYMBOL_REF)
1246    {
1247      rtx address, pic_ref;
1248
1249      if (reg == 0)
1250	{
1251	  gcc_assert (can_create_pseudo_p ());
1252	  reg = gen_reg_rtx (Pmode);
1253	}
1254
1255      if (SYMBOL_REF_LOCAL_P (orig))
1256	{
1257	  /* If not during reload, allocate another temp reg here for
1258	     loading in the address, so that these instructions can be
1259	     optimized properly.  */
1260	  rtx temp_reg = create_temp_reg_if_possible (Pmode, reg);
1261	  tilegx_compute_pcrel_address (temp_reg, orig);
1262
1263	  /* Note: this is conservative.  We use the text_label but we
1264	     don't use the pic_offset_table.  However, in some cases
1265	     we may need the pic_offset_table (see
1266	     tilegx_fixup_pcrel_references).  */
1267	  crtl->uses_pic_offset_table = 1;
1268
1269	  address = temp_reg;
1270
1271	  emit_move_insn (reg, address);
1272	  return reg;
1273	}
1274      else
1275	{
1276	  /* If not during reload, allocate another temp reg here for
1277	     loading in the address, so that these instructions can be
1278	     optimized properly.  */
1279	  rtx temp_reg = create_temp_reg_if_possible (Pmode, reg);
1280
1281	  gcc_assert (flag_pic);
1282	  if (flag_pic == 1)
1283	    {
1284	      if (TARGET_32BIT)
1285		{
1286		  emit_insn (gen_add_got16_32bit (temp_reg,
1287						  tilegx_got_rtx (),
1288						  orig));
1289		}
1290	      else
1291		{
1292		  emit_insn (gen_add_got16 (temp_reg,
1293					    tilegx_got_rtx (), orig));
1294		}
1295	    }
1296	  else
1297	    {
1298	      rtx temp_reg2 = create_temp_reg_if_possible (Pmode, reg);
1299	      rtx temp_reg3 = create_temp_reg_if_possible (Pmode, reg);
1300	      if (TARGET_32BIT)
1301		{
1302		  emit_insn (gen_mov_got32_step1_32bit (temp_reg3, orig));
1303		  emit_insn (gen_mov_got32_step2_32bit
1304			     (temp_reg2, temp_reg3, orig));
1305		}
1306	      else
1307		{
1308		  emit_insn (gen_mov_got32_step1 (temp_reg3, orig));
1309		  emit_insn (gen_mov_got32_step2 (temp_reg2, temp_reg3,
1310						  orig));
1311		}
1312	      emit_move_insn (temp_reg,
1313			      gen_rtx_PLUS (Pmode,
1314					    tilegx_got_rtx (), temp_reg2));
1315	    }
1316
1317	  address = temp_reg;
1318
1319	  pic_ref = gen_const_mem (Pmode, address);
1320	  crtl->uses_pic_offset_table = 1;
1321	  emit_move_insn (reg, pic_ref);
1322	  /* The following put a REG_EQUAL note on this insn, so that
1323	     it can be optimized by loop.  But it causes the label to
1324	     be optimized away.  */
1325	  /* set_unique_reg_note (insn, REG_EQUAL, orig); */
1326	  return reg;
1327	}
1328    }
1329  else if (GET_CODE (orig) == CONST)
1330    {
1331      rtx base, offset;
1332
1333      if (GET_CODE (XEXP (orig, 0)) == PLUS
1334	  && XEXP (XEXP (orig, 0), 0) == tilegx_got_rtx ())
1335	return orig;
1336
1337      if (reg == 0)
1338	{
1339	  gcc_assert (can_create_pseudo_p ());
1340	  reg = gen_reg_rtx (Pmode);
1341	}
1342
1343      gcc_assert (GET_CODE (XEXP (orig, 0)) == PLUS);
1344      base = tilegx_legitimize_pic_address (XEXP (XEXP (orig, 0), 0),
1345					    Pmode, reg);
1346      offset = tilegx_legitimize_pic_address (XEXP (XEXP (orig, 0), 1), Pmode,
1347					      base == reg ? 0 : reg);
1348
1349      if (CONST_INT_P (offset))
1350	{
1351	  if (can_create_pseudo_p ())
1352	    offset = force_reg (Pmode, offset);
1353	  else
1354	    /* If we reach here, then something is seriously wrong.  */
1355	    gcc_unreachable ();
1356	}
1357
1358      if (can_create_pseudo_p ())
1359	return force_reg (Pmode, gen_rtx_PLUS (Pmode, base, offset));
1360      else
1361	gcc_unreachable ();
1362    }
1363  else if (GET_CODE (orig) == LABEL_REF)
1364    {
1365      rtx address;
1366      rtx temp_reg;
1367
1368      if (reg == 0)
1369	{
1370	  gcc_assert (can_create_pseudo_p ());
1371	  reg = gen_reg_rtx (Pmode);
1372	}
1373
1374      /* If not during reload, allocate another temp reg here for
1375	 loading in the address, so that these instructions can be
1376	 optimized properly.  */
1377      temp_reg = create_temp_reg_if_possible (Pmode, reg);
1378      tilegx_compute_pcrel_address (temp_reg, orig);
1379
1380      /* Note: this is conservative.  We use the text_label but we
1381	 don't use the pic_offset_table.  */
1382      crtl->uses_pic_offset_table = 1;
1383
1384      address = temp_reg;
1385
1386      emit_move_insn (reg, address);
1387
1388      return reg;
1389    }
1390
1391  return orig;
1392}
1393
1394
1395/* Implement TARGET_LEGITIMIZE_ADDRESS.  */
1396static rtx
1397tilegx_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
1398			   machine_mode mode)
1399{
1400  if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD
1401      && symbolic_operand (x, Pmode) && tilegx_tls_referenced_p (x))
1402    {
1403      return tilegx_legitimize_tls_address (x);
1404    }
1405  else if (flag_pic)
1406    {
1407      return tilegx_legitimize_pic_address (x, mode, 0);
1408    }
1409  else
1410    return x;
1411}
1412
1413
1414/* Implement TARGET_DELEGITIMIZE_ADDRESS.  */
1415static rtx
1416tilegx_delegitimize_address (rtx x)
1417{
1418  x = delegitimize_mem_from_attrs (x);
1419
1420  if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == UNSPEC)
1421    {
1422      switch (XINT (XEXP (x, 0), 1))
1423	{
1424	  case UNSPEC_HW0:
1425	  case UNSPEC_HW1:
1426	  case UNSPEC_HW2:
1427	  case UNSPEC_HW3:
1428	  case UNSPEC_HW0_LAST:
1429	  case UNSPEC_HW1_LAST:
1430	  case UNSPEC_HW2_LAST:
1431	  case UNSPEC_HW0_PCREL:
1432	  case UNSPEC_HW1_PCREL:
1433	  case UNSPEC_HW1_LAST_PCREL:
1434	  case UNSPEC_HW2_LAST_PCREL:
1435	  case UNSPEC_HW0_PLT_PCREL:
1436	  case UNSPEC_HW1_PLT_PCREL:
1437	  case UNSPEC_HW1_LAST_PLT_PCREL:
1438	  case UNSPEC_HW2_LAST_PLT_PCREL:
1439	  case UNSPEC_HW0_GOT:
1440	  case UNSPEC_HW0_LAST_GOT:
1441  	  case UNSPEC_HW1_LAST_GOT:
1442  	  case UNSPEC_HW0_TLS_GD:
1443  	  case UNSPEC_HW1_LAST_TLS_GD:
1444  	  case UNSPEC_HW0_TLS_IE:
1445  	  case UNSPEC_HW1_LAST_TLS_IE:
1446  	  case UNSPEC_HW0_TLS_LE:
1447  	  case UNSPEC_HW1_LAST_TLS_LE:
1448	    x = XVECEXP (XEXP (x, 0), 0, 0);
1449	  break;
1450	}
1451    }
1452
1453  return x;
1454}
1455
1456
1457/* Emit code to load the PIC register.  */
1458static void
1459load_pic_register (bool delay_pic_helper ATTRIBUTE_UNUSED)
1460{
1461  int orig_flag_pic = flag_pic;
1462
1463  rtx got_symbol = tilegx_got_symbol ();
1464  rtx text_label_symbol = tilegx_text_label_symbol ();
1465  rtx text_label_rtx = tilegx_text_label_rtx ();
1466  flag_pic = 0;
1467
1468  if (TARGET_32BIT)
1469    {
1470      emit_insn (gen_insn_lnk_and_label_32bit (text_label_rtx,
1471					       text_label_symbol));
1472    }
1473  else
1474    {
1475      emit_insn (gen_insn_lnk_and_label (text_label_rtx, text_label_symbol));
1476    }
1477
1478  tilegx_compute_pcrel_address (tilegx_got_rtx (), got_symbol);
1479
1480  flag_pic = orig_flag_pic;
1481
1482  /* Need to emit this whether or not we obey regdecls, since
1483     setjmp/longjmp can cause life info to screw up.  ??? In the case
1484     where we don't obey regdecls, this is not sufficient since we may
1485     not fall out the bottom.  */
1486  emit_use (tilegx_got_rtx ());
1487}
1488
1489
1490/* Return the simd variant of the constant NUM of mode MODE, by
1491   replicating it to fill an interger of mode DImode.  NUM is first
1492   truncated to fit in MODE.  */
1493rtx
1494tilegx_simd_int (rtx num, machine_mode mode)
1495{
1496  HOST_WIDE_INT n = 0;
1497
1498  gcc_assert (CONST_INT_P (num));
1499
1500  n = INTVAL (num);
1501
1502  switch (mode)
1503    {
1504    case QImode:
1505      n = 0x0101010101010101LL * (n & 0x000000FF);
1506      break;
1507    case HImode:
1508      n = 0x0001000100010001LL * (n & 0x0000FFFF);
1509      break;
1510    case SImode:
1511      n = 0x0000000100000001LL * (n & 0xFFFFFFFF);
1512      break;
1513    case DImode:
1514      break;
1515    default:
1516      gcc_unreachable ();
1517    }
1518
1519  return GEN_INT (n);
1520}
1521
1522
1523/* Returns true iff VAL can be moved into a register in one
1524   instruction.  And if it can, it emits the code to move the constant
1525   into DEST_REG.
1526
1527   If THREE_WIDE_ONLY is true, this insists on an instruction that
1528   works in a bundle containing three instructions.  */
1529static bool
1530expand_set_cint64_one_inst (rtx dest_reg,
1531			    HOST_WIDE_INT val, bool three_wide_only)
1532{
1533  if (val == trunc_int_for_mode (val, QImode))
1534    {
1535      /* Success! */
1536      emit_move_insn (dest_reg, GEN_INT (val));
1537      return true;
1538    }
1539  else if (!three_wide_only)
1540    {
1541      /* Test for the following constraints: J, K, N, P.  We avoid
1542	 generating an rtx and using existing predicates because we
1543	 can be testing and rejecting a lot of constants, and GEN_INT
1544	 is O(N).  */
1545      if ((val >= -32768 && val <= 65535)
1546	  || ((val == (val & 0xFF) * 0x0101010101010101LL))
1547	  || (val == ((trunc_int_for_mode (val, QImode) & 0xFFFF)
1548		      * 0x0001000100010001LL)))
1549	{
1550	  emit_move_insn (dest_reg, GEN_INT (val));
1551	  return true;
1552	}
1553    }
1554
1555  return false;
1556}
1557
1558
1559/* Implement DImode rotatert.  */
1560static HOST_WIDE_INT
1561rotate_right (HOST_WIDE_INT n, int count)
1562{
1563  unsigned HOST_WIDE_INT x = n & 0xFFFFFFFFFFFFFFFFULL;
1564  if (count == 0)
1565    return x;
1566  return ((x >> count) | (x << (64 - count))) & 0xFFFFFFFFFFFFFFFFULL;
1567}
1568
1569
1570/* Return true iff n contains exactly one contiguous sequence of 1
1571   bits, possibly wrapping around from high bits to low bits.  */
1572bool
1573tilegx_bitfield_operand_p (HOST_WIDE_INT n, int *first_bit, int *last_bit)
1574{
1575  int i;
1576
1577  if (n == 0)
1578    return false;
1579
1580  for (i = 0; i < 64; i++)
1581    {
1582      unsigned HOST_WIDE_INT x = rotate_right (n, i);
1583      if (!(x & 1))
1584	continue;
1585
1586      /* See if x is a power of two minus one, i.e. only consecutive 1
1587	 bits starting from bit 0.  */
1588      if ((x & (x + 1)) == 0)
1589	{
1590	  if (first_bit != NULL)
1591	    *first_bit = i;
1592	  if (last_bit != NULL)
1593	    *last_bit = (i + exact_log2 (x ^ (x >> 1))) & 63;
1594
1595	  return true;
1596	}
1597    }
1598
1599  return false;
1600}
1601
1602
1603/* Create code to move the CONST_INT value in src_val to dest_reg.  */
1604static void
1605expand_set_cint64 (rtx dest_reg, rtx src_val)
1606{
1607  HOST_WIDE_INT val;
1608  int leading_zeroes, trailing_zeroes;
1609  int three_wide_only;
1610  int shift, ins_shift, zero_cluster_shift;
1611  rtx temp, subreg;
1612
1613  gcc_assert (CONST_INT_P (src_val));
1614  val = trunc_int_for_mode (INTVAL (src_val), GET_MODE (dest_reg));
1615
1616  /* See if we can generate the constant in one instruction.  */
1617  if (expand_set_cint64_one_inst (dest_reg, val, false))
1618    return;
1619
1620  /* Force the destination to DImode so we can use DImode instructions
1621     to create it.  This both allows instructions like rotl, and
1622     certain efficient 3-wide instructions.  */
1623  subreg = simplify_gen_subreg (DImode, dest_reg, GET_MODE (dest_reg), 0);
1624  gcc_assert (subreg != NULL);
1625  dest_reg = subreg;
1626
1627  temp = create_temp_reg_if_possible (DImode, dest_reg);
1628
1629  leading_zeroes = 63 - floor_log2 (val & 0xFFFFFFFFFFFFFFFFULL);
1630  trailing_zeroes = exact_log2 (val & -val);
1631
1632  /* First try all three-wide instructions that generate a constant
1633     (i.e. movei) followed by various shifts and rotates. If none of
1634     those work, try various two-wide ways of generating a constant
1635     followed by various shifts and rotates.  */
1636  for (three_wide_only = 1; three_wide_only >= 0; three_wide_only--)
1637    {
1638      int count;
1639
1640      if (expand_set_cint64_one_inst (temp, val >> trailing_zeroes,
1641				      three_wide_only))
1642	{
1643	  /* 0xFFFFFFFFFFFFA500 becomes:
1644	     movei temp, 0xFFFFFFFFFFFFFFA5
1645	     shli dest, temp, 8  */
1646	  emit_move_insn (dest_reg,
1647			  gen_rtx_ASHIFT (DImode, temp,
1648					  GEN_INT (trailing_zeroes)));
1649	  return;
1650	}
1651
1652      if (expand_set_cint64_one_inst (temp, val << leading_zeroes,
1653				      three_wide_only))
1654	{
1655	  /* 0x7FFFFFFFFFFFFFFF becomes:
1656	     movei temp, -2
1657	     shrui dest, temp, 1  */
1658	  emit_move_insn (dest_reg,
1659			  gen_rtx_LSHIFTRT (DImode, temp,
1660					    GEN_INT (leading_zeroes)));
1661	  return;
1662	}
1663
1664      /* Try rotating a one-instruction immediate.  */
1665      for (count = 1; count < 64; count++)
1666	{
1667	  HOST_WIDE_INT r = rotate_right (val, count);
1668	  if (expand_set_cint64_one_inst (temp, r, three_wide_only))
1669	    {
1670	      /* 0xFFFFFFFFFFA5FFFF becomes:
1671		 movei temp, 0xFFFFFFFFFFFFFFA5
1672		 rotli dest, temp, 16  */
1673	      emit_move_insn (dest_reg,
1674			      gen_rtx_ROTATE (DImode, temp, GEN_INT (count)));
1675	      return;
1676	    }
1677	}
1678    }
1679
1680  /* There are two cases here to produce a large constant.
1681     In the most general case, we do this:
1682
1683     moveli x, hw3(NUM)
1684     shl16insli x, x, hw2(NUM)
1685     shl16insli x, x, hw1(NUM)
1686     shl16insli x, x, hw0(NUM)
1687
1688     However, we can sometimes do better.  shl16insli is a poor way to
1689     insert 16 zero bits, because simply shifting left by 16 has more
1690     bundling freedom.  So if we see any contiguous aligned sequence
1691     of 16 or more zero bits (below the highest set bit), it is always
1692     more efficient to materialize the bits above the zero bits, then
1693     left shift to put in the zeroes, then insert whatever bits
1694     remain.  For example, we might end up with:
1695
1696     movei x, NUM >> (37 + 16)
1697     shli x, x, 37
1698     shl16insli x, x, hw0(NUM)      */
1699
1700  zero_cluster_shift = -1;
1701
1702  for (shift = 0; shift < 48 - leading_zeroes; shift += 16)
1703    {
1704      HOST_WIDE_INT x = val >> shift;
1705
1706      /* Find the least significant group of 16 aligned zero bits.  */
1707      if ((x & 0xFFFF) == 0x0000)
1708	{
1709	  /* Grab any following zero bits as well.  */
1710	  zero_cluster_shift = exact_log2 (x & -x);
1711	  shift += zero_cluster_shift;
1712	  break;
1713	}
1714    }
1715
1716  if (zero_cluster_shift >= 0)
1717    {
1718      unsigned HOST_WIDE_INT leftover;
1719
1720      /* Recursively create the constant above the lowest 16 zero
1721	 bits.  */
1722      expand_set_cint64 (temp, GEN_INT (val >> shift));
1723
1724      /* See if we can easily insert the remaining bits, or if we need
1725	 to fall through to the more general case.  */
1726      leftover = val - ((val >> shift) << shift);
1727      if (leftover == 0)
1728	{
1729	  /* A simple left shift is enough.  */
1730	  emit_move_insn (dest_reg,
1731			  gen_rtx_ASHIFT (DImode, temp, GEN_INT (shift)));
1732	  return;
1733	}
1734      else if (leftover <= 32767)
1735	{
1736	  /* Left shift into position then add in the leftover.  */
1737	  rtx temp2 = create_temp_reg_if_possible (DImode, temp);
1738	  emit_move_insn (temp2,
1739			  gen_rtx_ASHIFT (DImode, temp, GEN_INT (shift)));
1740	  emit_move_insn (dest_reg,
1741			  gen_rtx_PLUS (DImode, temp2, GEN_INT (leftover)));
1742	  return;
1743	}
1744      else
1745	{
1746	  /* Shift in the batch of >= 16 zeroes we detected earlier.
1747	     After this, shift will be aligned mod 16 so the final
1748	     loop can use shl16insli.  */
1749	  rtx temp2 = create_temp_reg_if_possible (DImode, temp);
1750	  rtx shift_count_rtx = GEN_INT (zero_cluster_shift);
1751
1752	  emit_move_insn (temp2,
1753			  gen_rtx_ASHIFT (DImode, temp, shift_count_rtx));
1754
1755	  shift -= zero_cluster_shift;
1756	  temp = temp2;
1757	}
1758    }
1759  else
1760    {
1761      /* Set as many high 16-bit blocks as we can with a single
1762	 instruction.  We'll insert the remaining 16-bit blocks
1763	 below.  */
1764      for (shift = 16;; shift += 16)
1765	{
1766	  gcc_assert (shift < 64);
1767	  if (expand_set_cint64_one_inst (temp, val >> shift, false))
1768	    break;
1769	}
1770    }
1771
1772  /* At this point, temp == val >> shift, shift % 16 == 0, and we
1773     still need to insert any bits of 'val' below 'shift'. Those bits
1774     are guaranteed to not have 16 contiguous zeroes.  */
1775
1776  gcc_assert ((shift & 15) == 0);
1777
1778  for (ins_shift = shift - 16; ins_shift >= 0; ins_shift -= 16)
1779    {
1780      rtx result;
1781      HOST_WIDE_INT bits = (val >> ins_shift) & 0xFFFF;
1782      gcc_assert (bits != 0);
1783
1784      /* On the last iteration we need to store into dest_reg.  */
1785      if (ins_shift == 0)
1786	result = dest_reg;
1787      else
1788	result = create_temp_reg_if_possible (DImode, dest_reg);
1789
1790      emit_insn (gen_insn_shl16insli (result, temp, GEN_INT (bits)));
1791
1792      temp = result;
1793    }
1794}
1795
1796
1797/* Load OP1, a 64-bit constant, into OP0, a register.  We know it
1798   can't be done in one insn when we get here, the move expander
1799   guarantees this.  */
1800void
1801tilegx_expand_set_const64 (rtx op0, rtx op1)
1802{
1803  if (CONST_INT_P (op1))
1804    {
1805      /* TODO: I don't know if we want to split large constants
1806	 now, or wait until later (with a define_split).
1807
1808	 Does splitting early help CSE?  Does it harm other
1809	 optimizations that might fold loads?  */
1810      expand_set_cint64 (op0, op1);
1811    }
1812  else
1813    {
1814      rtx temp = create_temp_reg_if_possible (Pmode, op0);
1815
1816      if (TARGET_32BIT)
1817	{
1818	  /* Generate the 2-insn sequence to materialize a symbolic
1819	     address.  */
1820	  emit_insn (gen_mov_address_32bit_step1 (temp, op1));
1821	  emit_insn (gen_mov_address_32bit_step2 (op0, temp, op1));
1822	}
1823      else
1824	{
1825	  /* Generate the 3-insn sequence to materialize a symbolic
1826	     address.  Note that this assumes that virtual addresses
1827	     fit in 48 signed bits, which is currently true.  */
1828	  rtx temp2 = create_temp_reg_if_possible (Pmode, op0);
1829	  emit_insn (gen_mov_address_step1 (temp, op1));
1830	  emit_insn (gen_mov_address_step2 (temp2, temp, op1));
1831	  emit_insn (gen_mov_address_step3 (op0, temp2, op1));
1832	}
1833    }
1834}
1835
1836
1837/* Expand a move instruction.  Return true if all work is done.  */
1838bool
1839tilegx_expand_mov (machine_mode mode, rtx *operands)
1840{
1841  /* Handle sets of MEM first.  */
1842  if (MEM_P (operands[0]))
1843    {
1844      if (can_create_pseudo_p ())
1845	operands[0] = validize_mem (operands[0]);
1846
1847      if (reg_or_0_operand (operands[1], mode))
1848	return false;
1849
1850      if (!reload_in_progress)
1851	operands[1] = force_reg (mode, operands[1]);
1852    }
1853
1854  /* Fixup TLS cases.  */
1855  if (CONSTANT_P (operands[1]) && tilegx_tls_referenced_p (operands[1]))
1856    {
1857      operands[1] = tilegx_legitimize_tls_address (operands[1]);
1858      return false;
1859    }
1860
1861  /* Fixup PIC cases.  */
1862  if (flag_pic && CONSTANT_P (operands[1]))
1863    {
1864      if (tilegx_pic_address_needs_scratch (operands[1]))
1865	operands[1] = tilegx_legitimize_pic_address (operands[1], mode, 0);
1866
1867      if (symbolic_operand (operands[1], mode))
1868	{
1869	  operands[1] = tilegx_legitimize_pic_address (operands[1],
1870						       mode,
1871						       (reload_in_progress ?
1872							operands[0] :
1873							NULL_RTX));
1874	  return false;
1875	}
1876    }
1877
1878  /* Accept non-constants and valid constants unmodified.  */
1879  if (!CONSTANT_P (operands[1]) || move_operand (operands[1], mode))
1880    return false;
1881
1882  /* Split large integers.  */
1883  tilegx_expand_set_const64 (operands[0], operands[1]);
1884  return true;
1885}
1886
1887
1888/* Expand unaligned loads.  */
1889void
1890tilegx_expand_unaligned_load (rtx dest_reg, rtx mem, HOST_WIDE_INT bitsize,
1891			      HOST_WIDE_INT bit_offset, bool sign)
1892{
1893  machine_mode mode;
1894  rtx addr_lo, addr_hi;
1895  rtx mem_lo, mem_hi, hi;
1896  rtx mema, wide_result;
1897  int last_byte_offset;
1898  HOST_WIDE_INT byte_offset = bit_offset / BITS_PER_UNIT;
1899
1900  mode = GET_MODE (dest_reg);
1901
1902  if (bitsize == 2 * BITS_PER_UNIT && (bit_offset % BITS_PER_UNIT) == 0)
1903    {
1904      rtx mem_left, mem_right;
1905      rtx left = gen_reg_rtx (mode);
1906
1907      /* When just loading a two byte value, we can load the two bytes
1908	 individually and combine them efficiently.  */
1909
1910      mem_lo = adjust_address (mem, QImode, byte_offset);
1911      mem_hi = adjust_address (mem, QImode, byte_offset + 1);
1912
1913      if (BYTES_BIG_ENDIAN)
1914	{
1915	  mem_left = mem_lo;
1916	  mem_right = mem_hi;
1917	}
1918      else
1919	{
1920	  mem_left = mem_hi;
1921	  mem_right = mem_lo;
1922	}
1923
1924      if (sign)
1925	{
1926	  /* Do a signed load of the second byte and use bfins to set
1927	     the high bits of the result.  */
1928	  emit_insn (gen_zero_extendqidi2 (gen_lowpart (DImode, dest_reg),
1929					   mem_right));
1930	  emit_insn (gen_extendqidi2 (gen_lowpart (DImode, left), mem_left));
1931	  emit_insn (gen_insv (gen_lowpart (DImode, dest_reg),
1932			       GEN_INT (64 - 8), GEN_INT (8),
1933			       gen_lowpart (DImode, left)));
1934	}
1935      else
1936	{
1937	  /* Do two unsigned loads and use v1int_l to interleave
1938	     them.  */
1939	  rtx right = gen_reg_rtx (mode);
1940	  emit_insn (gen_zero_extendqidi2 (gen_lowpart (DImode, right),
1941					   mem_right));
1942	  emit_insn (gen_zero_extendqidi2 (gen_lowpart (DImode, left),
1943					   mem_left));
1944	  emit_insn (gen_insn_v1int_l (gen_lowpart (DImode, dest_reg),
1945				       gen_lowpart (DImode, left),
1946				       gen_lowpart (DImode, right)));
1947	}
1948
1949      return;
1950    }
1951
1952  mema = XEXP (mem, 0);
1953
1954  /* AND addresses cannot be in any alias set, since they may
1955     implicitly alias surrounding code.  Ideally we'd have some alias
1956     set that covered all types except those with alignment 8 or
1957     higher.  */
1958  addr_lo = force_reg (Pmode, plus_constant (Pmode, mema, byte_offset));
1959  mem_lo = change_address (mem, mode,
1960			   gen_rtx_AND (GET_MODE (mema), addr_lo,
1961					GEN_INT (-8)));
1962  set_mem_alias_set (mem_lo, 0);
1963
1964  /* Load the high word at an address that will not fault if the low
1965     address is aligned and at the very end of a page.  */
1966  last_byte_offset = (bit_offset + bitsize - 1) / BITS_PER_UNIT;
1967  addr_hi = force_reg (Pmode, plus_constant (Pmode, mema, last_byte_offset));
1968  mem_hi = change_address (mem, mode,
1969			   gen_rtx_AND (GET_MODE (mema), addr_hi,
1970					GEN_INT (-8)));
1971  set_mem_alias_set (mem_hi, 0);
1972
1973  if (bitsize == 64)
1974    {
1975      addr_lo = make_safe_from (addr_lo, dest_reg);
1976      wide_result = dest_reg;
1977    }
1978  else
1979    {
1980      wide_result = gen_reg_rtx (mode);
1981    }
1982
1983  /* Load hi first in case dest_reg is used in mema.  */
1984  hi = gen_reg_rtx (mode);
1985  emit_move_insn (hi, mem_hi);
1986  emit_move_insn (wide_result, mem_lo);
1987
1988  emit_insn (gen_insn_dblalign (gen_lowpart (DImode, wide_result),
1989				gen_lowpart (DImode, wide_result),
1990				gen_lowpart (DImode, hi), addr_lo));
1991
1992  if (bitsize != 64)
1993    {
1994      rtx extracted =
1995	extract_bit_field (gen_lowpart (DImode, wide_result),
1996			   bitsize, bit_offset % BITS_PER_UNIT,
1997			   !sign, gen_lowpart (DImode, dest_reg),
1998			   DImode, DImode);
1999
2000      if (extracted != dest_reg)
2001	emit_move_insn (dest_reg, gen_lowpart (DImode, extracted));
2002    }
2003}
2004
2005
2006/* Expand unaligned stores.  */
2007static void
2008tilegx_expand_unaligned_store (rtx mem, rtx src, HOST_WIDE_INT bitsize,
2009			       HOST_WIDE_INT bit_offset)
2010{
2011  HOST_WIDE_INT byte_offset = bit_offset / BITS_PER_UNIT;
2012  HOST_WIDE_INT bytesize = bitsize / BITS_PER_UNIT;
2013  HOST_WIDE_INT shift_init, shift_increment, shift_amt;
2014  HOST_WIDE_INT i;
2015  rtx mem_addr;
2016  rtx store_val;
2017
2018  shift_init = BYTES_BIG_ENDIAN ? (bitsize - BITS_PER_UNIT) : 0;
2019  shift_increment = BYTES_BIG_ENDIAN ? -BITS_PER_UNIT : BITS_PER_UNIT;
2020
2021  for (i = 0, shift_amt = shift_init;
2022       i < bytesize;
2023       i++, shift_amt += shift_increment)
2024    {
2025      mem_addr = adjust_address (mem, QImode, byte_offset + i);
2026
2027      if (shift_amt)
2028	{
2029	  store_val = expand_simple_binop (DImode, LSHIFTRT,
2030					   gen_lowpart (DImode, src),
2031					   GEN_INT (shift_amt), NULL, 1,
2032					   OPTAB_LIB_WIDEN);
2033	  store_val = gen_lowpart (QImode, store_val);
2034	}
2035      else
2036	{
2037	  store_val = gen_lowpart (QImode, src);
2038	}
2039
2040      emit_move_insn (mem_addr, store_val);
2041    }
2042}
2043
2044
2045/* Implement the movmisalign patterns.  One of the operands is a
2046   memory that is not naturally aligned.  Emit instructions to load
2047   it.  */
2048void
2049tilegx_expand_movmisalign (machine_mode mode, rtx *operands)
2050{
2051  if (MEM_P (operands[1]))
2052    {
2053      rtx tmp;
2054
2055      if (register_operand (operands[0], mode))
2056	tmp = operands[0];
2057      else
2058	tmp = gen_reg_rtx (mode);
2059
2060      tilegx_expand_unaligned_load (tmp, operands[1], GET_MODE_BITSIZE (mode),
2061				    0, true);
2062
2063      if (tmp != operands[0])
2064	emit_move_insn (operands[0], tmp);
2065    }
2066  else if (MEM_P (operands[0]))
2067    {
2068      if (!reg_or_0_operand (operands[1], mode))
2069	operands[1] = force_reg (mode, operands[1]);
2070
2071      tilegx_expand_unaligned_store (operands[0], operands[1],
2072				     GET_MODE_BITSIZE (mode), 0);
2073    }
2074  else
2075    gcc_unreachable ();
2076
2077}
2078
2079
2080/* Implement the allocate_stack pattern (alloca).  */
2081void
2082tilegx_allocate_stack (rtx op0, rtx op1)
2083{
2084  /* Technically the correct way to initialize chain_loc is with
2085   * gen_frame_mem() instead of gen_rtx_MEM(), but gen_frame_mem()
2086   * sets the alias_set to that of a frame reference.  Some of our
2087   * tests rely on some unsafe assumption about when the chaining
2088   * update is done, we need to be conservative about reordering the
2089   * chaining instructions.
2090   */
2091  rtx fp_addr = gen_reg_rtx (Pmode);
2092  rtx fp_value = gen_reg_rtx (Pmode);
2093  rtx fp_loc;
2094
2095  emit_move_insn (fp_addr, gen_rtx_PLUS (Pmode, stack_pointer_rtx,
2096					 GEN_INT (UNITS_PER_WORD)));
2097
2098  fp_loc = gen_frame_mem (Pmode, fp_addr);
2099
2100  emit_move_insn (fp_value, fp_loc);
2101
2102  op1 = force_reg (Pmode, op1);
2103
2104  emit_move_insn (stack_pointer_rtx,
2105		  gen_rtx_MINUS (Pmode, stack_pointer_rtx, op1));
2106
2107  emit_move_insn (fp_addr, gen_rtx_PLUS (Pmode, stack_pointer_rtx,
2108					 GEN_INT (UNITS_PER_WORD)));
2109
2110  fp_loc = gen_frame_mem (Pmode, fp_addr);
2111
2112  emit_move_insn (fp_loc, fp_value);
2113
2114  emit_move_insn (op0, virtual_stack_dynamic_rtx);
2115}
2116
2117
2118
2119/* Multiplies */
2120
2121
2122/* Returns the insn_code in ENTRY.  */
2123static enum insn_code
2124tilegx_multiply_get_opcode (const struct tilegx_multiply_insn_seq_entry
2125			    *entry)
2126{
2127  return tilegx_multiply_insn_seq_decode_opcode[entry->compressed_opcode];
2128}
2129
2130
2131/* Returns the length of the 'op' array.  */
2132static int
2133tilegx_multiply_get_num_ops (const struct tilegx_multiply_insn_seq *seq)
2134{
2135  /* The array either uses all of its allocated slots or is terminated
2136     by a bogus opcode. Either way, the array size is the index of the
2137     last valid opcode plus one.  */
2138  int i;
2139  for (i = tilegx_multiply_insn_seq_MAX_OPERATIONS - 1; i >= 0; i--)
2140    if (tilegx_multiply_get_opcode (&seq->op[i]) != CODE_FOR_nothing)
2141      return i + 1;
2142
2143  /* An empty array is not allowed.  */
2144  gcc_unreachable ();
2145}
2146
2147
2148/* We precompute a number of expression trees for multiplying by
2149   constants.  This generates code for such an expression tree by
2150   walking through the nodes in the tree (which are conveniently
2151   pre-linearized) and emitting an instruction for each one.  */
2152static void
2153tilegx_expand_constant_multiply_given_sequence (rtx result, rtx src,
2154						const struct
2155						tilegx_multiply_insn_seq *seq)
2156{
2157  int i;
2158  int num_ops;
2159
2160  /* Keep track of the subexpressions computed so far, so later
2161     instructions can refer to them.  We seed the array with zero and
2162     the value being multiplied.  */
2163  int num_subexprs = 2;
2164  rtx subexprs[tilegx_multiply_insn_seq_MAX_OPERATIONS + 2];
2165  subexprs[0] = const0_rtx;
2166  subexprs[1] = src;
2167
2168  /* Determine how many instructions we are going to generate.  */
2169  num_ops = tilegx_multiply_get_num_ops (seq);
2170  gcc_assert (num_ops > 0
2171	      && num_ops <= tilegx_multiply_insn_seq_MAX_OPERATIONS);
2172
2173  for (i = 0; i < num_ops; i++)
2174    {
2175      const struct tilegx_multiply_insn_seq_entry *entry = &seq->op[i];
2176
2177      /* Figure out where to store the output of this instruction.  */
2178      const bool is_last_op = (i + 1 == num_ops);
2179      rtx out = is_last_op ? result : gen_reg_rtx (DImode);
2180
2181      enum insn_code opcode = tilegx_multiply_get_opcode (entry);
2182      if (opcode == CODE_FOR_ashldi3)
2183	{
2184	  /* Handle shift by immediate. This is a special case because
2185	     the meaning of the second operand is a constant shift
2186	     count rather than an operand index.  */
2187
2188	  /* Make sure the shift count is in range. Zero should not
2189	     happen.  */
2190	  const int shift_count = entry->rhs;
2191	  gcc_assert (shift_count > 0 && shift_count < 64);
2192
2193	  /* Emit the actual instruction.  */
2194	  emit_insn (GEN_FCN (opcode)
2195		     (out, subexprs[entry->lhs],
2196		      gen_rtx_CONST_INT (DImode, shift_count)));
2197	}
2198      else
2199	{
2200	  /* Handle a normal two-operand instruction, such as add or
2201	     shl1add.  */
2202
2203	  /* Make sure we are referring to a previously computed
2204	     subexpression.  */
2205	  gcc_assert (entry->rhs < num_subexprs);
2206
2207	  /* Emit the actual instruction.  */
2208	  emit_insn (GEN_FCN (opcode)
2209		     (out, subexprs[entry->lhs], subexprs[entry->rhs]));
2210	}
2211
2212      /* Record this subexpression for use by later expressions.  */
2213      subexprs[num_subexprs++] = out;
2214    }
2215}
2216
2217
2218/* bsearch helper function.  */
2219static int
2220tilegx_compare_multipliers (const void *key, const void *t)
2221{
2222  long long delta =
2223    (*(const long long *) key
2224     - ((const struct tilegx_multiply_insn_seq *) t)->multiplier);
2225  return (delta < 0) ? -1 : (delta > 0);
2226}
2227
2228
2229/* Returns the tilegx_multiply_insn_seq for multiplier, or NULL if none
2230   exists.  */
2231static const struct tilegx_multiply_insn_seq *
2232tilegx_find_multiply_insn_seq_for_constant (long long multiplier)
2233{
2234  return ((const struct tilegx_multiply_insn_seq *)
2235	  bsearch (&multiplier, tilegx_multiply_insn_seq_table,
2236		   tilegx_multiply_insn_seq_table_size,
2237		   sizeof tilegx_multiply_insn_seq_table[0],
2238		   tilegx_compare_multipliers));
2239}
2240
2241
2242/* Try to a expand constant multiply in DImode by looking it up in a
2243   precompiled table.  OP0 is the result operand, OP1 is the source
2244   operand, and MULTIPLIER is the value of the constant.  Return true
2245   if it succeeds.  */
2246static bool
2247tilegx_expand_const_muldi (rtx op0, rtx op1, long long multiplier)
2248{
2249  /* See if we have precomputed an efficient way to multiply by this
2250     constant.  */
2251  const struct tilegx_multiply_insn_seq *seq =
2252    tilegx_find_multiply_insn_seq_for_constant (multiplier);
2253  if (seq != NULL)
2254    {
2255      tilegx_expand_constant_multiply_given_sequence (op0, op1, seq);
2256      return true;
2257    }
2258  else
2259    return false;
2260}
2261
2262
2263/* Expand the muldi pattern.  */
2264bool
2265tilegx_expand_muldi (rtx op0, rtx op1, rtx op2)
2266{
2267  if (CONST_INT_P (op2))
2268    {
2269      HOST_WIDE_INT n = trunc_int_for_mode (INTVAL (op2), DImode);
2270      return tilegx_expand_const_muldi (op0, op1, n);
2271    }
2272  return false;
2273}
2274
2275
2276/* Expand a high multiply pattern in DImode.  RESULT, OP1, OP2 are the
2277   operands, and SIGN is true if it's a signed multiply, and false if
2278   it's an unsigned multiply.  */
2279static void
2280tilegx_expand_high_multiply (rtx result, rtx op1, rtx op2, bool sign)
2281{
2282  rtx tmp0 = gen_reg_rtx (DImode);
2283  rtx tmp1 = gen_reg_rtx (DImode);
2284  rtx tmp2 = gen_reg_rtx (DImode);
2285  rtx tmp3 = gen_reg_rtx (DImode);
2286  rtx tmp4 = gen_reg_rtx (DImode);
2287  rtx tmp5 = gen_reg_rtx (DImode);
2288  rtx tmp6 = gen_reg_rtx (DImode);
2289  rtx tmp7 = gen_reg_rtx (DImode);
2290  rtx tmp8 = gen_reg_rtx (DImode);
2291  rtx tmp9 = gen_reg_rtx (DImode);
2292  rtx tmp10 = gen_reg_rtx (DImode);
2293  rtx tmp11 = gen_reg_rtx (DImode);
2294  rtx tmp12 = gen_reg_rtx (DImode);
2295  rtx tmp13 = gen_reg_rtx (DImode);
2296  rtx result_lo = gen_reg_rtx (DImode);
2297
2298  if (sign)
2299    {
2300      emit_insn (gen_insn_mul_hs_lu (tmp0, op1, op2));
2301      emit_insn (gen_insn_mul_hs_lu (tmp1, op2, op1));
2302      emit_insn (gen_insn_mul_lu_lu (tmp2, op1, op2));
2303      emit_insn (gen_insn_mul_hs_hs (tmp3, op1, op2));
2304    }
2305  else
2306    {
2307      emit_insn (gen_insn_mul_hu_lu (tmp0, op1, op2));
2308      emit_insn (gen_insn_mul_hu_lu (tmp1, op2, op1));
2309      emit_insn (gen_insn_mul_lu_lu (tmp2, op1, op2));
2310      emit_insn (gen_insn_mul_hu_hu (tmp3, op1, op2));
2311    }
2312
2313  emit_move_insn (tmp4, (gen_rtx_ASHIFT (DImode, tmp0, GEN_INT (32))));
2314
2315  emit_move_insn (tmp5, (gen_rtx_ASHIFT (DImode, tmp1, GEN_INT (32))));
2316
2317  emit_move_insn (tmp6, (gen_rtx_PLUS (DImode, tmp4, tmp5)));
2318  emit_move_insn (result_lo, (gen_rtx_PLUS (DImode, tmp2, tmp6)));
2319
2320  emit_move_insn (tmp7, gen_rtx_LTU (DImode, tmp6, tmp4));
2321  emit_move_insn (tmp8, gen_rtx_LTU (DImode, result_lo, tmp2));
2322
2323  if (sign)
2324    {
2325      emit_move_insn (tmp9, (gen_rtx_ASHIFTRT (DImode, tmp0, GEN_INT (32))));
2326      emit_move_insn (tmp10, (gen_rtx_ASHIFTRT (DImode, tmp1, GEN_INT (32))));
2327    }
2328  else
2329    {
2330      emit_move_insn (tmp9, (gen_rtx_LSHIFTRT (DImode, tmp0, GEN_INT (32))));
2331      emit_move_insn (tmp10, (gen_rtx_LSHIFTRT (DImode, tmp1, GEN_INT (32))));
2332    }
2333
2334  emit_move_insn (tmp11, (gen_rtx_PLUS (DImode, tmp3, tmp7)));
2335  emit_move_insn (tmp12, (gen_rtx_PLUS (DImode, tmp8, tmp9)));
2336  emit_move_insn (tmp13, (gen_rtx_PLUS (DImode, tmp11, tmp12)));
2337  emit_move_insn (result, (gen_rtx_PLUS (DImode, tmp13, tmp10)));
2338}
2339
2340
2341/* Implement smuldi3_highpart.  */
2342void
2343tilegx_expand_smuldi3_highpart (rtx op0, rtx op1, rtx op2)
2344{
2345  tilegx_expand_high_multiply (op0, op1, op2, true);
2346}
2347
2348
2349/* Implement umuldi3_highpart.  */
2350void
2351tilegx_expand_umuldi3_highpart (rtx op0, rtx op1, rtx op2)
2352{
2353  tilegx_expand_high_multiply (op0, op1, op2, false);
2354}
2355
2356
2357
2358/* Compare and branches  */
2359
2360/* Produce the rtx yielding a bool for a floating point
2361   comparison.  */
2362static bool
2363tilegx_emit_fp_setcc (rtx res, enum rtx_code code, machine_mode mode,
2364		      rtx op0, rtx op1)
2365{
2366  /* TODO: Certain compares again constants can be done using entirely
2367     integer operations. But you have to get the special cases right
2368     e.g. NaN, +0 == -0, etc.  */
2369
2370  rtx flags;
2371  int flag_index;
2372  rtx a = force_reg (DImode, gen_lowpart (DImode, op0));
2373  rtx b = force_reg (DImode, gen_lowpart (DImode, op1));
2374
2375  flags = gen_reg_rtx (DImode);
2376
2377  if (mode == SFmode)
2378    {
2379      emit_insn (gen_insn_fsingle_add1 (flags, a, b));
2380    }
2381  else
2382    {
2383      gcc_assert (mode == DFmode);
2384      emit_insn (gen_insn_fdouble_add_flags (flags, a, b));
2385    }
2386
2387  switch (code)
2388    {
2389    case EQ: flag_index = 30; break;
2390    case NE: flag_index = 31; break;
2391    case LE: flag_index = 27; break;
2392    case LT: flag_index = 26; break;
2393    case GE: flag_index = 29; break;
2394    case GT: flag_index = 28; break;
2395    default: gcc_unreachable ();
2396    }
2397
2398  gcc_assert (GET_MODE (res) == DImode);
2399  emit_move_insn (res, gen_rtx_ZERO_EXTRACT (DImode, flags, GEN_INT (1),
2400					     GEN_INT (flag_index)));
2401  return true;
2402}
2403
2404
2405/* Certain simplifications can be done to make invalid setcc
2406   operations valid.  Return the final comparison, or NULL if we can't
2407   work.  */
2408static bool
2409tilegx_emit_setcc_internal (rtx res, enum rtx_code code, rtx op0, rtx op1,
2410			    machine_mode cmp_mode)
2411{
2412  rtx tmp;
2413  bool swap = false;
2414
2415  if (cmp_mode == SFmode || cmp_mode == DFmode)
2416    return tilegx_emit_fp_setcc (res, code, cmp_mode, op0, op1);
2417
2418  /* The general case: fold the comparison code to the types of
2419     compares that we have, choosing the branch as necessary.  */
2420
2421  switch (code)
2422    {
2423    case EQ:
2424    case NE:
2425    case LE:
2426    case LT:
2427    case LEU:
2428    case LTU:
2429      /* We have these compares.  */
2430      break;
2431
2432    case GE:
2433    case GT:
2434    case GEU:
2435    case GTU:
2436      /* We do not have these compares, so we reverse the
2437	 operands.  */
2438      swap = true;
2439      break;
2440
2441    default:
2442      /* We should not have called this with any other code.  */
2443      gcc_unreachable ();
2444    }
2445
2446  if (swap)
2447    {
2448      code = swap_condition (code);
2449      tmp = op0, op0 = op1, op1 = tmp;
2450    }
2451
2452  if (!reg_or_0_operand (op0, cmp_mode))
2453    op0 = force_reg (cmp_mode, op0);
2454
2455  if (!CONST_INT_P (op1) && !register_operand (op1, cmp_mode))
2456    op1 = force_reg (cmp_mode, op1);
2457
2458  /* Return the setcc comparison.  */
2459  emit_insn (gen_rtx_SET (VOIDmode, res,
2460			  gen_rtx_fmt_ee (code, DImode, op0, op1)));
2461
2462  return true;
2463}
2464
2465
2466/* Implement cstore patterns.  */
2467bool
2468tilegx_emit_setcc (rtx operands[], machine_mode cmp_mode)
2469{
2470  return
2471    tilegx_emit_setcc_internal (operands[0], GET_CODE (operands[1]),
2472				operands[2], operands[3], cmp_mode);
2473}
2474
2475
2476/* Return whether CODE is a signed comparison.  */
2477static bool
2478signed_compare_p (enum rtx_code code)
2479{
2480  return (code == EQ || code == NE || code == LT || code == LE
2481	  || code == GT || code == GE);
2482}
2483
2484
2485/* Generate the comparison for a DImode conditional branch.  */
2486static rtx
2487tilegx_emit_cc_test (enum rtx_code code, rtx op0, rtx op1,
2488		     machine_mode cmp_mode, bool eq_ne_only)
2489{
2490  enum rtx_code branch_code;
2491  rtx temp;
2492
2493  if (cmp_mode == SFmode || cmp_mode == DFmode)
2494    {
2495      /* Compute a boolean saying whether the comparison is true.  */
2496      temp = gen_reg_rtx (DImode);
2497      tilegx_emit_setcc_internal (temp, code, op0, op1, cmp_mode);
2498
2499      /* Test that flag.  */
2500      return gen_rtx_fmt_ee (NE, VOIDmode, temp, const0_rtx);
2501    }
2502
2503  /* Check for a compare against zero using a comparison we can do
2504     directly.  */
2505  if (op1 == const0_rtx
2506      && (code == EQ || code == NE
2507	  || (!eq_ne_only && signed_compare_p (code))))
2508    {
2509      op0 = force_reg (cmp_mode, op0);
2510      return gen_rtx_fmt_ee (code, VOIDmode, op0, const0_rtx);
2511    }
2512
2513  /* The general case: fold the comparison code to the types of
2514     compares that we have, choosing the branch as necessary.  */
2515  switch (code)
2516    {
2517    case EQ:
2518    case LE:
2519    case LT:
2520    case LEU:
2521    case LTU:
2522      /* We have these compares.  */
2523      branch_code = NE;
2524      break;
2525
2526    case NE:
2527    case GE:
2528    case GT:
2529    case GEU:
2530    case GTU:
2531      /* These must be reversed (except NE, but let's
2532	 canonicalize).  */
2533      code = reverse_condition (code);
2534      branch_code = EQ;
2535      break;
2536
2537    default:
2538      gcc_unreachable ();
2539    }
2540
2541  if (CONST_INT_P (op1) && (!satisfies_constraint_I (op1) || code == LEU))
2542    {
2543      HOST_WIDE_INT n = INTVAL (op1);
2544
2545      switch (code)
2546	{
2547	case EQ:
2548	  /* Subtract off the value we want to compare against and see
2549	     if we get zero.  This is cheaper than creating a constant
2550	     in a register. Except that subtracting -128 is more
2551	     expensive than seqi to -128, so we leave that alone.  */
2552	  /* ??? Don't do this when comparing against symbols,
2553	     otherwise we'll reduce (&x == 0x1234) to (&x-0x1234 ==
2554	     0), which will be declared false out of hand (at least
2555	     for non-weak).  */
2556	  if (n != -128
2557	      && add_operand (GEN_INT (-n), DImode)
2558	      && !(symbolic_operand (op0, VOIDmode)
2559		   || (REG_P (op0) && REG_POINTER (op0))))
2560	    {
2561	      /* TODO: Use a SIMD add immediate to hit zero for tiled
2562		 constants in a single instruction.  */
2563	      if (GET_MODE (op0) != DImode)
2564		{
2565		  /* Convert to DImode so we can use addli.  Note that
2566		     this will not actually generate any code because
2567		     sign extension from SI -> DI is a no-op.  I don't
2568		     know if it's safe just to make a paradoxical
2569		     subreg here though.  */
2570		  rtx temp2 = gen_reg_rtx (DImode);
2571		  emit_insn (gen_extendsidi2 (temp2, op0));
2572		  op0 = temp2;
2573		}
2574	      else
2575		{
2576		  op0 = force_reg (DImode, op0);
2577		}
2578	      temp = gen_reg_rtx (DImode);
2579	      emit_move_insn (temp, gen_rtx_PLUS (DImode, op0, GEN_INT (-n)));
2580	      return gen_rtx_fmt_ee (reverse_condition (branch_code),
2581				     VOIDmode, temp, const0_rtx);
2582	    }
2583	  break;
2584
2585	case LEU:
2586	  if (n == -1)
2587	    break;
2588	  /* FALLTHRU */
2589
2590	case LTU:
2591	  /* Change ((unsigned)x < 0x1000) into !((int)x >> 12), etc.
2592	     We use arithmetic shift right because it's a 3-wide op,
2593	     while logical shift right is not.  */
2594	  {
2595	    int first = exact_log2 (code == LTU ? n : n + 1);
2596	    if (first != -1)
2597	      {
2598		op0 = force_reg (cmp_mode, op0);
2599		temp = gen_reg_rtx (cmp_mode);
2600		emit_move_insn (temp,
2601				gen_rtx_ASHIFTRT (cmp_mode, op0,
2602						  GEN_INT (first)));
2603		return gen_rtx_fmt_ee (reverse_condition (branch_code),
2604				       VOIDmode, temp, const0_rtx);
2605	      }
2606	  }
2607	  break;
2608
2609	default:
2610	  break;
2611	}
2612    }
2613
2614  /* Compute a flag saying whether we should branch.  */
2615  temp = gen_reg_rtx (DImode);
2616  tilegx_emit_setcc_internal (temp, code, op0, op1, cmp_mode);
2617
2618  /* Return the branch comparison.  */
2619  return gen_rtx_fmt_ee (branch_code, VOIDmode, temp, const0_rtx);
2620}
2621
2622
2623/* Generate the comparison for a conditional branch.  */
2624void
2625tilegx_emit_conditional_branch (rtx operands[], machine_mode cmp_mode)
2626{
2627  rtx cmp_rtx =
2628    tilegx_emit_cc_test (GET_CODE (operands[0]), operands[1], operands[2],
2629			 cmp_mode, false);
2630  rtx branch_rtx = gen_rtx_SET (VOIDmode, pc_rtx,
2631				gen_rtx_IF_THEN_ELSE (VOIDmode, cmp_rtx,
2632						      gen_rtx_LABEL_REF
2633						      (VOIDmode,
2634						       operands[3]),
2635						      pc_rtx));
2636  emit_jump_insn (branch_rtx);
2637}
2638
2639
2640/* Implement the mov<mode>cc pattern.  */
2641rtx
2642tilegx_emit_conditional_move (rtx cmp)
2643{
2644  return
2645    tilegx_emit_cc_test (GET_CODE (cmp), XEXP (cmp, 0), XEXP (cmp, 1),
2646			 GET_MODE (XEXP (cmp, 0)), true);
2647}
2648
2649
2650/* Return true if INSN is annotated with a REG_BR_PROB note that
2651   indicates it's a branch that's predicted taken.  */
2652static bool
2653cbranch_predicted_p (rtx_insn *insn)
2654{
2655  rtx x = find_reg_note (insn, REG_BR_PROB, 0);
2656
2657  if (x)
2658    {
2659      int pred_val = XINT (x, 0);
2660
2661      return pred_val >= REG_BR_PROB_BASE / 2;
2662    }
2663
2664  return false;
2665}
2666
2667
2668/* Output assembly code for a specific branch instruction, appending
2669   the branch prediction flag to the opcode if appropriate.  */
2670static const char *
2671tilegx_output_simple_cbranch_with_opcode (rtx_insn *insn, const char *opcode,
2672					  int regop, bool reverse_predicted)
2673{
2674  static char buf[64];
2675  sprintf (buf, "%s%s\t%%r%d, %%l0", opcode,
2676	   (cbranch_predicted_p (insn) ^ reverse_predicted) ? "t" : "",
2677	   regop);
2678  return buf;
2679}
2680
2681
2682/* Output assembly code for a specific branch instruction, appending
2683   the branch prediction flag to the opcode if appropriate.  */
2684const char *
2685tilegx_output_cbranch_with_opcode (rtx_insn *insn, rtx *operands,
2686				   const char *opcode,
2687				   const char *rev_opcode, int regop)
2688{
2689  const char *branch_if_false;
2690  rtx taken, not_taken;
2691  bool is_simple_branch;
2692
2693  gcc_assert (LABEL_P (operands[0]));
2694
2695  is_simple_branch = true;
2696  if (INSN_ADDRESSES_SET_P ())
2697    {
2698      int from_addr = INSN_ADDRESSES (INSN_UID (insn));
2699      int to_addr = INSN_ADDRESSES (INSN_UID (operands[0]));
2700      int delta = to_addr - from_addr;
2701      is_simple_branch = IN_RANGE (delta, -524288, 524280);
2702    }
2703
2704  if (is_simple_branch)
2705    {
2706      /* Just a simple conditional branch.  */
2707      return
2708	tilegx_output_simple_cbranch_with_opcode (insn, opcode, regop, false);
2709    }
2710
2711  /* Generate a reversed branch around a direct jump.  This fallback
2712     does not use branch-likely instructions.  */
2713  not_taken = gen_label_rtx ();
2714  taken = operands[0];
2715
2716  /* Generate the reversed branch to NOT_TAKEN.  */
2717  operands[0] = not_taken;
2718  branch_if_false =
2719    tilegx_output_simple_cbranch_with_opcode (insn, rev_opcode, regop, true);
2720  output_asm_insn (branch_if_false, operands);
2721
2722  output_asm_insn ("j\t%l0", &taken);
2723
2724  /* Output NOT_TAKEN.  */
2725  targetm.asm_out.internal_label (asm_out_file, "L",
2726				  CODE_LABEL_NUMBER (not_taken));
2727  return "";
2728}
2729
2730
2731/* Output assembly code for a conditional branch instruction.  */
2732const char *
2733tilegx_output_cbranch (rtx_insn *insn, rtx *operands, bool reversed)
2734{
2735  enum rtx_code code = GET_CODE (operands[1]);
2736  const char *opcode;
2737  const char *rev_opcode;
2738
2739  if (reversed)
2740    code = reverse_condition (code);
2741
2742  switch (code)
2743    {
2744    case NE:
2745      opcode = "bnez";
2746      rev_opcode = "beqz";
2747      break;
2748    case EQ:
2749      opcode = "beqz";
2750      rev_opcode = "bnez";
2751      break;
2752    case GE:
2753      opcode = "bgez";
2754      rev_opcode = "bltz";
2755      break;
2756    case GT:
2757      opcode = "bgtz";
2758      rev_opcode = "blez";
2759      break;
2760    case LE:
2761      opcode = "blez";
2762      rev_opcode = "bgtz";
2763      break;
2764    case LT:
2765      opcode = "bltz";
2766      rev_opcode = "bgez";
2767      break;
2768    default:
2769      gcc_unreachable ();
2770    }
2771
2772  return tilegx_output_cbranch_with_opcode (insn, operands, opcode,
2773					    rev_opcode, 2);
2774}
2775
2776
2777/* Implement the tablejump pattern.  */
2778void
2779tilegx_expand_tablejump (rtx op0, rtx op1)
2780{
2781  if (flag_pic)
2782    {
2783      rtx temp = gen_reg_rtx (Pmode);
2784      rtx temp2 = gen_reg_rtx (Pmode);
2785
2786      tilegx_compute_pcrel_address (temp, gen_rtx_LABEL_REF (Pmode, op1));
2787      emit_move_insn (temp2,
2788		      gen_rtx_PLUS (Pmode,
2789				    convert_to_mode (Pmode, op0, false),
2790				    temp));
2791      op0 = temp2;
2792    }
2793
2794  emit_jump_insn (gen_tablejump_aux (op0, op1));
2795}
2796
2797
2798/* Emit barrier before an atomic, as needed for the memory MODEL.  */
2799void
2800tilegx_pre_atomic_barrier (enum memmodel model)
2801{
2802  if (need_atomic_barrier_p (model, true))
2803    emit_insn (gen_memory_barrier ());
2804}
2805
2806
2807/* Emit barrier after an atomic, as needed for the memory MODEL.  */
2808void
2809tilegx_post_atomic_barrier (enum memmodel model)
2810{
2811  if (need_atomic_barrier_p (model, false))
2812    emit_insn (gen_memory_barrier ());
2813}
2814
2815
2816
2817/* Expand a builtin vector binary op, by calling gen function GEN with
2818   operands in the proper modes.  DEST is converted to DEST_MODE, and
2819   src0 and src1 (if DO_SRC1 is true) is converted to SRC_MODE.  */
2820void
2821tilegx_expand_builtin_vector_binop (rtx (*gen) (rtx, rtx, rtx),
2822				    machine_mode dest_mode,
2823				    rtx dest,
2824				    machine_mode src_mode,
2825				    rtx src0, rtx src1, bool do_src1)
2826{
2827  dest = gen_lowpart (dest_mode, dest);
2828
2829  if (src0 == const0_rtx)
2830    src0 = CONST0_RTX (src_mode);
2831  else
2832    src0 = gen_lowpart (src_mode, src0);
2833
2834  if (do_src1)
2835    {
2836      if (src1 == const0_rtx)
2837	src1 = CONST0_RTX (src_mode);
2838      else
2839	src1 = gen_lowpart (src_mode, src1);
2840    }
2841
2842  emit_insn ((*gen) (dest, src0, src1));
2843}
2844
2845
2846
2847/* Intrinsics  */
2848
2849
2850struct tile_builtin_info
2851{
2852  enum insn_code icode;
2853  tree fndecl;
2854};
2855
2856static struct tile_builtin_info tilegx_builtin_info[TILEGX_BUILTIN_max] = {
2857  { CODE_FOR_adddi3,                    NULL }, /* add */
2858  { CODE_FOR_addsi3,                    NULL }, /* addx */
2859  { CODE_FOR_ssaddsi3,                  NULL }, /* addxsc */
2860  { CODE_FOR_anddi3,                    NULL }, /* and */
2861  { CODE_FOR_insn_bfexts,               NULL }, /* bfexts */
2862  { CODE_FOR_insn_bfextu,               NULL }, /* bfextu */
2863  { CODE_FOR_insn_bfins,                NULL }, /* bfins */
2864  { CODE_FOR_clzdi2,                    NULL }, /* clz */
2865  { CODE_FOR_insn_cmoveqz,              NULL }, /* cmoveqz */
2866  { CODE_FOR_insn_cmovnez,              NULL }, /* cmovnez */
2867  { CODE_FOR_insn_cmpeq_didi,           NULL }, /* cmpeq */
2868  { CODE_FOR_insn_cmpexch,              NULL }, /* cmpexch */
2869  { CODE_FOR_insn_cmpexch4,             NULL }, /* cmpexch4 */
2870  { CODE_FOR_insn_cmples_didi,          NULL }, /* cmples */
2871  { CODE_FOR_insn_cmpleu_didi,          NULL }, /* cmpleu */
2872  { CODE_FOR_insn_cmplts_didi,          NULL }, /* cmplts */
2873  { CODE_FOR_insn_cmpltu_didi,          NULL }, /* cmpltu */
2874  { CODE_FOR_insn_cmpne_didi,           NULL }, /* cmpne */
2875  { CODE_FOR_insn_cmul,                 NULL }, /* cmul */
2876  { CODE_FOR_insn_cmula,                NULL }, /* cmula */
2877  { CODE_FOR_insn_cmulaf,               NULL }, /* cmulaf */
2878  { CODE_FOR_insn_cmulf,                NULL }, /* cmulf */
2879  { CODE_FOR_insn_cmulfr,               NULL }, /* cmulfr */
2880  { CODE_FOR_insn_cmulh,                NULL }, /* cmulh */
2881  { CODE_FOR_insn_cmulhr,               NULL }, /* cmulhr */
2882  { CODE_FOR_insn_crc32_32,             NULL }, /* crc32_32 */
2883  { CODE_FOR_insn_crc32_8,              NULL }, /* crc32_8 */
2884  { CODE_FOR_ctzdi2,                    NULL }, /* ctz */
2885  { CODE_FOR_insn_dblalign,             NULL }, /* dblalign */
2886  { CODE_FOR_insn_dblalign2,            NULL }, /* dblalign2 */
2887  { CODE_FOR_insn_dblalign4,            NULL }, /* dblalign4 */
2888  { CODE_FOR_insn_dblalign6,            NULL }, /* dblalign6 */
2889  { CODE_FOR_insn_drain,                NULL }, /* drain */
2890  { CODE_FOR_insn_dtlbpr,               NULL }, /* dtlbpr */
2891  { CODE_FOR_insn_exch,                 NULL }, /* exch */
2892  { CODE_FOR_insn_exch4,                NULL }, /* exch4 */
2893  { CODE_FOR_insn_fdouble_add_flags,    NULL }, /* fdouble_add_flags */
2894  { CODE_FOR_insn_fdouble_addsub,       NULL }, /* fdouble_addsub */
2895  { CODE_FOR_insn_fdouble_mul_flags,    NULL }, /* fdouble_mul_flags */
2896  { CODE_FOR_insn_fdouble_pack1,        NULL }, /* fdouble_pack1 */
2897  { CODE_FOR_insn_fdouble_pack2,        NULL }, /* fdouble_pack2 */
2898  { CODE_FOR_insn_fdouble_sub_flags,    NULL }, /* fdouble_sub_flags */
2899  { CODE_FOR_insn_fdouble_unpack_max,   NULL }, /* fdouble_unpack_max */
2900  { CODE_FOR_insn_fdouble_unpack_min,   NULL }, /* fdouble_unpack_min */
2901  { CODE_FOR_insn_fetchadd,             NULL }, /* fetchadd */
2902  { CODE_FOR_insn_fetchadd4,            NULL }, /* fetchadd4 */
2903  { CODE_FOR_insn_fetchaddgez,          NULL }, /* fetchaddgez */
2904  { CODE_FOR_insn_fetchaddgez4,         NULL }, /* fetchaddgez4 */
2905  { CODE_FOR_insn_fetchand,             NULL }, /* fetchand */
2906  { CODE_FOR_insn_fetchand4,            NULL }, /* fetchand4 */
2907  { CODE_FOR_insn_fetchor,              NULL }, /* fetchor */
2908  { CODE_FOR_insn_fetchor4,             NULL }, /* fetchor4 */
2909  { CODE_FOR_insn_finv,                 NULL }, /* finv */
2910  { CODE_FOR_insn_flush,                NULL }, /* flush */
2911  { CODE_FOR_insn_flushwb,              NULL }, /* flushwb */
2912  { CODE_FOR_insn_fnop,                 NULL }, /* fnop */
2913  { CODE_FOR_insn_fsingle_add1,         NULL }, /* fsingle_add1 */
2914  { CODE_FOR_insn_fsingle_addsub2,      NULL }, /* fsingle_addsub2 */
2915  { CODE_FOR_insn_fsingle_mul1,         NULL }, /* fsingle_mul1 */
2916  { CODE_FOR_insn_fsingle_mul2,         NULL }, /* fsingle_mul2 */
2917  { CODE_FOR_insn_fsingle_pack1,        NULL }, /* fsingle_pack1 */
2918  { CODE_FOR_insn_fsingle_pack2,        NULL }, /* fsingle_pack2 */
2919  { CODE_FOR_insn_fsingle_sub1,         NULL }, /* fsingle_sub1 */
2920  { CODE_FOR_insn_icoh,                 NULL }, /* icoh */
2921  { CODE_FOR_insn_ill,                  NULL }, /* ill */
2922  { CODE_FOR_insn_info,                 NULL }, /* info */
2923  { CODE_FOR_insn_infol,                NULL }, /* infol */
2924  { CODE_FOR_insn_inv,                  NULL }, /* inv */
2925  { CODE_FOR_insn_ld,                   NULL }, /* ld */
2926  { CODE_FOR_insn_ld1s,                 NULL }, /* ld1s */
2927  { CODE_FOR_insn_ld1u,                 NULL }, /* ld1u */
2928  { CODE_FOR_insn_ld2s,                 NULL }, /* ld2s */
2929  { CODE_FOR_insn_ld2u,                 NULL }, /* ld2u */
2930  { CODE_FOR_insn_ld4s,                 NULL }, /* ld4s */
2931  { CODE_FOR_insn_ld4u,                 NULL }, /* ld4u */
2932  { CODE_FOR_insn_ldna,                 NULL }, /* ldna */
2933  { CODE_FOR_insn_ldnt,                 NULL }, /* ldnt */
2934  { CODE_FOR_insn_ldnt1s,               NULL }, /* ldnt1s */
2935  { CODE_FOR_insn_ldnt1u,               NULL }, /* ldnt1u */
2936  { CODE_FOR_insn_ldnt2s,               NULL }, /* ldnt2s */
2937  { CODE_FOR_insn_ldnt2u,               NULL }, /* ldnt2u */
2938  { CODE_FOR_insn_ldnt4s,               NULL }, /* ldnt4s */
2939  { CODE_FOR_insn_ldnt4u,               NULL }, /* ldnt4u */
2940  { CODE_FOR_insn_ld_L2,                NULL }, /* ld_L2 */
2941  { CODE_FOR_insn_ld1s_L2,              NULL }, /* ld1s_L2 */
2942  { CODE_FOR_insn_ld1u_L2,              NULL }, /* ld1u_L2 */
2943  { CODE_FOR_insn_ld2s_L2,              NULL }, /* ld2s_L2 */
2944  { CODE_FOR_insn_ld2u_L2,              NULL }, /* ld2u_L2 */
2945  { CODE_FOR_insn_ld4s_L2,              NULL }, /* ld4s_L2 */
2946  { CODE_FOR_insn_ld4u_L2,              NULL }, /* ld4u_L2 */
2947  { CODE_FOR_insn_ldna_L2,              NULL }, /* ldna_L2 */
2948  { CODE_FOR_insn_ldnt_L2,              NULL }, /* ldnt_L2 */
2949  { CODE_FOR_insn_ldnt1s_L2,            NULL }, /* ldnt1s_L2 */
2950  { CODE_FOR_insn_ldnt1u_L2,            NULL }, /* ldnt1u_L2 */
2951  { CODE_FOR_insn_ldnt2s_L2,            NULL }, /* ldnt2s_L2 */
2952  { CODE_FOR_insn_ldnt2u_L2,            NULL }, /* ldnt2u_L2 */
2953  { CODE_FOR_insn_ldnt4s_L2,            NULL }, /* ldnt4s_L2 */
2954  { CODE_FOR_insn_ldnt4u_L2,            NULL }, /* ldnt4u_L2 */
2955  { CODE_FOR_insn_ld_miss,              NULL }, /* ld_miss */
2956  { CODE_FOR_insn_ld1s_miss,            NULL }, /* ld1s_miss */
2957  { CODE_FOR_insn_ld1u_miss,            NULL }, /* ld1u_miss */
2958  { CODE_FOR_insn_ld2s_miss,            NULL }, /* ld2s_miss */
2959  { CODE_FOR_insn_ld2u_miss,            NULL }, /* ld2u_miss */
2960  { CODE_FOR_insn_ld4s_miss,            NULL }, /* ld4s_miss */
2961  { CODE_FOR_insn_ld4u_miss,            NULL }, /* ld4u_miss */
2962  { CODE_FOR_insn_ldna_miss,            NULL }, /* ldna_miss */
2963  { CODE_FOR_insn_ldnt_miss,            NULL }, /* ldnt_miss */
2964  { CODE_FOR_insn_ldnt1s_miss,          NULL }, /* ldnt1s_miss */
2965  { CODE_FOR_insn_ldnt1u_miss,          NULL }, /* ldnt1u_miss */
2966  { CODE_FOR_insn_ldnt2s_miss,          NULL }, /* ldnt2s_miss */
2967  { CODE_FOR_insn_ldnt2u_miss,          NULL }, /* ldnt2u_miss */
2968  { CODE_FOR_insn_ldnt4s_miss,          NULL }, /* ldnt4s_miss */
2969  { CODE_FOR_insn_ldnt4u_miss,          NULL }, /* ldnt4u_miss */
2970  { CODE_FOR_insn_lnk,                  NULL }, /* lnk */
2971  { CODE_FOR_memory_barrier,            NULL }, /* mf */
2972  { CODE_FOR_insn_mfspr,                NULL }, /* mfspr */
2973  { CODE_FOR_insn_mm,                   NULL }, /* mm */
2974  { CODE_FOR_insn_mnz,                  NULL }, /* mnz */
2975  { CODE_FOR_movdi,                     NULL }, /* move */
2976  { CODE_FOR_insn_mtspr,                NULL }, /* mtspr */
2977  { CODE_FOR_insn_mul_hs_hs,            NULL }, /* mul_hs_hs */
2978  { CODE_FOR_insn_mul_hs_hu,            NULL }, /* mul_hs_hu */
2979  { CODE_FOR_insn_mul_hs_ls,            NULL }, /* mul_hs_ls */
2980  { CODE_FOR_insn_mul_hs_lu,            NULL }, /* mul_hs_lu */
2981  { CODE_FOR_insn_mul_hu_hu,            NULL }, /* mul_hu_hu */
2982  { CODE_FOR_insn_mul_hu_ls,            NULL }, /* mul_hu_ls */
2983  { CODE_FOR_insn_mul_hu_lu,            NULL }, /* mul_hu_lu */
2984  { CODE_FOR_insn_mul_ls_ls,            NULL }, /* mul_ls_ls */
2985  { CODE_FOR_insn_mul_ls_lu,            NULL }, /* mul_ls_lu */
2986  { CODE_FOR_insn_mul_lu_lu,            NULL }, /* mul_lu_lu */
2987  { CODE_FOR_insn_mula_hs_hs,           NULL }, /* mula_hs_hs */
2988  { CODE_FOR_insn_mula_hs_hu,           NULL }, /* mula_hs_hu */
2989  { CODE_FOR_insn_mula_hs_ls,           NULL }, /* mula_hs_ls */
2990  { CODE_FOR_insn_mula_hs_lu,           NULL }, /* mula_hs_lu */
2991  { CODE_FOR_insn_mula_hu_hu,           NULL }, /* mula_hu_hu */
2992  { CODE_FOR_insn_mula_hu_ls,           NULL }, /* mula_hu_ls */
2993  { CODE_FOR_insn_mula_hu_lu,           NULL }, /* mula_hu_lu */
2994  { CODE_FOR_insn_mula_ls_ls,           NULL }, /* mula_ls_ls */
2995  { CODE_FOR_insn_mula_ls_lu,           NULL }, /* mula_ls_lu */
2996  { CODE_FOR_insn_mula_lu_lu,           NULL }, /* mula_lu_lu */
2997  { CODE_FOR_insn_mulax,                NULL }, /* mulax */
2998  { CODE_FOR_mulsi3,                    NULL }, /* mulx */
2999  { CODE_FOR_insn_mz,                   NULL }, /* mz */
3000  { CODE_FOR_insn_nap,                  NULL }, /* nap */
3001  { CODE_FOR_nop,                       NULL }, /* nop */
3002  { CODE_FOR_insn_nor_di,               NULL }, /* nor */
3003  { CODE_FOR_iordi3,                    NULL }, /* or */
3004  { CODE_FOR_popcountdi2,               NULL }, /* pcnt */
3005  { CODE_FOR_insn_prefetch_l1,          NULL }, /* prefetch_l1 */
3006  { CODE_FOR_insn_prefetch_l1_fault,    NULL }, /* prefetch_l1_fault */
3007  { CODE_FOR_insn_prefetch_l2,          NULL }, /* prefetch_l2 */
3008  { CODE_FOR_insn_prefetch_l2_fault,    NULL }, /* prefetch_l2_fault */
3009  { CODE_FOR_insn_prefetch_l3,          NULL }, /* prefetch_l3 */
3010  { CODE_FOR_insn_prefetch_l3_fault,    NULL }, /* prefetch_l3_fault */
3011  { CODE_FOR_insn_revbits,              NULL }, /* revbits */
3012  { CODE_FOR_bswapdi2,                  NULL }, /* revbytes */
3013  { CODE_FOR_rotldi3,                   NULL }, /* rotl */
3014  { CODE_FOR_ashldi3,                   NULL }, /* shl */
3015  { CODE_FOR_insn_shl16insli,           NULL }, /* shl16insli */
3016  { CODE_FOR_insn_shl1add,              NULL }, /* shl1add */
3017  { CODE_FOR_insn_shl1addx,             NULL }, /* shl1addx */
3018  { CODE_FOR_insn_shl2add,              NULL }, /* shl2add */
3019  { CODE_FOR_insn_shl2addx,             NULL }, /* shl2addx */
3020  { CODE_FOR_insn_shl3add,              NULL }, /* shl3add */
3021  { CODE_FOR_insn_shl3addx,             NULL }, /* shl3addx */
3022  { CODE_FOR_ashlsi3,                   NULL }, /* shlx */
3023  { CODE_FOR_ashrdi3,                   NULL }, /* shrs */
3024  { CODE_FOR_lshrdi3,                   NULL }, /* shru */
3025  { CODE_FOR_lshrsi3,                   NULL }, /* shrux */
3026  { CODE_FOR_insn_shufflebytes,         NULL }, /* shufflebytes */
3027  { CODE_FOR_insn_shufflebytes1,        NULL }, /* shufflebytes1 */
3028  { CODE_FOR_insn_st,                   NULL }, /* st */
3029  { CODE_FOR_insn_st1,                  NULL }, /* st1 */
3030  { CODE_FOR_insn_st2,                  NULL }, /* st2 */
3031  { CODE_FOR_insn_st4,                  NULL }, /* st4 */
3032  { CODE_FOR_insn_stnt,                 NULL }, /* stnt */
3033  { CODE_FOR_insn_stnt1,                NULL }, /* stnt1 */
3034  { CODE_FOR_insn_stnt2,                NULL }, /* stnt2 */
3035  { CODE_FOR_insn_stnt4,                NULL }, /* stnt4 */
3036  { CODE_FOR_subdi3,                    NULL }, /* sub */
3037  { CODE_FOR_subsi3,                    NULL }, /* subx */
3038  { CODE_FOR_sssubsi3,                  NULL }, /* subxsc */
3039  { CODE_FOR_insn_tblidxb0,             NULL }, /* tblidxb0 */
3040  { CODE_FOR_insn_tblidxb1,             NULL }, /* tblidxb1 */
3041  { CODE_FOR_insn_tblidxb2,             NULL }, /* tblidxb2 */
3042  { CODE_FOR_insn_tblidxb3,             NULL }, /* tblidxb3 */
3043  { CODE_FOR_insn_v1add,                NULL }, /* v1add */
3044  { CODE_FOR_insn_v1addi,               NULL }, /* v1addi */
3045  { CODE_FOR_insn_v1adduc,              NULL }, /* v1adduc */
3046  { CODE_FOR_insn_v1adiffu,             NULL }, /* v1adiffu */
3047  { CODE_FOR_insn_v1avgu,               NULL }, /* v1avgu */
3048  { CODE_FOR_insn_v1cmpeq,              NULL }, /* v1cmpeq */
3049  { CODE_FOR_insn_v1cmpeqi,             NULL }, /* v1cmpeqi */
3050  { CODE_FOR_insn_v1cmples,             NULL }, /* v1cmples */
3051  { CODE_FOR_insn_v1cmpleu,             NULL }, /* v1cmpleu */
3052  { CODE_FOR_insn_v1cmplts,             NULL }, /* v1cmplts */
3053  { CODE_FOR_insn_v1cmpltsi,            NULL }, /* v1cmpltsi */
3054  { CODE_FOR_insn_v1cmpltu,             NULL }, /* v1cmpltu */
3055  { CODE_FOR_insn_v1cmpltui,            NULL }, /* v1cmpltui */
3056  { CODE_FOR_insn_v1cmpne,              NULL }, /* v1cmpne */
3057  { CODE_FOR_insn_v1ddotpu,             NULL }, /* v1ddotpu */
3058  { CODE_FOR_insn_v1ddotpua,            NULL }, /* v1ddotpua */
3059  { CODE_FOR_insn_v1ddotpus,            NULL }, /* v1ddotpus */
3060  { CODE_FOR_insn_v1ddotpusa,           NULL }, /* v1ddotpusa */
3061  { CODE_FOR_insn_v1dotp,               NULL }, /* v1dotp */
3062  { CODE_FOR_insn_v1dotpa,              NULL }, /* v1dotpa */
3063  { CODE_FOR_insn_v1dotpu,              NULL }, /* v1dotpu */
3064  { CODE_FOR_insn_v1dotpua,             NULL }, /* v1dotpua */
3065  { CODE_FOR_insn_v1dotpus,             NULL }, /* v1dotpus */
3066  { CODE_FOR_insn_v1dotpusa,            NULL }, /* v1dotpusa */
3067  { CODE_FOR_insn_v1int_h,              NULL }, /* v1int_h */
3068  { CODE_FOR_insn_v1int_l,              NULL }, /* v1int_l */
3069  { CODE_FOR_insn_v1maxu,               NULL }, /* v1maxu */
3070  { CODE_FOR_insn_v1maxui,              NULL }, /* v1maxui */
3071  { CODE_FOR_insn_v1minu,               NULL }, /* v1minu */
3072  { CODE_FOR_insn_v1minui,              NULL }, /* v1minui */
3073  { CODE_FOR_insn_v1mnz,                NULL }, /* v1mnz */
3074  { CODE_FOR_insn_v1multu,              NULL }, /* v1multu */
3075  { CODE_FOR_insn_v1mulu,               NULL }, /* v1mulu */
3076  { CODE_FOR_insn_v1mulus,              NULL }, /* v1mulus */
3077  { CODE_FOR_insn_v1mz,                 NULL }, /* v1mz */
3078  { CODE_FOR_insn_v1sadau,              NULL }, /* v1sadau */
3079  { CODE_FOR_insn_v1sadu,               NULL }, /* v1sadu */
3080  { CODE_FOR_insn_v1shl,                NULL }, /* v1shl */
3081  { CODE_FOR_insn_v1shl,                NULL }, /* v1shli */
3082  { CODE_FOR_insn_v1shrs,               NULL }, /* v1shrs */
3083  { CODE_FOR_insn_v1shrs,               NULL }, /* v1shrsi */
3084  { CODE_FOR_insn_v1shru,               NULL }, /* v1shru */
3085  { CODE_FOR_insn_v1shru,               NULL }, /* v1shrui */
3086  { CODE_FOR_insn_v1sub,                NULL }, /* v1sub */
3087  { CODE_FOR_insn_v1subuc,              NULL }, /* v1subuc */
3088  { CODE_FOR_insn_v2add,                NULL }, /* v2add */
3089  { CODE_FOR_insn_v2addi,               NULL }, /* v2addi */
3090  { CODE_FOR_insn_v2addsc,              NULL }, /* v2addsc */
3091  { CODE_FOR_insn_v2adiffs,             NULL }, /* v2adiffs */
3092  { CODE_FOR_insn_v2avgs,               NULL }, /* v2avgs */
3093  { CODE_FOR_insn_v2cmpeq,              NULL }, /* v2cmpeq */
3094  { CODE_FOR_insn_v2cmpeqi,             NULL }, /* v2cmpeqi */
3095  { CODE_FOR_insn_v2cmples,             NULL }, /* v2cmples */
3096  { CODE_FOR_insn_v2cmpleu,             NULL }, /* v2cmpleu */
3097  { CODE_FOR_insn_v2cmplts,             NULL }, /* v2cmplts */
3098  { CODE_FOR_insn_v2cmpltsi,            NULL }, /* v2cmpltsi */
3099  { CODE_FOR_insn_v2cmpltu,             NULL }, /* v2cmpltu */
3100  { CODE_FOR_insn_v2cmpltui,            NULL }, /* v2cmpltui */
3101  { CODE_FOR_insn_v2cmpne,              NULL }, /* v2cmpne */
3102  { CODE_FOR_insn_v2dotp,               NULL }, /* v2dotp */
3103  { CODE_FOR_insn_v2dotpa,              NULL }, /* v2dotpa */
3104  { CODE_FOR_insn_v2int_h,              NULL }, /* v2int_h */
3105  { CODE_FOR_insn_v2int_l,              NULL }, /* v2int_l */
3106  { CODE_FOR_insn_v2maxs,               NULL }, /* v2maxs */
3107  { CODE_FOR_insn_v2maxsi,              NULL }, /* v2maxsi */
3108  { CODE_FOR_insn_v2mins,               NULL }, /* v2mins */
3109  { CODE_FOR_insn_v2minsi,              NULL }, /* v2minsi */
3110  { CODE_FOR_insn_v2mnz,                NULL }, /* v2mnz */
3111  { CODE_FOR_insn_v2mulfsc,             NULL }, /* v2mulfsc */
3112  { CODE_FOR_insn_v2muls,               NULL }, /* v2muls */
3113  { CODE_FOR_insn_v2mults,              NULL }, /* v2mults */
3114  { CODE_FOR_insn_v2mz,                 NULL }, /* v2mz */
3115  { CODE_FOR_insn_v2packh,              NULL }, /* v2packh */
3116  { CODE_FOR_insn_v2packl,              NULL }, /* v2packl */
3117  { CODE_FOR_insn_v2packuc,             NULL }, /* v2packuc */
3118  { CODE_FOR_insn_v2sadas,              NULL }, /* v2sadas */
3119  { CODE_FOR_insn_v2sadau,              NULL }, /* v2sadau */
3120  { CODE_FOR_insn_v2sads,               NULL }, /* v2sads */
3121  { CODE_FOR_insn_v2sadu,               NULL }, /* v2sadu */
3122  { CODE_FOR_insn_v2shl,                NULL }, /* v2shl */
3123  { CODE_FOR_insn_v2shl,                NULL }, /* v2shli */
3124  { CODE_FOR_insn_v2shlsc,              NULL }, /* v2shlsc */
3125  { CODE_FOR_insn_v2shrs,               NULL }, /* v2shrs */
3126  { CODE_FOR_insn_v2shrs,               NULL }, /* v2shrsi */
3127  { CODE_FOR_insn_v2shru,               NULL }, /* v2shru */
3128  { CODE_FOR_insn_v2shru,               NULL }, /* v2shrui */
3129  { CODE_FOR_insn_v2sub,                NULL }, /* v2sub */
3130  { CODE_FOR_insn_v2subsc,              NULL }, /* v2subsc */
3131  { CODE_FOR_insn_v4add,                NULL }, /* v4add */
3132  { CODE_FOR_insn_v4addsc,              NULL }, /* v4addsc */
3133  { CODE_FOR_insn_v4int_h,              NULL }, /* v4int_h */
3134  { CODE_FOR_insn_v4int_l,              NULL }, /* v4int_l */
3135  { CODE_FOR_insn_v4packsc,             NULL }, /* v4packsc */
3136  { CODE_FOR_insn_v4shl,                NULL }, /* v4shl */
3137  { CODE_FOR_insn_v4shlsc,              NULL }, /* v4shlsc */
3138  { CODE_FOR_insn_v4shrs,               NULL }, /* v4shrs */
3139  { CODE_FOR_insn_v4shru,               NULL }, /* v4shru */
3140  { CODE_FOR_insn_v4sub,                NULL }, /* v4sub */
3141  { CODE_FOR_insn_v4subsc,              NULL }, /* v4subsc */
3142  { CODE_FOR_insn_wh64,                 NULL }, /* wh64 */
3143  { CODE_FOR_xordi3,                    NULL }, /* xor */
3144  { CODE_FOR_tilegx_network_barrier,    NULL }, /* network_barrier */
3145  { CODE_FOR_tilegx_idn0_receive,       NULL }, /* idn0_receive */
3146  { CODE_FOR_tilegx_idn1_receive,       NULL }, /* idn1_receive */
3147  { CODE_FOR_tilegx_idn_send,           NULL }, /* idn_send */
3148  { CODE_FOR_tilegx_udn0_receive,       NULL }, /* udn0_receive */
3149  { CODE_FOR_tilegx_udn1_receive,       NULL }, /* udn1_receive */
3150  { CODE_FOR_tilegx_udn2_receive,       NULL }, /* udn2_receive */
3151  { CODE_FOR_tilegx_udn3_receive,       NULL }, /* udn3_receive */
3152  { CODE_FOR_tilegx_udn_send,           NULL }, /* udn_send */
3153};
3154
3155
3156struct tilegx_builtin_def
3157{
3158  const char *name;
3159  enum tilegx_builtin code;
3160  bool is_const;
3161  /* The first character is the return type.  Subsequent characters
3162     are the argument types. See char_to_type.  */
3163  const char *type;
3164};
3165
3166
3167static const struct tilegx_builtin_def tilegx_builtins[] = {
3168  { "__insn_add",                TILEGX_INSN_ADD,                true,  "lll"  },
3169  { "__insn_addi",               TILEGX_INSN_ADD,                true,  "lll"  },
3170  { "__insn_addli",              TILEGX_INSN_ADD,                true,  "lll"  },
3171  { "__insn_addx",               TILEGX_INSN_ADDX,               true,  "iii"  },
3172  { "__insn_addxi",              TILEGX_INSN_ADDX,               true,  "iii"  },
3173  { "__insn_addxli",             TILEGX_INSN_ADDX,               true,  "iii"  },
3174  { "__insn_addxsc",             TILEGX_INSN_ADDXSC,             true,  "iii"  },
3175  { "__insn_and",                TILEGX_INSN_AND,                true,  "lll"  },
3176  { "__insn_andi",               TILEGX_INSN_AND,                true,  "lll"  },
3177  { "__insn_bfexts",             TILEGX_INSN_BFEXTS,             true,  "llll" },
3178  { "__insn_bfextu",             TILEGX_INSN_BFEXTU,             true,  "llll" },
3179  { "__insn_bfins",              TILEGX_INSN_BFINS,              true,  "lllll"},
3180  { "__insn_clz",                TILEGX_INSN_CLZ,                true,  "ll"   },
3181  { "__insn_cmoveqz",            TILEGX_INSN_CMOVEQZ,            true,  "llll" },
3182  { "__insn_cmovnez",            TILEGX_INSN_CMOVNEZ,            true,  "llll" },
3183  { "__insn_cmpeq",              TILEGX_INSN_CMPEQ,              true,  "lll"  },
3184  { "__insn_cmpeqi",             TILEGX_INSN_CMPEQ,              true,  "lll"  },
3185  { "__insn_cmpexch",            TILEGX_INSN_CMPEXCH,            false, "lpl"  },
3186  { "__insn_cmpexch4",           TILEGX_INSN_CMPEXCH4,           false, "ipi"  },
3187  { "__insn_cmples",             TILEGX_INSN_CMPLES,             true,  "lll"  },
3188  { "__insn_cmpleu",             TILEGX_INSN_CMPLEU,             true,  "lll"  },
3189  { "__insn_cmplts",             TILEGX_INSN_CMPLTS,             true,  "lll"  },
3190  { "__insn_cmpltsi",            TILEGX_INSN_CMPLTS,             true,  "lll"  },
3191  { "__insn_cmpltu",             TILEGX_INSN_CMPLTU,             true,  "lll"  },
3192  { "__insn_cmpltui",            TILEGX_INSN_CMPLTU,             true,  "lll"  },
3193  { "__insn_cmpne",              TILEGX_INSN_CMPNE,              true,  "lll"  },
3194  { "__insn_cmul",               TILEGX_INSN_CMUL,               true,  "lll"  },
3195  { "__insn_cmula",              TILEGX_INSN_CMULA,              true,  "llll" },
3196  { "__insn_cmulaf",             TILEGX_INSN_CMULAF,             true,  "llll" },
3197  { "__insn_cmulf",              TILEGX_INSN_CMULF,              true,  "lll"  },
3198  { "__insn_cmulfr",             TILEGX_INSN_CMULFR,             true,  "lll"  },
3199  { "__insn_cmulh",              TILEGX_INSN_CMULH,              true,  "lll"  },
3200  { "__insn_cmulhr",             TILEGX_INSN_CMULHR,             true,  "lll"  },
3201  { "__insn_crc32_32",           TILEGX_INSN_CRC32_32,           true,  "lll"  },
3202  { "__insn_crc32_8",            TILEGX_INSN_CRC32_8,            true,  "lll"  },
3203  { "__insn_ctz",                TILEGX_INSN_CTZ,                true,  "ll"   },
3204  { "__insn_dblalign",           TILEGX_INSN_DBLALIGN,           true,  "lllk" },
3205  { "__insn_dblalign2",          TILEGX_INSN_DBLALIGN2,          true,  "lll"  },
3206  { "__insn_dblalign4",          TILEGX_INSN_DBLALIGN4,          true,  "lll"  },
3207  { "__insn_dblalign6",          TILEGX_INSN_DBLALIGN6,          true,  "lll"  },
3208  { "__insn_drain",              TILEGX_INSN_DRAIN,              false, "v"    },
3209  { "__insn_dtlbpr",             TILEGX_INSN_DTLBPR,             false, "vl"   },
3210  { "__insn_exch",               TILEGX_INSN_EXCH,               false, "lpl"  },
3211  { "__insn_exch4",              TILEGX_INSN_EXCH4,              false, "ipi"  },
3212  { "__insn_fdouble_add_flags",  TILEGX_INSN_FDOUBLE_ADD_FLAGS,  true,  "lll"  },
3213  { "__insn_fdouble_addsub",     TILEGX_INSN_FDOUBLE_ADDSUB,     true,  "llll" },
3214  { "__insn_fdouble_mul_flags",  TILEGX_INSN_FDOUBLE_MUL_FLAGS,  true,  "lll"  },
3215  { "__insn_fdouble_pack1",      TILEGX_INSN_FDOUBLE_PACK1,      true,  "lll"  },
3216  { "__insn_fdouble_pack2",      TILEGX_INSN_FDOUBLE_PACK2,      true,  "llll" },
3217  { "__insn_fdouble_sub_flags",  TILEGX_INSN_FDOUBLE_SUB_FLAGS,  true,  "lll"  },
3218  { "__insn_fdouble_unpack_max", TILEGX_INSN_FDOUBLE_UNPACK_MAX, true,  "lll"  },
3219  { "__insn_fdouble_unpack_min", TILEGX_INSN_FDOUBLE_UNPACK_MIN, true,  "lll"  },
3220  { "__insn_fetchadd",           TILEGX_INSN_FETCHADD,           false, "lpl"  },
3221  { "__insn_fetchadd4",          TILEGX_INSN_FETCHADD4,          false, "ipi"  },
3222  { "__insn_fetchaddgez",        TILEGX_INSN_FETCHADDGEZ,        false, "lpl"  },
3223  { "__insn_fetchaddgez4",       TILEGX_INSN_FETCHADDGEZ4,       false, "ipi"  },
3224  { "__insn_fetchand",           TILEGX_INSN_FETCHAND,           false, "lpl"  },
3225  { "__insn_fetchand4",          TILEGX_INSN_FETCHAND4,          false, "ipi"  },
3226  { "__insn_fetchor",            TILEGX_INSN_FETCHOR,            false, "lpl"  },
3227  { "__insn_fetchor4",           TILEGX_INSN_FETCHOR4,           false, "ipi"  },
3228  { "__insn_finv",               TILEGX_INSN_FINV,               false, "vk"   },
3229  { "__insn_flush",              TILEGX_INSN_FLUSH,              false, "vk"   },
3230  { "__insn_flushwb",            TILEGX_INSN_FLUSHWB,            false, "v"    },
3231  { "__insn_fnop",               TILEGX_INSN_FNOP,               false, "v"    },
3232  { "__insn_fsingle_add1",       TILEGX_INSN_FSINGLE_ADD1,       true,  "lll"  },
3233  { "__insn_fsingle_addsub2",    TILEGX_INSN_FSINGLE_ADDSUB2,    true,  "llll" },
3234  { "__insn_fsingle_mul1",       TILEGX_INSN_FSINGLE_MUL1,       true,  "lll"  },
3235  { "__insn_fsingle_mul2",       TILEGX_INSN_FSINGLE_MUL2,       true,  "lll"  },
3236  { "__insn_fsingle_pack1",      TILEGX_INSN_FSINGLE_PACK1,      true,  "ll"   },
3237  { "__insn_fsingle_pack2",      TILEGX_INSN_FSINGLE_PACK2,      true,  "lll"  },
3238  { "__insn_fsingle_sub1",       TILEGX_INSN_FSINGLE_SUB1,       true,  "lll"  },
3239  { "__insn_icoh",               TILEGX_INSN_ICOH,               false, "vk"   },
3240  { "__insn_ill",                TILEGX_INSN_ILL,                false, "v"    },
3241  { "__insn_info",               TILEGX_INSN_INFO,               false, "vl"   },
3242  { "__insn_infol",              TILEGX_INSN_INFOL,              false, "vl"   },
3243  { "__insn_inv",                TILEGX_INSN_INV,                false, "vp"   },
3244  { "__insn_ld",                 TILEGX_INSN_LD,                 false, "lk"   },
3245  { "__insn_ld1s",               TILEGX_INSN_LD1S,               false, "lk"   },
3246  { "__insn_ld1u",               TILEGX_INSN_LD1U,               false, "lk"   },
3247  { "__insn_ld2s",               TILEGX_INSN_LD2S,               false, "lk"   },
3248  { "__insn_ld2u",               TILEGX_INSN_LD2U,               false, "lk"   },
3249  { "__insn_ld4s",               TILEGX_INSN_LD4S,               false, "lk"   },
3250  { "__insn_ld4u",               TILEGX_INSN_LD4U,               false, "lk"   },
3251  { "__insn_ldna",               TILEGX_INSN_LDNA,               false, "lk"   },
3252  { "__insn_ldnt",               TILEGX_INSN_LDNT,               false, "lk"   },
3253  { "__insn_ldnt1s",             TILEGX_INSN_LDNT1S,             false, "lk"   },
3254  { "__insn_ldnt1u",             TILEGX_INSN_LDNT1U,             false, "lk"   },
3255  { "__insn_ldnt2s",             TILEGX_INSN_LDNT2S,             false, "lk"   },
3256  { "__insn_ldnt2u",             TILEGX_INSN_LDNT2U,             false, "lk"   },
3257  { "__insn_ldnt4s",             TILEGX_INSN_LDNT4S,             false, "lk"   },
3258  { "__insn_ldnt4u",             TILEGX_INSN_LDNT4U,             false, "lk"   },
3259  { "__insn_ld_L2",              TILEGX_INSN_LD_L2,              false, "lk"   },
3260  { "__insn_ld1s_L2",            TILEGX_INSN_LD1S_L2,            false, "lk"   },
3261  { "__insn_ld1u_L2",            TILEGX_INSN_LD1U_L2,            false, "lk"   },
3262  { "__insn_ld2s_L2",            TILEGX_INSN_LD2S_L2,            false, "lk"   },
3263  { "__insn_ld2u_L2",            TILEGX_INSN_LD2U_L2,            false, "lk"   },
3264  { "__insn_ld4s_L2",            TILEGX_INSN_LD4S_L2,            false, "lk"   },
3265  { "__insn_ld4u_L2",            TILEGX_INSN_LD4U_L2,            false, "lk"   },
3266  { "__insn_ldna_L2",            TILEGX_INSN_LDNA_L2,            false, "lk"   },
3267  { "__insn_ldnt_L2",            TILEGX_INSN_LDNT_L2,            false, "lk"   },
3268  { "__insn_ldnt1s_L2",          TILEGX_INSN_LDNT1S_L2,          false, "lk"   },
3269  { "__insn_ldnt1u_L2",          TILEGX_INSN_LDNT1U_L2,          false, "lk"   },
3270  { "__insn_ldnt2s_L2",          TILEGX_INSN_LDNT2S_L2,          false, "lk"   },
3271  { "__insn_ldnt2u_L2",          TILEGX_INSN_LDNT2U_L2,          false, "lk"   },
3272  { "__insn_ldnt4s_L2",          TILEGX_INSN_LDNT4S_L2,          false, "lk"   },
3273  { "__insn_ldnt4u_L2",          TILEGX_INSN_LDNT4U_L2,          false, "lk"   },
3274  { "__insn_ld_miss",            TILEGX_INSN_LD_MISS,            false, "lk"   },
3275  { "__insn_ld1s_miss",          TILEGX_INSN_LD1S_MISS,          false, "lk"   },
3276  { "__insn_ld1u_miss",          TILEGX_INSN_LD1U_MISS,          false, "lk"   },
3277  { "__insn_ld2s_miss",          TILEGX_INSN_LD2S_MISS,          false, "lk"   },
3278  { "__insn_ld2u_miss",          TILEGX_INSN_LD2U_MISS,          false, "lk"   },
3279  { "__insn_ld4s_miss",          TILEGX_INSN_LD4S_MISS,          false, "lk"   },
3280  { "__insn_ld4u_miss",          TILEGX_INSN_LD4U_MISS,          false, "lk"   },
3281  { "__insn_ldna_miss",          TILEGX_INSN_LDNA_MISS,          false, "lk"   },
3282  { "__insn_ldnt_miss",          TILEGX_INSN_LDNT_MISS,          false, "lk"   },
3283  { "__insn_ldnt1s_miss",        TILEGX_INSN_LDNT1S_MISS,        false, "lk"   },
3284  { "__insn_ldnt1u_miss",        TILEGX_INSN_LDNT1U_MISS,        false, "lk"   },
3285  { "__insn_ldnt2s_miss",        TILEGX_INSN_LDNT2S_MISS,        false, "lk"   },
3286  { "__insn_ldnt2u_miss",        TILEGX_INSN_LDNT2U_MISS,        false, "lk"   },
3287  { "__insn_ldnt4s_miss",        TILEGX_INSN_LDNT4S_MISS,        false, "lk"   },
3288  { "__insn_ldnt4u_miss",        TILEGX_INSN_LDNT4U_MISS,        false, "lk"   },
3289  { "__insn_lnk",                TILEGX_INSN_LNK,                true,  "l"    },
3290  { "__insn_mf",                 TILEGX_INSN_MF,                 false, "v"    },
3291  { "__insn_mfspr",              TILEGX_INSN_MFSPR,              false, "ll"   },
3292  { "__insn_mm",                 TILEGX_INSN_MM,                 true,  "lllll"},
3293  { "__insn_mnz",                TILEGX_INSN_MNZ,                true,  "lll"  },
3294  { "__insn_move",               TILEGX_INSN_MOVE,               true,  "ll"   },
3295  { "__insn_movei",              TILEGX_INSN_MOVE,               true,  "ll"   },
3296  { "__insn_moveli",             TILEGX_INSN_MOVE,               true,  "ll"   },
3297  { "__insn_mtspr",              TILEGX_INSN_MTSPR,              false, "vll"  },
3298  { "__insn_mul_hs_hs",          TILEGX_INSN_MUL_HS_HS,          true,  "lll"  },
3299  { "__insn_mul_hs_hu",          TILEGX_INSN_MUL_HS_HU,          true,  "lll"  },
3300  { "__insn_mul_hs_ls",          TILEGX_INSN_MUL_HS_LS,          true,  "lll"  },
3301  { "__insn_mul_hs_lu",          TILEGX_INSN_MUL_HS_LU,          true,  "lll"  },
3302  { "__insn_mul_hu_hu",          TILEGX_INSN_MUL_HU_HU,          true,  "lll"  },
3303  { "__insn_mul_hu_ls",          TILEGX_INSN_MUL_HU_LS,          true,  "lll"  },
3304  { "__insn_mul_hu_lu",          TILEGX_INSN_MUL_HU_LU,          true,  "lll"  },
3305  { "__insn_mul_ls_ls",          TILEGX_INSN_MUL_LS_LS,          true,  "lll"  },
3306  { "__insn_mul_ls_lu",          TILEGX_INSN_MUL_LS_LU,          true,  "lll"  },
3307  { "__insn_mul_lu_lu",          TILEGX_INSN_MUL_LU_LU,          true,  "lll"  },
3308  { "__insn_mula_hs_hs",         TILEGX_INSN_MULA_HS_HS,         true,  "llll" },
3309  { "__insn_mula_hs_hu",         TILEGX_INSN_MULA_HS_HU,         true,  "llll" },
3310  { "__insn_mula_hs_ls",         TILEGX_INSN_MULA_HS_LS,         true,  "llll" },
3311  { "__insn_mula_hs_lu",         TILEGX_INSN_MULA_HS_LU,         true,  "llll" },
3312  { "__insn_mula_hu_hu",         TILEGX_INSN_MULA_HU_HU,         true,  "llll" },
3313  { "__insn_mula_hu_ls",         TILEGX_INSN_MULA_HU_LS,         true,  "llll" },
3314  { "__insn_mula_hu_lu",         TILEGX_INSN_MULA_HU_LU,         true,  "llll" },
3315  { "__insn_mula_ls_ls",         TILEGX_INSN_MULA_LS_LS,         true,  "llll" },
3316  { "__insn_mula_ls_lu",         TILEGX_INSN_MULA_LS_LU,         true,  "llll" },
3317  { "__insn_mula_lu_lu",         TILEGX_INSN_MULA_LU_LU,         true,  "llll" },
3318  { "__insn_mulax",              TILEGX_INSN_MULAX,              true,  "iiii" },
3319  { "__insn_mulx",               TILEGX_INSN_MULX,               true,  "iii"  },
3320  { "__insn_mz",                 TILEGX_INSN_MZ,                 true,  "lll"  },
3321  { "__insn_nap",                TILEGX_INSN_NAP,                false, "v"    },
3322  { "__insn_nop",                TILEGX_INSN_NOP,                true,  "v"    },
3323  { "__insn_nor",                TILEGX_INSN_NOR,                true,  "lll"  },
3324  { "__insn_or",                 TILEGX_INSN_OR,                 true,  "lll"  },
3325  { "__insn_ori",                TILEGX_INSN_OR,                 true,  "lll"  },
3326  { "__insn_pcnt",               TILEGX_INSN_PCNT,               true,  "ll"   },
3327  { "__insn_prefetch",           TILEGX_INSN_PREFETCH_L1,        false, "vk"   },
3328  { "__insn_prefetch_l1",        TILEGX_INSN_PREFETCH_L1,        false, "vk"   },
3329  { "__insn_prefetch_l1_fault",  TILEGX_INSN_PREFETCH_L1_FAULT,  false, "vk"   },
3330  { "__insn_prefetch_l2",        TILEGX_INSN_PREFETCH_L2,        false, "vk"   },
3331  { "__insn_prefetch_l2_fault",  TILEGX_INSN_PREFETCH_L2_FAULT,  false, "vk"   },
3332  { "__insn_prefetch_l3",        TILEGX_INSN_PREFETCH_L3,        false, "vk"   },
3333  { "__insn_prefetch_l3_fault",  TILEGX_INSN_PREFETCH_L3_FAULT,  false, "vk"   },
3334  { "__insn_revbits",            TILEGX_INSN_REVBITS,            true,  "ll"   },
3335  { "__insn_revbytes",           TILEGX_INSN_REVBYTES,           true,  "ll"   },
3336  { "__insn_rotl",               TILEGX_INSN_ROTL,               true,  "lli"  },
3337  { "__insn_rotli",              TILEGX_INSN_ROTL,               true,  "lli"  },
3338  { "__insn_shl",                TILEGX_INSN_SHL,                true,  "lli"  },
3339  { "__insn_shl16insli",         TILEGX_INSN_SHL16INSLI,         true,  "lll"  },
3340  { "__insn_shl1add",            TILEGX_INSN_SHL1ADD,            true,  "lll"  },
3341  { "__insn_shl1addx",           TILEGX_INSN_SHL1ADDX,           true,  "iii"  },
3342  { "__insn_shl2add",            TILEGX_INSN_SHL2ADD,            true,  "lll"  },
3343  { "__insn_shl2addx",           TILEGX_INSN_SHL2ADDX,           true,  "iii"  },
3344  { "__insn_shl3add",            TILEGX_INSN_SHL3ADD,            true,  "lll"  },
3345  { "__insn_shl3addx",           TILEGX_INSN_SHL3ADDX,           true,  "iii"  },
3346  { "__insn_shli",               TILEGX_INSN_SHL,                true,  "lli"  },
3347  { "__insn_shlx",               TILEGX_INSN_SHLX,               true,  "iii"  },
3348  { "__insn_shlxi",              TILEGX_INSN_SHLX,               true,  "iii"  },
3349  { "__insn_shrs",               TILEGX_INSN_SHRS,               true,  "lli"  },
3350  { "__insn_shrsi",              TILEGX_INSN_SHRS,               true,  "lli"  },
3351  { "__insn_shru",               TILEGX_INSN_SHRU,               true,  "lli"  },
3352  { "__insn_shrui",              TILEGX_INSN_SHRU,               true,  "lli"  },
3353  { "__insn_shrux",              TILEGX_INSN_SHRUX,              true,  "iii"  },
3354  { "__insn_shruxi",             TILEGX_INSN_SHRUX,              true,  "iii"  },
3355  { "__insn_shufflebytes",       TILEGX_INSN_SHUFFLEBYTES,       true,  "llll" },
3356  { "__insn_shufflebytes1",      TILEGX_INSN_SHUFFLEBYTES1,      true,  "lll"  },
3357  { "__insn_st",                 TILEGX_INSN_ST,                 false, "vpl"  },
3358  { "__insn_st1",                TILEGX_INSN_ST1,                false, "vpl"  },
3359  { "__insn_st2",                TILEGX_INSN_ST2,                false, "vpl"  },
3360  { "__insn_st4",                TILEGX_INSN_ST4,                false, "vpl"  },
3361  { "__insn_stnt",               TILEGX_INSN_STNT,               false, "vpl"  },
3362  { "__insn_stnt1",              TILEGX_INSN_STNT1,              false, "vpl"  },
3363  { "__insn_stnt2",              TILEGX_INSN_STNT2,              false, "vpl"  },
3364  { "__insn_stnt4",              TILEGX_INSN_STNT4,              false, "vpl"  },
3365  { "__insn_sub",                TILEGX_INSN_SUB,                true,  "lll"  },
3366  { "__insn_subx",               TILEGX_INSN_SUBX,               true,  "iii"  },
3367  { "__insn_subxsc",             TILEGX_INSN_SUBXSC,             true,  "iii"  },
3368  { "__insn_tblidxb0",           TILEGX_INSN_TBLIDXB0,           true,  "lll"  },
3369  { "__insn_tblidxb1",           TILEGX_INSN_TBLIDXB1,           true,  "lll"  },
3370  { "__insn_tblidxb2",           TILEGX_INSN_TBLIDXB2,           true,  "lll"  },
3371  { "__insn_tblidxb3",           TILEGX_INSN_TBLIDXB3,           true,  "lll"  },
3372  { "__insn_v1add",              TILEGX_INSN_V1ADD,              true,  "lll"  },
3373  { "__insn_v1addi",             TILEGX_INSN_V1ADDI,             true,  "lll"  },
3374  { "__insn_v1adduc",            TILEGX_INSN_V1ADDUC,            true,  "lll"  },
3375  { "__insn_v1adiffu",           TILEGX_INSN_V1ADIFFU,           true,  "lll"  },
3376  { "__insn_v1avgu",             TILEGX_INSN_V1AVGU,             true,  "lll"  },
3377  { "__insn_v1cmpeq",            TILEGX_INSN_V1CMPEQ,            true,  "lll"  },
3378  { "__insn_v1cmpeqi",           TILEGX_INSN_V1CMPEQI,           true,  "lll"  },
3379  { "__insn_v1cmples",           TILEGX_INSN_V1CMPLES,           true,  "lll"  },
3380  { "__insn_v1cmpleu",           TILEGX_INSN_V1CMPLEU,           true,  "lll"  },
3381  { "__insn_v1cmplts",           TILEGX_INSN_V1CMPLTS,           true,  "lll"  },
3382  { "__insn_v1cmpltsi",          TILEGX_INSN_V1CMPLTSI,          true,  "lll"  },
3383  { "__insn_v1cmpltu",           TILEGX_INSN_V1CMPLTU,           true,  "lll"  },
3384  { "__insn_v1cmpltui",          TILEGX_INSN_V1CMPLTUI,          true,  "lll"  },
3385  { "__insn_v1cmpne",            TILEGX_INSN_V1CMPNE,            true,  "lll"  },
3386  { "__insn_v1ddotpu",           TILEGX_INSN_V1DDOTPU,           true,  "lll"  },
3387  { "__insn_v1ddotpua",          TILEGX_INSN_V1DDOTPUA,          true,  "llll" },
3388  { "__insn_v1ddotpus",          TILEGX_INSN_V1DDOTPUS,          true,  "lll"  },
3389  { "__insn_v1ddotpusa",         TILEGX_INSN_V1DDOTPUSA,         true,  "llll" },
3390  { "__insn_v1dotp",             TILEGX_INSN_V1DOTP,             true,  "lll"  },
3391  { "__insn_v1dotpa",            TILEGX_INSN_V1DOTPA,            true,  "llll" },
3392  { "__insn_v1dotpu",            TILEGX_INSN_V1DOTPU,            true,  "lll"  },
3393  { "__insn_v1dotpua",           TILEGX_INSN_V1DOTPUA,           true,  "llll" },
3394  { "__insn_v1dotpus",           TILEGX_INSN_V1DOTPUS,           true,  "lll"  },
3395  { "__insn_v1dotpusa",          TILEGX_INSN_V1DOTPUSA,          true,  "llll" },
3396  { "__insn_v1int_h",            TILEGX_INSN_V1INT_H,            true,  "lll"  },
3397  { "__insn_v1int_l",            TILEGX_INSN_V1INT_L,            true,  "lll"  },
3398  { "__insn_v1maxu",             TILEGX_INSN_V1MAXU,             true,  "lll"  },
3399  { "__insn_v1maxui",            TILEGX_INSN_V1MAXUI,            true,  "lll"  },
3400  { "__insn_v1minu",             TILEGX_INSN_V1MINU,             true,  "lll"  },
3401  { "__insn_v1minui",            TILEGX_INSN_V1MINUI,            true,  "lll"  },
3402  { "__insn_v1mnz",              TILEGX_INSN_V1MNZ,              true,  "lll"  },
3403  { "__insn_v1multu",            TILEGX_INSN_V1MULTU,            true,  "lll"  },
3404  { "__insn_v1mulu",             TILEGX_INSN_V1MULU,             true,  "lll"  },
3405  { "__insn_v1mulus",            TILEGX_INSN_V1MULUS,            true,  "lll"  },
3406  { "__insn_v1mz",               TILEGX_INSN_V1MZ,               true,  "lll"  },
3407  { "__insn_v1sadau",            TILEGX_INSN_V1SADAU,            true,  "llll" },
3408  { "__insn_v1sadu",             TILEGX_INSN_V1SADU,             true,  "lll"  },
3409  { "__insn_v1shl",              TILEGX_INSN_V1SHL,              true,  "lll"  },
3410  { "__insn_v1shli",             TILEGX_INSN_V1SHLI,             true,  "lll"  },
3411  { "__insn_v1shrs",             TILEGX_INSN_V1SHRS,             true,  "lll"  },
3412  { "__insn_v1shrsi",            TILEGX_INSN_V1SHRSI,            true,  "lll"  },
3413  { "__insn_v1shru",             TILEGX_INSN_V1SHRU,             true,  "lll"  },
3414  { "__insn_v1shrui",            TILEGX_INSN_V1SHRUI,            true,  "lll"  },
3415  { "__insn_v1sub",              TILEGX_INSN_V1SUB,              true,  "lll"  },
3416  { "__insn_v1subuc",            TILEGX_INSN_V1SUBUC,            true,  "lll"  },
3417  { "__insn_v2add",              TILEGX_INSN_V2ADD,              true,  "lll"  },
3418  { "__insn_v2addi",             TILEGX_INSN_V2ADDI,             true,  "lll"  },
3419  { "__insn_v2addsc",            TILEGX_INSN_V2ADDSC,            true,  "lll"  },
3420  { "__insn_v2adiffs",           TILEGX_INSN_V2ADIFFS,           true,  "lll"  },
3421  { "__insn_v2avgs",             TILEGX_INSN_V2AVGS,             true,  "lll"  },
3422  { "__insn_v2cmpeq",            TILEGX_INSN_V2CMPEQ,            true,  "lll"  },
3423  { "__insn_v2cmpeqi",           TILEGX_INSN_V2CMPEQI,           true,  "lll"  },
3424  { "__insn_v2cmples",           TILEGX_INSN_V2CMPLES,           true,  "lll"  },
3425  { "__insn_v2cmpleu",           TILEGX_INSN_V2CMPLEU,           true,  "lll"  },
3426  { "__insn_v2cmplts",           TILEGX_INSN_V2CMPLTS,           true,  "lll"  },
3427  { "__insn_v2cmpltsi",          TILEGX_INSN_V2CMPLTSI,          true,  "lll"  },
3428  { "__insn_v2cmpltu",           TILEGX_INSN_V2CMPLTU,           true,  "lll"  },
3429  { "__insn_v2cmpltui",          TILEGX_INSN_V2CMPLTUI,          true,  "lll"  },
3430  { "__insn_v2cmpne",            TILEGX_INSN_V2CMPNE,            true,  "lll"  },
3431  { "__insn_v2dotp",             TILEGX_INSN_V2DOTP,             true,  "lll"  },
3432  { "__insn_v2dotpa",            TILEGX_INSN_V2DOTPA,            true,  "llll" },
3433  { "__insn_v2int_h",            TILEGX_INSN_V2INT_H,            true,  "lll"  },
3434  { "__insn_v2int_l",            TILEGX_INSN_V2INT_L,            true,  "lll"  },
3435  { "__insn_v2maxs",             TILEGX_INSN_V2MAXS,             true,  "lll"  },
3436  { "__insn_v2maxsi",            TILEGX_INSN_V2MAXSI,            true,  "lll"  },
3437  { "__insn_v2mins",             TILEGX_INSN_V2MINS,             true,  "lll"  },
3438  { "__insn_v2minsi",            TILEGX_INSN_V2MINSI,            true,  "lll"  },
3439  { "__insn_v2mnz",              TILEGX_INSN_V2MNZ,              true,  "lll"  },
3440  { "__insn_v2mulfsc",           TILEGX_INSN_V2MULFSC,           true,  "lll"  },
3441  { "__insn_v2muls",             TILEGX_INSN_V2MULS,             true,  "lll"  },
3442  { "__insn_v2mults",            TILEGX_INSN_V2MULTS,            true,  "lll"  },
3443  { "__insn_v2mz",               TILEGX_INSN_V2MZ,               true,  "lll"  },
3444  { "__insn_v2packh",            TILEGX_INSN_V2PACKH,            true,  "lll"  },
3445  { "__insn_v2packl",            TILEGX_INSN_V2PACKL,            true,  "lll"  },
3446  { "__insn_v2packuc",           TILEGX_INSN_V2PACKUC,           true,  "lll"  },
3447  { "__insn_v2sadas",            TILEGX_INSN_V2SADAS,            true,  "llll" },
3448  { "__insn_v2sadau",            TILEGX_INSN_V2SADAU,            true,  "llll" },
3449  { "__insn_v2sads",             TILEGX_INSN_V2SADS,             true,  "lll"  },
3450  { "__insn_v2sadu",             TILEGX_INSN_V2SADU,             true,  "lll"  },
3451  { "__insn_v2shl",              TILEGX_INSN_V2SHL,              true,  "lll"  },
3452  { "__insn_v2shli",             TILEGX_INSN_V2SHLI,             true,  "lll"  },
3453  { "__insn_v2shlsc",            TILEGX_INSN_V2SHLSC,            true,  "lll"  },
3454  { "__insn_v2shrs",             TILEGX_INSN_V2SHRS,             true,  "lll"  },
3455  { "__insn_v2shrsi",            TILEGX_INSN_V2SHRSI,            true,  "lll"  },
3456  { "__insn_v2shru",             TILEGX_INSN_V2SHRU,             true,  "lll"  },
3457  { "__insn_v2shrui",            TILEGX_INSN_V2SHRUI,            true,  "lll"  },
3458  { "__insn_v2sub",              TILEGX_INSN_V2SUB,              true,  "lll"  },
3459  { "__insn_v2subsc",            TILEGX_INSN_V2SUBSC,            true,  "lll"  },
3460  { "__insn_v4add",              TILEGX_INSN_V4ADD,              true,  "lll"  },
3461  { "__insn_v4addsc",            TILEGX_INSN_V4ADDSC,            true,  "lll"  },
3462  { "__insn_v4int_h",            TILEGX_INSN_V4INT_H,            true,  "lll"  },
3463  { "__insn_v4int_l",            TILEGX_INSN_V4INT_L,            true,  "lll"  },
3464  { "__insn_v4packsc",           TILEGX_INSN_V4PACKSC,           true,  "lll"  },
3465  { "__insn_v4shl",              TILEGX_INSN_V4SHL,              true,  "lll"  },
3466  { "__insn_v4shlsc",            TILEGX_INSN_V4SHLSC,            true,  "lll"  },
3467  { "__insn_v4shrs",             TILEGX_INSN_V4SHRS,             true,  "lll"  },
3468  { "__insn_v4shru",             TILEGX_INSN_V4SHRU,             true,  "lll"  },
3469  { "__insn_v4sub",              TILEGX_INSN_V4SUB,              true,  "lll"  },
3470  { "__insn_v4subsc",            TILEGX_INSN_V4SUBSC,            true,  "lll"  },
3471  { "__insn_wh64",               TILEGX_INSN_WH64,               false, "vp"   },
3472  { "__insn_xor",                TILEGX_INSN_XOR,                true,  "lll"  },
3473  { "__insn_xori",               TILEGX_INSN_XOR,                true,  "lll"  },
3474  { "__tile_network_barrier",    TILEGX_NETWORK_BARRIER,         false, "v"    },
3475  { "__tile_idn0_receive",       TILEGX_IDN0_RECEIVE,            false, "l"    },
3476  { "__tile_idn1_receive",       TILEGX_IDN1_RECEIVE,            false, "l"    },
3477  { "__tile_idn_send",           TILEGX_IDN_SEND,                false, "vl"   },
3478  { "__tile_udn0_receive",       TILEGX_UDN0_RECEIVE,            false, "l"    },
3479  { "__tile_udn1_receive",       TILEGX_UDN1_RECEIVE,            false, "l"    },
3480  { "__tile_udn2_receive",       TILEGX_UDN2_RECEIVE,            false, "l"    },
3481  { "__tile_udn3_receive",       TILEGX_UDN3_RECEIVE,            false, "l"    },
3482  { "__tile_udn_send",           TILEGX_UDN_SEND,                false, "vl"   },
3483};
3484
3485
3486/* Convert a character in a builtin type string to a tree type.  */
3487static tree
3488char_to_type (char c)
3489{
3490  static tree volatile_ptr_type_node = NULL;
3491  static tree volatile_const_ptr_type_node = NULL;
3492
3493  if (volatile_ptr_type_node == NULL)
3494    {
3495      volatile_ptr_type_node =
3496	build_pointer_type (build_qualified_type (void_type_node,
3497						  TYPE_QUAL_VOLATILE));
3498      volatile_const_ptr_type_node =
3499	build_pointer_type (build_qualified_type (void_type_node,
3500						  TYPE_QUAL_CONST
3501						  | TYPE_QUAL_VOLATILE));
3502    }
3503
3504  switch (c)
3505    {
3506    case 'v':
3507      return void_type_node;
3508    case 'i':
3509      return unsigned_type_node;
3510    case 'l':
3511      return long_long_unsigned_type_node;
3512    case 'p':
3513      return volatile_ptr_type_node;
3514    case 'k':
3515      return volatile_const_ptr_type_node;
3516    default:
3517      gcc_unreachable ();
3518    }
3519}
3520
3521
3522/* Implement TARGET_INIT_BUILTINS.  */
3523static void
3524tilegx_init_builtins (void)
3525{
3526  size_t i;
3527
3528  for (i = 0; i < ARRAY_SIZE (tilegx_builtins); i++)
3529    {
3530      const struct tilegx_builtin_def *p = &tilegx_builtins[i];
3531      tree ftype, ret_type, arg_type_list = void_list_node;
3532      tree decl;
3533      int j;
3534
3535      for (j = strlen (p->type) - 1; j > 0; j--)
3536	{
3537	  arg_type_list =
3538	    tree_cons (NULL_TREE, char_to_type (p->type[j]), arg_type_list);
3539	}
3540
3541      ret_type = char_to_type (p->type[0]);
3542
3543      ftype = build_function_type (ret_type, arg_type_list);
3544
3545      decl = add_builtin_function (p->name, ftype, p->code, BUILT_IN_MD,
3546				   NULL, NULL);
3547
3548      if (p->is_const)
3549	TREE_READONLY (decl) = 1;
3550      TREE_NOTHROW (decl) = 1;
3551
3552      if (tilegx_builtin_info[p->code].fndecl == NULL)
3553	tilegx_builtin_info[p->code].fndecl = decl;
3554    }
3555}
3556
3557
3558/* Implement TARGET_EXPAND_BUILTIN.  */
3559static rtx
3560tilegx_expand_builtin (tree exp,
3561		       rtx target,
3562		       rtx subtarget ATTRIBUTE_UNUSED,
3563		       machine_mode mode ATTRIBUTE_UNUSED,
3564		       int ignore ATTRIBUTE_UNUSED)
3565{
3566#define MAX_BUILTIN_ARGS 4
3567
3568  tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
3569  unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
3570  tree arg;
3571  call_expr_arg_iterator iter;
3572  enum insn_code icode;
3573  rtx op[MAX_BUILTIN_ARGS + 1], pat;
3574  int opnum;
3575  bool nonvoid;
3576  insn_gen_fn fn;
3577
3578  if (fcode >= TILEGX_BUILTIN_max)
3579    internal_error ("bad builtin fcode");
3580  icode = tilegx_builtin_info[fcode].icode;
3581  if (icode == 0)
3582    internal_error ("bad builtin icode");
3583
3584  nonvoid = TREE_TYPE (TREE_TYPE (fndecl)) != void_type_node;
3585
3586  opnum = nonvoid;
3587  FOR_EACH_CALL_EXPR_ARG (arg, iter, exp)
3588    {
3589      const struct insn_operand_data *insn_op;
3590
3591      if (arg == error_mark_node)
3592	return NULL_RTX;
3593      if (opnum > MAX_BUILTIN_ARGS)
3594	return NULL_RTX;
3595
3596      insn_op = &insn_data[icode].operand[opnum];
3597
3598      op[opnum] = expand_expr (arg, NULL_RTX, insn_op->mode, EXPAND_NORMAL);
3599
3600      if (!(*insn_op->predicate) (op[opnum], insn_op->mode))
3601	{
3602	  machine_mode opmode = insn_op->mode;
3603
3604	  /* pointer_operand and pmode_register_operand operands do
3605	     not specify a mode, so use the operand's mode instead
3606	     (which should always be right by the time we get here,
3607	     except for constants, which are VOIDmode).  */
3608	  if (opmode == VOIDmode)
3609	    {
3610	      machine_mode m = GET_MODE (op[opnum]);
3611	      gcc_assert (m == Pmode || m == VOIDmode);
3612	      opmode = Pmode;
3613	    }
3614
3615	  op[opnum] = copy_to_mode_reg (opmode, op[opnum]);
3616	}
3617
3618      if (!(*insn_op->predicate) (op[opnum], insn_op->mode))
3619	{
3620	  /* We still failed to meet the predicate even after moving
3621	     into a register. Assume we needed an immediate.  */
3622	  error_at (EXPR_LOCATION (exp),
3623		    "operand must be an immediate of the right size");
3624	  return const0_rtx;
3625	}
3626
3627      opnum++;
3628    }
3629
3630  if (nonvoid)
3631    {
3632      machine_mode tmode = insn_data[icode].operand[0].mode;
3633      if (!target
3634	  || GET_MODE (target) != tmode
3635	  || !(*insn_data[icode].operand[0].predicate) (target, tmode))
3636	{
3637	  if (tmode == VOIDmode)
3638	    {
3639	      /* get the mode from the return type.  */
3640	      tmode = TYPE_MODE (TREE_TYPE (TREE_TYPE (fndecl)));
3641	    }
3642	  target = gen_reg_rtx (tmode);
3643	}
3644      op[0] = target;
3645    }
3646
3647  fn = GEN_FCN (icode);
3648  switch (opnum)
3649    {
3650    case 0:
3651      pat = fn (NULL_RTX);
3652      break;
3653    case 1:
3654      pat = fn (op[0]);
3655      break;
3656    case 2:
3657      pat = fn (op[0], op[1]);
3658      break;
3659    case 3:
3660      pat = fn (op[0], op[1], op[2]);
3661      break;
3662    case 4:
3663      pat = fn (op[0], op[1], op[2], op[3]);
3664      break;
3665    case 5:
3666      pat = fn (op[0], op[1], op[2], op[3], op[4]);
3667      break;
3668    default:
3669      gcc_unreachable ();
3670    }
3671  if (!pat)
3672    return NULL_RTX;
3673
3674  /* If we are generating a prefetch, tell the scheduler not to move
3675     it around.  */
3676  if (GET_CODE (pat) == PREFETCH)
3677    PREFETCH_SCHEDULE_BARRIER_P (pat) = true;
3678
3679  emit_insn (pat);
3680
3681  if (nonvoid)
3682    return target;
3683  else
3684    return const0_rtx;
3685}
3686
3687
3688/* Implement TARGET_BUILTIN_DECL.  */
3689static tree
3690tilegx_builtin_decl (unsigned code, bool initialize_p ATTRIBUTE_UNUSED)
3691{
3692  if (code >= TILEGX_BUILTIN_max)
3693    return error_mark_node;
3694
3695  return tilegx_builtin_info[code].fndecl;
3696}
3697
3698
3699
3700/* Stack frames  */
3701
3702/* Return whether REGNO needs to be saved in the stack frame.  */
3703static bool
3704need_to_save_reg (unsigned int regno)
3705{
3706  if (!fixed_regs[regno] && !call_used_regs[regno]
3707      && df_regs_ever_live_p (regno))
3708    return true;
3709
3710  if (flag_pic
3711      && (regno == PIC_OFFSET_TABLE_REGNUM
3712	  || regno == TILEGX_PIC_TEXT_LABEL_REGNUM)
3713      && (crtl->uses_pic_offset_table || crtl->saves_all_registers))
3714    return true;
3715
3716  if (crtl->calls_eh_return)
3717    {
3718      unsigned i;
3719      for (i = 0; EH_RETURN_DATA_REGNO (i) != INVALID_REGNUM; i++)
3720	{
3721	  if (regno == EH_RETURN_DATA_REGNO (i))
3722	    return true;
3723	}
3724    }
3725
3726  return false;
3727}
3728
3729
3730/* Return the size of the register savev area.  This function is only
3731   correct starting with local register allocation */
3732static int
3733tilegx_saved_regs_size (void)
3734{
3735  int reg_save_size = 0;
3736  int regno;
3737  int offset_to_frame;
3738  int align_mask;
3739
3740  for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
3741    if (need_to_save_reg (regno))
3742      reg_save_size += UNITS_PER_WORD;
3743
3744  /* Pad out the register save area if necessary to make
3745     frame_pointer_rtx be as aligned as the stack pointer.  */
3746  offset_to_frame = crtl->args.pretend_args_size + reg_save_size;
3747  align_mask = (STACK_BOUNDARY / BITS_PER_UNIT) - 1;
3748  reg_save_size += (-offset_to_frame) & align_mask;
3749
3750  return reg_save_size;
3751}
3752
3753
3754/* Round up frame size SIZE.  */
3755static int
3756round_frame_size (int size)
3757{
3758  return ((size + STACK_BOUNDARY / BITS_PER_UNIT - 1)
3759	  & -STACK_BOUNDARY / BITS_PER_UNIT);
3760}
3761
3762
3763/* Emit a store in the stack frame to save REGNO at address ADDR, and
3764   emit the corresponding REG_CFA_OFFSET note described by CFA and
3765   CFA_OFFSET.  Return the emitted insn.  */
3766static rtx
3767frame_emit_store (int regno, int regno_note, rtx addr, rtx cfa,
3768		  int cfa_offset)
3769{
3770  rtx reg = gen_rtx_REG (DImode, regno);
3771  rtx mem = gen_frame_mem (DImode, addr);
3772  rtx mov = gen_movdi (mem, reg);
3773
3774  /* Describe what just happened in a way that dwarf understands.  We
3775     use temporary registers to hold the address to make scheduling
3776     easier, and use the REG_CFA_OFFSET to describe the address as an
3777     offset from the CFA.  */
3778  rtx reg_note = gen_rtx_REG (DImode, regno_note);
3779  rtx cfa_relative_addr = gen_rtx_PLUS (Pmode, cfa, GEN_INT (cfa_offset));
3780  rtx cfa_relative_mem = gen_frame_mem (DImode, cfa_relative_addr);
3781  rtx real = gen_rtx_SET (VOIDmode, cfa_relative_mem, reg_note);
3782  add_reg_note (mov, REG_CFA_OFFSET, real);
3783
3784  return emit_insn (mov);
3785}
3786
3787
3788/* Emit a load in the stack frame to load REGNO from address ADDR.
3789   Add a REG_CFA_RESTORE note to CFA_RESTORES if CFA_RESTORES is
3790   non-null.  Return the emitted insn.  */
3791static rtx_insn *
3792frame_emit_load (int regno, rtx addr, rtx *cfa_restores)
3793{
3794  rtx reg = gen_rtx_REG (DImode, regno);
3795  rtx mem = gen_frame_mem (DImode, addr);
3796  if (cfa_restores)
3797    *cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg, *cfa_restores);
3798  return emit_insn (gen_movdi (reg, mem));
3799}
3800
3801
3802/* Helper function to set RTX_FRAME_RELATED_P on instructions,
3803   including sequences.  */
3804static rtx
3805set_frame_related_p (void)
3806{
3807  rtx_insn *seq = get_insns ();
3808  rtx_insn *insn;
3809
3810  end_sequence ();
3811
3812  if (!seq)
3813    return NULL_RTX;
3814
3815  if (INSN_P (seq))
3816    {
3817      insn = seq;
3818      while (insn != NULL_RTX)
3819	{
3820	  RTX_FRAME_RELATED_P (insn) = 1;
3821	  insn = NEXT_INSN (insn);
3822	}
3823      seq = emit_insn (seq);
3824    }
3825  else
3826    {
3827      seq = emit_insn (seq);
3828      RTX_FRAME_RELATED_P (seq) = 1;
3829    }
3830  return seq;
3831}
3832
3833
3834#define FRP(exp)  (start_sequence (), exp, set_frame_related_p ())
3835
3836/* This emits code for 'sp += offset'.
3837
3838   The ABI only allows us to modify 'sp' in a single 'addi' or
3839   'addli', so the backtracer understands it. Larger amounts cannot
3840   use those instructions, so are added by placing the offset into a
3841   large register and using 'add'.
3842
3843   This happens after reload, so we need to expand it ourselves.  */
3844static rtx_insn *
3845emit_sp_adjust (int offset, int *next_scratch_regno, bool frame_related,
3846		rtx reg_notes)
3847{
3848  rtx to_add;
3849  rtx imm_rtx = GEN_INT (offset);
3850  rtx pat;
3851  rtx_insn *insn;
3852
3853  if (satisfies_constraint_J (imm_rtx))
3854    {
3855      /* We can add this using a single immediate add.  */
3856      to_add = imm_rtx;
3857    }
3858  else
3859    {
3860      rtx tmp = gen_rtx_REG (Pmode, (*next_scratch_regno)--);
3861      tilegx_expand_set_const64 (tmp, imm_rtx);
3862      to_add = tmp;
3863    }
3864
3865  /* Actually adjust the stack pointer.  */
3866  if (TARGET_32BIT)
3867    pat = gen_sp_adjust_32bit (stack_pointer_rtx, stack_pointer_rtx, to_add);
3868  else
3869    pat = gen_sp_adjust (stack_pointer_rtx, stack_pointer_rtx, to_add);
3870
3871  insn = emit_insn (pat);
3872  REG_NOTES (insn) = reg_notes;
3873
3874  /* Describe what just happened in a way that dwarf understands.  */
3875  if (frame_related)
3876    {
3877      rtx real = gen_rtx_SET (VOIDmode, stack_pointer_rtx,
3878			      gen_rtx_PLUS (Pmode, stack_pointer_rtx,
3879					    imm_rtx));
3880      RTX_FRAME_RELATED_P (insn) = 1;
3881      add_reg_note (insn, REG_CFA_ADJUST_CFA, real);
3882    }
3883
3884  return insn;
3885}
3886
3887
3888/* Return whether the current function is leaf.  This takes into
3889   account whether the function calls tls_get_addr.  */
3890static bool
3891tilegx_current_function_is_leaf (void)
3892{
3893  return crtl->is_leaf && !cfun->machine->calls_tls_get_addr;
3894}
3895
3896
3897/* Return the frame size.  */
3898static int
3899compute_total_frame_size (void)
3900{
3901  int total_size = (get_frame_size () + tilegx_saved_regs_size ()
3902		    + crtl->outgoing_args_size
3903		    + crtl->args.pretend_args_size);
3904
3905  if (!tilegx_current_function_is_leaf () || cfun->calls_alloca)
3906    {
3907      /* Make room for save area in callee.  */
3908      total_size += STACK_POINTER_OFFSET;
3909    }
3910
3911  return round_frame_size (total_size);
3912}
3913
3914
3915/* Return nonzero if this function is known to have a null epilogue.
3916   This allows the optimizer to omit jumps to jumps if no stack was
3917   created.  */
3918bool
3919tilegx_can_use_return_insn_p (void)
3920{
3921  return (reload_completed
3922	  && cfun->static_chain_decl == 0
3923	  && compute_total_frame_size () == 0
3924	  && tilegx_current_function_is_leaf ()
3925	  && !crtl->profile && !df_regs_ever_live_p (TILEGX_LINK_REGNUM));
3926}
3927
3928
3929/* Returns an rtx for a stack slot at 'FP + offset_from_fp'.  If there
3930   is a frame pointer, it computes the value relative to
3931   that. Otherwise it uses the stack pointer.  */
3932static rtx
3933compute_frame_addr (int offset_from_fp, int *next_scratch_regno)
3934{
3935  rtx base_reg_rtx, tmp_reg_rtx, offset_rtx;
3936  int offset_from_base;
3937
3938  if (frame_pointer_needed)
3939    {
3940      base_reg_rtx = hard_frame_pointer_rtx;
3941      offset_from_base = offset_from_fp;
3942    }
3943  else
3944    {
3945      int offset_from_sp = compute_total_frame_size () + offset_from_fp;
3946      offset_from_base = offset_from_sp;
3947      base_reg_rtx = stack_pointer_rtx;
3948    }
3949
3950  if (offset_from_base == 0)
3951    return base_reg_rtx;
3952
3953  /* Compute the new value of the stack pointer.  */
3954  tmp_reg_rtx = gen_rtx_REG (Pmode, (*next_scratch_regno)--);
3955  offset_rtx = GEN_INT (offset_from_base);
3956
3957  if (!add_operand (offset_rtx, Pmode))
3958    {
3959      expand_set_cint64 (tmp_reg_rtx, offset_rtx);
3960      offset_rtx = tmp_reg_rtx;
3961    }
3962
3963  emit_insn (gen_rtx_SET (VOIDmode, tmp_reg_rtx,
3964			  gen_rtx_PLUS (Pmode, base_reg_rtx, offset_rtx)));
3965
3966  return tmp_reg_rtx;
3967}
3968
3969
3970/* The stack frame looks like this:
3971         +-------------+
3972         |    ...      |
3973         |  incoming   |
3974         | stack args  |
3975   AP -> +-------------+
3976         | caller's HFP|
3977         +-------------+
3978         | lr save     |
3979  HFP -> +-------------+
3980         |  var args   |
3981         |  reg save   | crtl->args.pretend_args_size bytes
3982         +-------------+
3983         |    ...      |
3984         | saved regs  | tilegx_saved_regs_size() bytes
3985   FP -> +-------------+
3986         |    ...      |
3987         |   vars      | get_frame_size() bytes
3988         +-------------+
3989         |    ...      |
3990         |  outgoing   |
3991         |  stack args | crtl->outgoing_args_size bytes
3992         +-------------+
3993         | HFP         | ptr_size bytes (only here if nonleaf / alloca)
3994         +-------------+
3995         | callee lr   | ptr_size bytes (only here if nonleaf / alloca)
3996         | save        |
3997   SP -> +-------------+
3998
3999  HFP == incoming SP.
4000
4001  For functions with a frame larger than 32767 bytes, or which use
4002  alloca (), r52 is used as a frame pointer.  Otherwise there is no
4003  frame pointer.
4004
4005  FP is saved at SP+ptr_size before calling a subroutine so the callee
4006  can chain.  */
4007void
4008tilegx_expand_prologue (void)
4009{
4010#define ROUND_ROBIN_SIZE 4
4011  /* We round-robin through four scratch registers to hold temporary
4012     addresses for saving registers, to make instruction scheduling
4013     easier.  */
4014  rtx reg_save_addr[ROUND_ROBIN_SIZE] = {
4015    NULL_RTX, NULL_RTX, NULL_RTX, NULL_RTX
4016  };
4017  rtx insn, cfa;
4018  unsigned int which_scratch;
4019  int offset, start_offset, regno;
4020
4021  /* A register that holds a copy of the incoming fp.  */
4022  int fp_copy_regno = -1;
4023
4024  /* A register that holds a copy of the incoming sp.  */
4025  int sp_copy_regno = -1;
4026
4027  /* Next scratch register number to hand out (postdecrementing).  */
4028  int next_scratch_regno = 29;
4029
4030  int total_size = compute_total_frame_size ();
4031
4032  if (flag_stack_usage_info)
4033    current_function_static_stack_size = total_size;
4034
4035  /* Save lr first in its special location because code after this
4036     might use the link register as a scratch register.  */
4037  if (df_regs_ever_live_p (TILEGX_LINK_REGNUM) || crtl->calls_eh_return)
4038    FRP (frame_emit_store (TILEGX_LINK_REGNUM, TILEGX_LINK_REGNUM,
4039			   stack_pointer_rtx, stack_pointer_rtx, 0));
4040
4041  if (total_size == 0)
4042    {
4043      /* Load the PIC register if needed.  */
4044      if (flag_pic && crtl->uses_pic_offset_table)
4045	load_pic_register (false);
4046
4047      return;
4048    }
4049
4050  cfa = stack_pointer_rtx;
4051
4052  if (frame_pointer_needed)
4053    {
4054      fp_copy_regno = next_scratch_regno--;
4055
4056      /* Copy the old frame pointer aside so we can save it later.  */
4057      insn =
4058	FRP (emit_move_insn (gen_rtx_REG (word_mode, fp_copy_regno),
4059			     gen_lowpart (word_mode, hard_frame_pointer_rtx)));
4060      add_reg_note (insn, REG_CFA_REGISTER, NULL_RTX);
4061
4062      /* Set up the frame pointer.  */
4063      insn = FRP (emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx));
4064      add_reg_note (insn, REG_CFA_DEF_CFA, hard_frame_pointer_rtx);
4065      cfa = hard_frame_pointer_rtx;
4066      REGNO_POINTER_ALIGN (HARD_FRAME_POINTER_REGNUM) = STACK_BOUNDARY;
4067
4068      /* fp holds a copy of the incoming sp, in case we need to store
4069	 it.  */
4070      sp_copy_regno = HARD_FRAME_POINTER_REGNUM;
4071    }
4072  else if (!tilegx_current_function_is_leaf ())
4073    {
4074      /* Copy the old stack pointer aside so we can save it later.  */
4075      sp_copy_regno = next_scratch_regno--;
4076      emit_move_insn (gen_rtx_REG (Pmode, sp_copy_regno),
4077		      stack_pointer_rtx);
4078    }
4079
4080  if (tilegx_current_function_is_leaf ())
4081    {
4082      /* No need to store chain pointer to caller's frame.  */
4083      emit_sp_adjust (-total_size, &next_scratch_regno,
4084		      !frame_pointer_needed, NULL_RTX);
4085    }
4086  else
4087    {
4088      /* Save the frame pointer (incoming sp value) to support
4089         backtracing.  First we need to create an rtx with the store
4090         address.  */
4091      rtx chain_addr = gen_rtx_REG (Pmode, next_scratch_regno--);
4092      rtx size_rtx = GEN_INT (-(total_size - UNITS_PER_WORD));
4093
4094      if (add_operand (size_rtx, Pmode))
4095	{
4096	  /* Expose more parallelism by computing this value from the
4097	     original stack pointer, not the one after we have pushed
4098	     the frame.  */
4099	  rtx p = gen_rtx_PLUS (Pmode, stack_pointer_rtx, size_rtx);
4100	  emit_insn (gen_rtx_SET (VOIDmode, chain_addr, p));
4101	  emit_sp_adjust (-total_size, &next_scratch_regno,
4102			  !frame_pointer_needed, NULL_RTX);
4103	}
4104      else
4105	{
4106	  /* The stack frame is large, so just store the incoming sp
4107	     value at *(new_sp + UNITS_PER_WORD).  */
4108	  rtx p;
4109	  emit_sp_adjust (-total_size, &next_scratch_regno,
4110			  !frame_pointer_needed, NULL_RTX);
4111	  p = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
4112			    GEN_INT (UNITS_PER_WORD));
4113	  emit_insn (gen_rtx_SET (VOIDmode, chain_addr, p));
4114	}
4115
4116      /* Save our frame pointer for backtrace chaining.  */
4117      emit_insn (gen_movdi (gen_frame_mem (DImode, chain_addr),
4118			    gen_rtx_REG (DImode, sp_copy_regno)));
4119    }
4120
4121  /* Compute where to start storing registers we need to save.  */
4122  start_offset = -crtl->args.pretend_args_size - UNITS_PER_WORD;
4123  offset = start_offset;
4124
4125  /* Store all registers that need saving.  */
4126  which_scratch = 0;
4127  for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; regno--)
4128    if (need_to_save_reg (regno))
4129      {
4130	rtx r = reg_save_addr[which_scratch];
4131	int from_regno;
4132	int cfa_offset = frame_pointer_needed ? offset : total_size + offset;
4133
4134	if (r == NULL_RTX)
4135	  {
4136	    int prev_scratch_regno = next_scratch_regno;
4137	    r = compute_frame_addr (offset, &next_scratch_regno);
4138	    if (prev_scratch_regno != next_scratch_regno)
4139	      reg_save_addr[which_scratch] = r;
4140	  }
4141	else
4142	  {
4143	    /* Advance to the next stack slot to store this
4144	       register.  */
4145	    int stride = ROUND_ROBIN_SIZE * -UNITS_PER_WORD;
4146	    rtx p = gen_rtx_PLUS (Pmode, r, GEN_INT (stride));
4147	    emit_insn (gen_rtx_SET (VOIDmode, r, p));
4148	  }
4149
4150	/* Save this register to the stack (but use the old fp value
4151	   we copied aside if appropriate).  */
4152	from_regno =
4153	  (fp_copy_regno >= 0 && regno == HARD_FRAME_POINTER_REGNUM)
4154	  ? fp_copy_regno : regno;
4155	FRP (frame_emit_store (from_regno, regno, r, cfa, cfa_offset));
4156
4157	offset -= UNITS_PER_WORD;
4158	which_scratch = (which_scratch + 1) % ROUND_ROBIN_SIZE;
4159      }
4160
4161  /* If profiling, force that to happen after the frame is set up.  */
4162  if (crtl->profile)
4163    emit_insn (gen_blockage ());
4164
4165  /* Load the PIC register if needed.  */
4166  if (flag_pic && crtl->uses_pic_offset_table)
4167    load_pic_register (false);
4168}
4169
4170
4171/* Implement the epilogue and sibcall_epilogue patterns.  SIBCALL_P is
4172   true for a sibcall_epilogue pattern, and false for an epilogue
4173   pattern.  */
4174void
4175tilegx_expand_epilogue (bool sibcall_p)
4176{
4177  /* We round-robin through four scratch registers to hold temporary
4178     addresses for saving registers, to make instruction scheduling
4179     easier.  */
4180  rtx reg_save_addr[ROUND_ROBIN_SIZE] = {
4181    NULL_RTX, NULL_RTX, NULL_RTX, NULL_RTX
4182  };
4183  rtx_insn *last_insn, *insn;
4184  unsigned int which_scratch;
4185  int offset, start_offset, regno;
4186  rtx cfa_restores = NULL_RTX;
4187
4188  /* A register that holds a copy of the incoming fp.  */
4189  int fp_copy_regno = -1;
4190
4191  /* Next scratch register number to hand out (postdecrementing).  */
4192  int next_scratch_regno = 29;
4193
4194  int total_size = compute_total_frame_size ();
4195
4196  last_insn = get_last_insn ();
4197
4198  /* Load lr first since we are going to need it first.  */
4199  insn = NULL;
4200  if (df_regs_ever_live_p (TILEGX_LINK_REGNUM))
4201    {
4202      insn = frame_emit_load (TILEGX_LINK_REGNUM,
4203			      compute_frame_addr (0, &next_scratch_regno),
4204			      &cfa_restores);
4205    }
4206
4207  if (total_size == 0)
4208    {
4209      if (insn)
4210	{
4211	  RTX_FRAME_RELATED_P (insn) = 1;
4212	  REG_NOTES (insn) = cfa_restores;
4213	}
4214      goto done;
4215    }
4216
4217  /* Compute where to start restoring registers.  */
4218  start_offset = -crtl->args.pretend_args_size - UNITS_PER_WORD;
4219  offset = start_offset;
4220
4221  if (frame_pointer_needed)
4222    fp_copy_regno = next_scratch_regno--;
4223
4224  /* Restore all callee-saved registers.  */
4225  which_scratch = 0;
4226  for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; regno--)
4227    if (need_to_save_reg (regno))
4228      {
4229	rtx r = reg_save_addr[which_scratch];
4230	if (r == NULL_RTX)
4231	  {
4232	    r = compute_frame_addr (offset, &next_scratch_regno);
4233	    reg_save_addr[which_scratch] = r;
4234	  }
4235	else
4236	  {
4237	    /* Advance to the next stack slot to store this register.  */
4238	    int stride = ROUND_ROBIN_SIZE * -UNITS_PER_WORD;
4239	    rtx p = gen_rtx_PLUS (Pmode, r, GEN_INT (stride));
4240	    emit_insn (gen_rtx_SET (VOIDmode, r, p));
4241	  }
4242
4243	if (fp_copy_regno >= 0 && regno == HARD_FRAME_POINTER_REGNUM)
4244	  frame_emit_load (fp_copy_regno, r, NULL);
4245	else
4246	  frame_emit_load (regno, r, &cfa_restores);
4247
4248	offset -= UNITS_PER_WORD;
4249	which_scratch = (which_scratch + 1) % ROUND_ROBIN_SIZE;
4250      }
4251
4252  if (!tilegx_current_function_is_leaf ())
4253    cfa_restores =
4254      alloc_reg_note (REG_CFA_RESTORE, stack_pointer_rtx, cfa_restores);
4255
4256  emit_insn (gen_blockage ());
4257
4258  if (frame_pointer_needed)
4259    {
4260      /* Restore the old stack pointer by copying from the frame
4261	 pointer.  */
4262      if (TARGET_32BIT)
4263	{
4264	  insn = emit_insn (gen_sp_restore_32bit (stack_pointer_rtx,
4265						  hard_frame_pointer_rtx));
4266	}
4267      else
4268	{
4269	  insn = emit_insn (gen_sp_restore (stack_pointer_rtx,
4270					    hard_frame_pointer_rtx));
4271	}
4272      RTX_FRAME_RELATED_P (insn) = 1;
4273      REG_NOTES (insn) = cfa_restores;
4274      add_reg_note (insn, REG_CFA_DEF_CFA, stack_pointer_rtx);
4275    }
4276  else
4277    {
4278      insn = emit_sp_adjust (total_size, &next_scratch_regno, true,
4279			     cfa_restores);
4280    }
4281
4282  if (crtl->calls_eh_return)
4283    {
4284      if (TARGET_32BIT)
4285	emit_insn (gen_sp_adjust_32bit (stack_pointer_rtx, stack_pointer_rtx,
4286					EH_RETURN_STACKADJ_RTX));
4287      else
4288	emit_insn (gen_sp_adjust (stack_pointer_rtx, stack_pointer_rtx,
4289				  EH_RETURN_STACKADJ_RTX));
4290    }
4291
4292  /* Restore the old frame pointer.  */
4293  if (frame_pointer_needed)
4294    {
4295      insn = emit_move_insn (gen_lowpart (DImode, hard_frame_pointer_rtx),
4296			     gen_rtx_REG (DImode, fp_copy_regno));
4297      add_reg_note (insn, REG_CFA_RESTORE, hard_frame_pointer_rtx);
4298    }
4299
4300  /* Mark the pic registers as live outside of the function.  */
4301  if (flag_pic)
4302    {
4303      emit_use (cfun->machine->text_label_rtx);
4304      emit_use (cfun->machine->got_rtx);
4305    }
4306
4307done:
4308  if (!sibcall_p)
4309    {
4310      emit_jump_insn (gen__return ());
4311    }
4312  else
4313    {
4314      emit_use (gen_rtx_REG (Pmode, TILEGX_LINK_REGNUM));
4315    }
4316
4317  /* Mark all insns we just emitted as frame-related.  */
4318  for (; last_insn != NULL_RTX; last_insn = next_insn (last_insn))
4319    RTX_FRAME_RELATED_P (last_insn) = 1;
4320}
4321
4322#undef ROUND_ROBIN_SIZE
4323
4324
4325/* Implement INITIAL_ELIMINATION_OFFSET.  */
4326int
4327tilegx_initial_elimination_offset (int from, int to)
4328{
4329  int total_size = compute_total_frame_size ();
4330
4331  if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
4332    {
4333      return (total_size - crtl->args.pretend_args_size
4334	      - tilegx_saved_regs_size ());
4335    }
4336  else if (from == FRAME_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM)
4337    {
4338      return -(crtl->args.pretend_args_size + tilegx_saved_regs_size ());
4339    }
4340  else if (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
4341    {
4342      return STACK_POINTER_OFFSET + total_size;
4343    }
4344  else if (from == ARG_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM)
4345    {
4346      return STACK_POINTER_OFFSET;
4347    }
4348  else
4349    gcc_unreachable ();
4350}
4351
4352
4353/* Return an RTX indicating where the return address to the calling
4354   function can be found.  */
4355rtx
4356tilegx_return_addr (int count, rtx frame ATTRIBUTE_UNUSED)
4357{
4358  if (count != 0)
4359    return const0_rtx;
4360
4361  return get_hard_reg_initial_val (Pmode, TILEGX_LINK_REGNUM);
4362}
4363
4364
4365/* Implement EH_RETURN_HANDLER_RTX.  The MEM needs to be volatile to
4366   prevent it from being deleted.  */
4367rtx
4368tilegx_eh_return_handler_rtx (void)
4369{
4370  rtx tmp = gen_frame_mem (Pmode, hard_frame_pointer_rtx);
4371  MEM_VOLATILE_P (tmp) = true;
4372  return tmp;
4373}
4374
4375
4376
4377/* Registers  */
4378
4379/* Implemnet TARGET_CONDITIONAL_REGISTER_USAGE.  */
4380static void
4381tilegx_conditional_register_usage (void)
4382{
4383  global_regs[TILEGX_NETORDER_REGNUM] = 1;
4384  /* TILEGX_PIC_TEXT_LABEL_REGNUM is conditionally used.  It is a
4385     member of fixed_regs, and therefore must be member of
4386     call_used_regs, but it is not a member of call_really_used_regs[]
4387     because it is not clobbered by a call.  */
4388  if (TILEGX_PIC_TEXT_LABEL_REGNUM != INVALID_REGNUM)
4389    {
4390      fixed_regs[TILEGX_PIC_TEXT_LABEL_REGNUM] = 1;
4391      call_used_regs[TILEGX_PIC_TEXT_LABEL_REGNUM] = 1;
4392    }
4393  if (PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM)
4394    {
4395      fixed_regs[PIC_OFFSET_TABLE_REGNUM] = 1;
4396      call_used_regs[PIC_OFFSET_TABLE_REGNUM] = 1;
4397    }
4398}
4399
4400
4401/* Implement TARGET_FRAME_POINTER_REQUIRED.  */
4402static bool
4403tilegx_frame_pointer_required (void)
4404{
4405  return crtl->calls_eh_return || cfun->calls_alloca;
4406}
4407
4408
4409
4410/* Scheduling and reorg  */
4411
4412/* Return the length of INSN.  LENGTH is the initial length computed
4413   by attributes in the machine-description file.  This is where we
4414   account for bundles.  */
4415int
4416tilegx_adjust_insn_length (rtx_insn *insn, int length)
4417{
4418  machine_mode mode = GET_MODE (insn);
4419
4420  /* A non-termininating instruction in a bundle has length 0.  */
4421  if (mode == SImode)
4422    return 0;
4423
4424  /* By default, there is not length adjustment.  */
4425  return length;
4426}
4427
4428
4429/* Implement TARGET_SCHED_ISSUE_RATE.  */
4430static int
4431tilegx_issue_rate (void)
4432{
4433  return 3;
4434}
4435
4436
4437/* Return the rtx for the jump target.  */
4438static rtx
4439get_jump_target (rtx branch)
4440{
4441  if (CALL_P (branch))
4442    {
4443      rtx call;
4444      call = PATTERN (branch);
4445
4446      if (GET_CODE (call) == PARALLEL)
4447	call = XVECEXP (call, 0, 0);
4448
4449      if (GET_CODE (call) == SET)
4450	call = SET_SRC (call);
4451
4452      if (GET_CODE (call) == CALL)
4453	return XEXP (XEXP (call, 0), 0);
4454    }
4455  return 0;
4456}
4457
4458
4459/* Implement TARGET_SCHED_ADJUST_COST.  */
4460static int
4461tilegx_sched_adjust_cost (rtx_insn *insn, rtx link, rtx_insn *dep_insn,
4462			  int cost)
4463{
4464  /* If we have a true dependence, INSN is a call, and DEP_INSN
4465     defines a register that is needed by the call (argument or stack
4466     pointer) , set its latency to 0 so that it can be bundled with
4467     the call.  Explicitly check for and exclude the case when
4468     DEP_INSN defines the target of the jump.  */
4469  if (CALL_P (insn) && REG_NOTE_KIND (link) == REG_DEP_TRUE)
4470    {
4471      rtx target = get_jump_target (insn);
4472      if (!REG_P (target) || !set_of (target, dep_insn))
4473	return 0;
4474    }
4475
4476  return cost;
4477}
4478
4479
4480/* Skip over irrelevant NOTEs and such and look for the next insn we
4481   would consider bundling.  */
4482static rtx_insn *
4483next_insn_to_bundle (rtx_insn *r, rtx_insn *end)
4484{
4485  for (; r != end; r = NEXT_INSN (r))
4486    {
4487      if (NONDEBUG_INSN_P (r)
4488	  && GET_CODE (PATTERN (r)) != USE
4489	  && GET_CODE (PATTERN (r)) != CLOBBER)
4490	return r;
4491    }
4492
4493  return NULL;
4494}
4495
4496
4497/* Go through all insns, and use the information generated during
4498   scheduling to generate SEQUENCEs to represent bundles of
4499   instructions issued simultaneously.  */
4500static void
4501tilegx_gen_bundles (void)
4502{
4503  basic_block bb;
4504  FOR_EACH_BB_FN (bb, cfun)
4505    {
4506      rtx_insn *insn, *next, *prev;
4507      rtx_insn *end = NEXT_INSN (BB_END (bb));
4508
4509      prev = NULL;
4510      for (insn = next_insn_to_bundle (BB_HEAD (bb), end); insn;
4511	   prev = insn, insn = next)
4512	{
4513	  next = next_insn_to_bundle (NEXT_INSN (insn), end);
4514
4515	  /* Never wrap {} around inline asm.  */
4516	  if (GET_CODE (PATTERN (insn)) != ASM_INPUT)
4517	    {
4518	      if (next == NULL_RTX || GET_MODE (next) == TImode
4519		  /* NOTE: The scheduler incorrectly believes a call
4520		     insn can execute in the same cycle as the insn
4521		     after the call.  This is of course impossible.
4522		     Really we need to fix the scheduler somehow, so
4523		     the code after the call gets scheduled
4524		     optimally.  */
4525		  || CALL_P (insn))
4526		{
4527		  /* Mark current insn as the end of a bundle.  */
4528		  PUT_MODE (insn, QImode);
4529		}
4530	      else
4531		{
4532		  /* Mark it as part of a bundle.  */
4533		  PUT_MODE (insn, SImode);
4534		}
4535	    }
4536
4537	  /* Delete barrier insns, because they can mess up the
4538	     emitting of bundle braces.  If it is end-of-bundle, then
4539	     the previous insn must be marked end-of-bundle.  */
4540	  if (get_attr_type (insn) == TYPE_NOTHING) {
4541	    if (GET_MODE (insn) == QImode && prev != NULL
4542		&& GET_MODE (prev) == SImode)
4543	      {
4544		PUT_MODE (prev, QImode);
4545	      }
4546	    delete_insn (insn);
4547	  }
4548	}
4549    }
4550}
4551
4552
4553/* Replace OLD_INSN with NEW_INSN.  */
4554static void
4555replace_insns (rtx_insn *old_insn, rtx_insn *new_insns)
4556{
4557  if (new_insns)
4558    emit_insn_before (new_insns, old_insn);
4559
4560  delete_insn (old_insn);
4561}
4562
4563
4564/* Returns true if INSN is the first instruction of a pc-relative
4565   address compuatation.  */
4566static bool
4567match_pcrel_step1 (rtx insn)
4568{
4569  rtx pattern = PATTERN (insn);
4570  rtx src;
4571
4572  if (GET_CODE (pattern) != SET)
4573    return false;
4574
4575  src = SET_SRC (pattern);
4576
4577  return (GET_CODE (src) == CONST
4578	  && GET_CODE (XEXP (src, 0)) == UNSPEC
4579	  && XINT (XEXP (src, 0), 1) == UNSPEC_HW1_LAST_PCREL);
4580}
4581
4582
4583/* Do the first replacement step in tilegx_fixup_pcrel_references.  */
4584static void
4585replace_mov_pcrel_step1 (rtx_insn *insn)
4586{
4587  rtx pattern = PATTERN (insn);
4588  rtx unspec;
4589  rtx opnds[2];
4590  rtx_insn *new_insns;
4591
4592  gcc_assert (GET_CODE (pattern) == SET);
4593  opnds[0] = SET_DEST (pattern);
4594
4595  gcc_assert (GET_CODE (SET_SRC (pattern)) == CONST);
4596
4597  unspec = XEXP (SET_SRC (pattern), 0);
4598  gcc_assert (GET_CODE (unspec) == UNSPEC);
4599  gcc_assert (XINT (unspec, 1) == UNSPEC_HW1_LAST_PCREL);
4600  opnds[1] = XVECEXP (unspec, 0, 0);
4601
4602  /* We only need to replace SYMBOL_REFs, not LABEL_REFs.  */
4603  if (GET_CODE (opnds[1]) != SYMBOL_REF)
4604    return;
4605
4606  start_sequence ();
4607
4608  if (flag_pic != 1)
4609    {
4610      if (TARGET_32BIT)
4611	emit_insn (gen_mov_got32_step1_32bit (opnds[0], opnds[1]));
4612      else
4613	emit_insn (gen_mov_got32_step1 (opnds[0], opnds[1]));
4614    }
4615
4616  new_insns = get_insns ();
4617  end_sequence ();
4618
4619  replace_insns (insn, new_insns);
4620}
4621
4622
4623/* Returns true if INSN is the second instruction of a pc-relative
4624   address compuatation.  */
4625static bool
4626match_pcrel_step2 (rtx_insn *insn)
4627{
4628  rtx unspec;
4629  rtx addr;
4630
4631  if (TARGET_32BIT)
4632    {
4633      if (recog_memoized (insn) != CODE_FOR_insn_addr_shl16insli_32bit)
4634	return false;
4635    }
4636  else
4637    {
4638      if (recog_memoized (insn) != CODE_FOR_insn_addr_shl16insli)
4639	return false;
4640    }
4641
4642  unspec = SET_SRC (PATTERN (insn));
4643  addr = XVECEXP (unspec, 0, 1);
4644
4645  return (GET_CODE (addr) == CONST
4646	  && GET_CODE (XEXP (addr, 0)) == UNSPEC
4647	  && XINT (XEXP (addr, 0), 1) == UNSPEC_HW0_PCREL);
4648}
4649
4650
4651/* Do the second replacement step in tilegx_fixup_pcrel_references.  */
4652static void
4653replace_mov_pcrel_step2 (rtx_insn *insn)
4654{
4655  rtx pattern = PATTERN (insn);
4656  rtx unspec;
4657  rtx addr;
4658  rtx opnds[3];
4659  rtx_insn *new_insns;
4660  rtx got_rtx = tilegx_got_rtx ();
4661
4662  gcc_assert (GET_CODE (pattern) == SET);
4663  opnds[0] = SET_DEST (pattern);
4664
4665  unspec = SET_SRC (pattern);
4666  gcc_assert (GET_CODE (unspec) == UNSPEC);
4667  gcc_assert (XINT (unspec, 1) == UNSPEC_INSN_ADDR_SHL16INSLI);
4668
4669  opnds[1] = XVECEXP (unspec, 0, 0);
4670
4671  addr = XVECEXP (unspec, 0, 1);
4672  gcc_assert (GET_CODE (addr) == CONST);
4673
4674  unspec = XEXP (addr, 0);
4675  gcc_assert (GET_CODE (unspec) == UNSPEC);
4676  gcc_assert (XINT (unspec, 1) == UNSPEC_HW0_PCREL);
4677  opnds[2] = XVECEXP (unspec, 0, 0);
4678
4679  /* We only need to replace SYMBOL_REFs, not LABEL_REFs.  */
4680  if (GET_CODE (opnds[2]) != SYMBOL_REF)
4681    return;
4682
4683  start_sequence ();
4684
4685  if (flag_pic == 1)
4686    {
4687      if (TARGET_32BIT)
4688	emit_insn (gen_add_got16_32bit (opnds[0], got_rtx, opnds[2]));
4689      else
4690	emit_insn (gen_add_got16 (opnds[0], got_rtx, opnds[2]));
4691    }
4692  else
4693    {
4694      if (TARGET_32BIT)
4695	emit_insn (gen_mov_got32_step2_32bit
4696		   (opnds[0], opnds[1], opnds[2]));
4697      else
4698	emit_insn (gen_mov_got32_step2 (opnds[0], opnds[1], opnds[2]));
4699    }
4700
4701  new_insns = get_insns ();
4702  end_sequence ();
4703
4704  replace_insns (insn, new_insns);
4705}
4706
4707
4708/* Do the third replacement step in tilegx_fixup_pcrel_references.  */
4709static void
4710replace_mov_pcrel_step3 (rtx_insn *insn)
4711{
4712  rtx pattern = PATTERN (insn);
4713  rtx unspec;
4714  rtx opnds[4];
4715  rtx_insn *new_insns;
4716  rtx got_rtx = tilegx_got_rtx ();
4717  rtx text_label_rtx = tilegx_text_label_rtx ();
4718
4719  gcc_assert (GET_CODE (pattern) == SET);
4720  opnds[0] = SET_DEST (pattern);
4721
4722  unspec = SET_SRC (pattern);
4723  gcc_assert (GET_CODE (unspec) == UNSPEC);
4724  gcc_assert (XINT (unspec, 1) == UNSPEC_MOV_PCREL_STEP3);
4725
4726  opnds[1] = got_rtx;
4727
4728  if (XVECEXP (unspec, 0, 0) == text_label_rtx)
4729    opnds[2] = XVECEXP (unspec, 0, 1);
4730  else
4731    {
4732      gcc_assert (XVECEXP (unspec, 0, 1) == text_label_rtx);
4733      opnds[2] = XVECEXP (unspec, 0, 0);
4734    }
4735
4736  opnds[3] = XVECEXP (unspec, 0, 2);
4737
4738  /* We only need to replace SYMBOL_REFs, not LABEL_REFs.  */
4739  if (GET_CODE (opnds[3]) != SYMBOL_REF)
4740    return;
4741
4742  start_sequence ();
4743
4744  if (flag_pic == 1)
4745    {
4746      emit_move_insn (opnds[0], gen_const_mem (Pmode, opnds[2]));
4747    }
4748  else
4749    {
4750      emit_move_insn (opnds[0], gen_rtx_PLUS (Pmode, opnds[1], opnds[2]));
4751      emit_move_insn (opnds[0], gen_const_mem (Pmode, opnds[0]));
4752    }
4753
4754  new_insns = get_insns ();
4755  end_sequence ();
4756
4757  replace_insns (insn, new_insns);
4758}
4759
4760
4761/* We generate PC relative SYMBOL_REFs as an optimization, to avoid
4762   going through the GOT when the symbol is local to the compilation
4763   unit.  But such a symbol requires that the common text_label that
4764   we generate at the beginning of the function be in the same section
4765   as the reference to the SYMBOL_REF.  This may not be true if we
4766   generate hot/cold sections.  This function looks for such cases and
4767   replaces such references with the longer sequence going through the
4768   GOT.
4769
4770   We expect following instruction sequence:
4771   moveli      tmp1, hw1_last(x-.L_PICLNK)          [1]
4772   shl16insli  tmp2, tmp1, hw0(x-.L_PICLNK)         [2]
4773   add<x>      tmp3, txt_label_reg, tmp2            [3]
4774
4775   If we're compiling -fpic, we replace with the following sequence
4776   (the numbers in brackets match the instructions they're replacing
4777   above).
4778
4779   add<x>li    tmp2, got_reg, hw0_last_got(x)       [2]
4780   ld<4>       tmp3, tmp2                           [3]
4781
4782   If we're compiling -fPIC, we replace the first instruction with:
4783
4784   moveli      tmp1, hw1_last_got(x)                [1]
4785   shl16insli  tmp2, tmp1, hw0_got(x)               [2]
4786   add<x>      tmp3, got_reg, tmp2                  [3]
4787   ld<4>       tmp3, tmp3                           [3]
4788
4789   Note that we're careful to disturb the instruction sequence as
4790   little as possible, since it's very late in the compilation
4791   process.  */
4792static void
4793tilegx_fixup_pcrel_references (void)
4794{
4795  rtx_insn *insn, *next_insn;
4796  bool same_section_as_entry = true;
4797
4798  for (insn = get_insns (); insn; insn = next_insn)
4799    {
4800      next_insn = NEXT_INSN (insn);
4801
4802      if (NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_SWITCH_TEXT_SECTIONS)
4803	{
4804	  same_section_as_entry = !same_section_as_entry;
4805	  continue;
4806	}
4807
4808      if (same_section_as_entry)
4809	continue;
4810
4811      if (!(INSN_P (insn)
4812	    && GET_CODE (PATTERN (insn)) != USE
4813	    && GET_CODE (PATTERN (insn)) != CLOBBER))
4814	continue;
4815
4816      if (TARGET_32BIT)
4817	{
4818	  if (match_pcrel_step1 (insn))
4819	    replace_mov_pcrel_step1 (insn);
4820	  else if (match_pcrel_step2 (insn))
4821	    replace_mov_pcrel_step2 (insn);
4822	  else if (recog_memoized (insn) == CODE_FOR_mov_pcrel_step3_32bit)
4823	    replace_mov_pcrel_step3 (insn);
4824	}
4825      else
4826	{
4827	  if (match_pcrel_step1 (insn))
4828	    replace_mov_pcrel_step1 (insn);
4829	  else if (match_pcrel_step2 (insn))
4830	    replace_mov_pcrel_step2 (insn);
4831	  else if (recog_memoized (insn) == CODE_FOR_mov_pcrel_step3)
4832	    replace_mov_pcrel_step3 (insn);
4833	}
4834    }
4835}
4836
4837
4838/* Ensure that no var tracking notes are emitted in the middle of a
4839   three-instruction bundle.  */
4840static void
4841reorder_var_tracking_notes (void)
4842{
4843  basic_block bb;
4844  FOR_EACH_BB_FN (bb, cfun)
4845  {
4846    rtx_insn *insn, *next;
4847    rtx_insn *queue = NULL;
4848    bool in_bundle = false;
4849
4850    for (insn = BB_HEAD (bb); insn != BB_END (bb); insn = next)
4851      {
4852	next = NEXT_INSN (insn);
4853
4854	if (INSN_P (insn))
4855	  {
4856	    /* Emit queued up notes at the last instruction of a
4857	       bundle.  */
4858	    if (GET_MODE (insn) == QImode)
4859	      {
4860		while (queue)
4861		  {
4862		    rtx_insn *next_queue = PREV_INSN (queue);
4863		    SET_PREV_INSN (NEXT_INSN (insn)) = queue;
4864		    SET_NEXT_INSN (queue) = NEXT_INSN (insn);
4865		    SET_NEXT_INSN (insn) = queue;
4866		    SET_PREV_INSN (queue) = insn;
4867		    queue = next_queue;
4868		  }
4869		in_bundle = false;
4870	      }
4871	    else if (GET_MODE (insn) == SImode)
4872	      in_bundle = true;
4873	  }
4874	else if (NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_VAR_LOCATION)
4875	  {
4876	    if (in_bundle)
4877	      {
4878		rtx_insn *prev = PREV_INSN (insn);
4879		SET_PREV_INSN (next) = prev;
4880		SET_NEXT_INSN (prev) = next;
4881
4882		SET_PREV_INSN (insn) = queue;
4883		queue = insn;
4884	      }
4885	  }
4886      }
4887  }
4888}
4889
4890
4891/* Perform machine dependent operations on the rtl chain INSNS.  */
4892static void
4893tilegx_reorg (void)
4894{
4895  /* We are freeing block_for_insn in the toplev to keep compatibility
4896     with old MDEP_REORGS that are not CFG based.  Recompute it
4897     now.  */
4898  compute_bb_for_insn ();
4899
4900  if (flag_reorder_blocks_and_partition)
4901    {
4902      tilegx_fixup_pcrel_references ();
4903    }
4904
4905  if (flag_schedule_insns_after_reload)
4906    {
4907      split_all_insns ();
4908
4909      timevar_push (TV_SCHED2);
4910      schedule_insns ();
4911      timevar_pop (TV_SCHED2);
4912
4913      /* Examine the schedule to group into bundles.  */
4914      tilegx_gen_bundles ();
4915    }
4916
4917  df_analyze ();
4918
4919  if (flag_var_tracking)
4920    {
4921      timevar_push (TV_VAR_TRACKING);
4922      variable_tracking_main ();
4923      reorder_var_tracking_notes ();
4924      timevar_pop (TV_VAR_TRACKING);
4925    }
4926
4927  df_finish_pass (false);
4928}
4929
4930
4931
4932/* Assembly  */
4933
4934/* Select a format to encode pointers in exception handling data.
4935   CODE is 0 for data, 1 for code labels, 2 for function pointers.
4936   GLOBAL is true if the symbol may be affected by dynamic
4937   relocations.  */
4938int
4939tilegx_asm_preferred_eh_data_format (int code ATTRIBUTE_UNUSED, int global)
4940{
4941  int type = TARGET_32BIT ? DW_EH_PE_sdata4 : DW_EH_PE_sdata8;
4942  return (global ? DW_EH_PE_indirect : 0) | DW_EH_PE_pcrel | type;
4943}
4944
4945
4946/* Implement TARGET_ASM_OUTPUT_MI_THUNK.  */
4947static void
4948tilegx_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
4949			HOST_WIDE_INT delta, HOST_WIDE_INT vcall_offset,
4950			tree function)
4951{
4952  rtx this_rtx, funexp, addend;
4953  rtx_insn *insn;
4954
4955  /* Pretend to be a post-reload pass while generating rtl.  */
4956  reload_completed = 1;
4957
4958  /* Mark the end of the (empty) prologue.  */
4959  emit_note (NOTE_INSN_PROLOGUE_END);
4960
4961  /* Find the "this" pointer.  If the function returns a structure,
4962     the structure return pointer is in $1.  */
4963  if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function))
4964    this_rtx = gen_rtx_REG (Pmode, 1);
4965  else
4966    this_rtx = gen_rtx_REG (Pmode, 0);
4967
4968  /* Add DELTA to THIS_RTX.  */
4969  if (!(delta >= -32868 && delta <= 32767))
4970    {
4971      addend = gen_rtx_REG (Pmode, 29);
4972      emit_move_insn (addend, GEN_INT (delta));
4973    }
4974  else
4975    addend = GEN_INT (delta);
4976
4977  if (TARGET_32BIT)
4978    emit_insn (gen_addsi3 (this_rtx, this_rtx, addend));
4979  else
4980    emit_insn (gen_adddi3 (this_rtx, this_rtx, addend));
4981
4982  /* If needed, add *(*THIS_RTX + VCALL_OFFSET) to THIS_RTX.  */
4983  if (vcall_offset)
4984    {
4985      rtx tmp;
4986
4987      tmp = gen_rtx_REG (Pmode, 29);
4988      emit_move_insn (tmp, gen_rtx_MEM (Pmode, this_rtx));
4989
4990      if (!(vcall_offset >= -32868 && vcall_offset <= 32767))
4991	{
4992	  addend = gen_rtx_REG (Pmode, 28);
4993	  emit_move_insn (addend, GEN_INT (vcall_offset));
4994	}
4995      else
4996	addend = GEN_INT (vcall_offset);
4997
4998      if (TARGET_32BIT)
4999	emit_insn (gen_addsi3 (tmp, tmp, addend));
5000      else
5001	emit_insn (gen_adddi3 (tmp, tmp, addend));
5002
5003      emit_move_insn (tmp, gen_rtx_MEM (Pmode, tmp));
5004
5005      if (TARGET_32BIT)
5006	emit_insn (gen_addsi3 (this_rtx, this_rtx, tmp));
5007      else
5008	emit_insn (gen_adddi3 (this_rtx, this_rtx, tmp));
5009    }
5010
5011  /* Generate a tail call to the target function.  */
5012  if (!TREE_USED (function))
5013    {
5014      assemble_external (function);
5015      TREE_USED (function) = 1;
5016    }
5017  funexp = XEXP (DECL_RTL (function), 0);
5018  funexp = gen_rtx_MEM (FUNCTION_MODE, funexp);
5019  insn = emit_call_insn (gen_sibcall (funexp, const0_rtx));
5020  SIBLING_CALL_P (insn) = 1;
5021
5022  /* Run just enough of rest_of_compilation to get the insns emitted.
5023     There's not really enough bulk here to make other passes such as
5024     instruction scheduling worth while.  Note that use_thunk calls
5025     assemble_start_function and assemble_end_function.
5026
5027     We don't currently bundle, but the instruciton sequence is all
5028     serial except for the tail call, so we're only wasting one cycle.
5029   */
5030  insn = get_insns ();
5031  shorten_branches (insn);
5032  final_start_function (insn, file, 1);
5033  final (insn, file, 1);
5034  final_end_function ();
5035
5036  /* Stop pretending to be a post-reload pass.  */
5037  reload_completed = 0;
5038}
5039
5040
5041/* Implement TARGET_ASM_TRAMPOLINE_TEMPLATE.  */
5042static void
5043tilegx_asm_trampoline_template (FILE *file)
5044{
5045  int ptr_mode_size = GET_MODE_SIZE (ptr_mode);
5046  if (TARGET_32BIT)
5047    {
5048      fprintf (file, "\tlnk      r10\n");
5049      fprintf (file, "\taddxi    r10, r10, 32\n");
5050      fprintf (file, "\tld4s_add r11, r10, %d\n", ptr_mode_size);
5051      fprintf (file, "\tld4s     r10, r10\n");
5052      fprintf (file, "\tjr       r11\n");
5053      fprintf (file, "\t.word 0 # <function address>\n");
5054      fprintf (file, "\t.word 0 # <static chain value>\n");
5055    }
5056  else
5057    {
5058      fprintf (file, "\tlnk      r10\n");
5059      fprintf (file, "\taddi     r10, r10, 32\n");
5060      fprintf (file, "\tld_add   r11, r10, %d\n", ptr_mode_size);
5061      fprintf (file, "\tld       r10, r10\n");
5062      fprintf (file, "\tjr       r11\n");
5063      fprintf (file, "\t.quad 0 # <function address>\n");
5064      fprintf (file, "\t.quad 0 # <static chain value>\n");
5065    }
5066}
5067
5068
5069/* Implement TARGET_TRAMPOLINE_INIT.  */
5070static void
5071tilegx_trampoline_init (rtx m_tramp, tree fndecl, rtx static_chain)
5072{
5073  rtx fnaddr, chaddr;
5074  rtx mem;
5075  rtx begin_addr, end_addr;
5076  int ptr_mode_size = GET_MODE_SIZE (ptr_mode);
5077
5078  fnaddr = copy_to_reg (XEXP (DECL_RTL (fndecl), 0));
5079  chaddr = copy_to_reg (static_chain);
5080
5081  emit_block_move (m_tramp, assemble_trampoline_template (),
5082		   GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NORMAL);
5083
5084  mem = adjust_address (m_tramp, ptr_mode,
5085			TRAMPOLINE_SIZE - 2 * ptr_mode_size);
5086  emit_move_insn (mem, fnaddr);
5087  mem = adjust_address (m_tramp, ptr_mode,
5088			TRAMPOLINE_SIZE - ptr_mode_size);
5089  emit_move_insn (mem, chaddr);
5090
5091  /* Get pointers to the beginning and end of the code block.  */
5092  begin_addr = force_reg (Pmode, XEXP (m_tramp, 0));
5093  end_addr = force_reg (Pmode, plus_constant (Pmode, XEXP (m_tramp, 0),
5094					      TRAMPOLINE_SIZE));
5095
5096  emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__clear_cache"),
5097		     LCT_NORMAL, VOIDmode, 2, begin_addr, Pmode,
5098		     end_addr, Pmode);
5099}
5100
5101
5102/* Implement TARGET_PRINT_OPERAND.  */
5103static void
5104tilegx_print_operand (FILE *file, rtx x, int code)
5105{
5106  switch (code)
5107    {
5108    case 'c':
5109      /* Print the compare operator opcode for conditional moves.  */
5110      switch (GET_CODE (x))
5111	{
5112	case EQ:
5113	  fputs ("z", file);
5114	  break;
5115	case NE:
5116	  fputs ("nz", file);
5117	  break;
5118	default:
5119	  output_operand_lossage ("invalid %%c operand");
5120	}
5121      return;
5122
5123    case 'C':
5124      /* Print the compare operator opcode for conditional moves.  */
5125      switch (GET_CODE (x))
5126	{
5127	case EQ:
5128	  fputs ("nz", file);
5129	  break;
5130	case NE:
5131	  fputs ("z", file);
5132	  break;
5133	default:
5134	  output_operand_lossage ("invalid %%C operand");
5135	}
5136      return;
5137
5138    case 'd':
5139      {
5140	/* Print the compare operator opcode for conditional moves.  */
5141	switch (GET_CODE (x))
5142	  {
5143	  case EQ:
5144	    fputs ("eq", file);
5145	    break;
5146	  case NE:
5147	    fputs ("ne", file);
5148	    break;
5149	  default:
5150	    output_operand_lossage ("invalid %%d operand");
5151	  }
5152	return;
5153      }
5154
5155    case 'D':
5156      {
5157	/* Print the compare operator opcode for conditional moves.  */
5158	switch (GET_CODE (x))
5159	  {
5160	  case EQ:
5161	    fputs ("ne", file);
5162	    break;
5163	  case NE:
5164	    fputs ("eq", file);
5165	    break;
5166	  default:
5167	    output_operand_lossage ("invalid %%D operand");
5168	  }
5169	return;
5170      }
5171
5172    case 'H':
5173      {
5174      if (GET_CODE (x) == CONST
5175	  && GET_CODE (XEXP (x, 0)) == UNSPEC)
5176	{
5177	  rtx addr = XVECEXP (XEXP (x, 0), 0, 0);
5178	  int unspec = XINT (XEXP (x, 0), 1);
5179	  const char *opstr = NULL;
5180	  switch (unspec)
5181	    {
5182	    case UNSPEC_HW0:
5183	    case UNSPEC_HW0_PCREL:
5184	      opstr = "hw0";
5185	      break;
5186	    case UNSPEC_HW1:
5187	    case UNSPEC_HW1_PCREL:
5188	      opstr = "hw1";
5189	      break;
5190	    case UNSPEC_HW2:
5191	      opstr = "hw2";
5192	      break;
5193	    case UNSPEC_HW3:
5194	      opstr = "hw3";
5195	      break;
5196	    case UNSPEC_HW0_LAST:
5197	      opstr = "hw0_last";
5198	      break;
5199	    case UNSPEC_HW1_LAST:
5200	    case UNSPEC_HW1_LAST_PCREL:
5201	      opstr = "hw1_last";
5202	      break;
5203	    case UNSPEC_HW2_LAST:
5204	    case UNSPEC_HW2_LAST_PCREL:
5205	      opstr = "hw2_last";
5206	      break;
5207	    case UNSPEC_HW0_GOT:
5208	      opstr = "hw0_got";
5209	      break;
5210	    case UNSPEC_HW0_LAST_GOT:
5211	      opstr = "hw0_last_got";
5212	      break;
5213	    case UNSPEC_HW1_LAST_GOT:
5214	      opstr = "hw1_last_got";
5215	      break;
5216	    case UNSPEC_HW0_TLS_GD:
5217	      opstr = "hw0_tls_gd";
5218	      break;
5219	    case UNSPEC_HW1_LAST_TLS_GD:
5220	      opstr = "hw1_last_tls_gd";
5221	      break;
5222	    case UNSPEC_HW0_TLS_IE:
5223	      opstr = "hw0_tls_ie";
5224	      break;
5225	    case UNSPEC_HW1_LAST_TLS_IE:
5226	      opstr = "hw1_last_tls_ie";
5227	      break;
5228	    case UNSPEC_HW0_TLS_LE:
5229	      opstr = "hw0_tls_le";
5230	      break;
5231	    case UNSPEC_HW1_LAST_TLS_LE:
5232	      opstr = "hw1_last_tls_le";
5233	      break;
5234	    case UNSPEC_HW0_PLT_PCREL:
5235	      opstr = "hw0_plt";
5236	      break;
5237	    case UNSPEC_HW1_PLT_PCREL:
5238	      opstr = "hw1_plt";
5239	      break;
5240	    case UNSPEC_HW1_LAST_PLT_PCREL:
5241	      opstr = "hw1_last_plt";
5242	      break;
5243	    case UNSPEC_HW2_LAST_PLT_PCREL:
5244	      opstr = "hw2_last_plt";
5245	      break;
5246	    default:
5247	      output_operand_lossage ("invalid %%H specifier");
5248	    }
5249
5250	  fputs (opstr, file);
5251	  fputc ('(', file);
5252	  output_addr_const (file, addr);
5253
5254	  if (unspec == UNSPEC_HW0_PCREL
5255	      || unspec == UNSPEC_HW1_PCREL
5256	      || unspec == UNSPEC_HW1_LAST_PCREL
5257	      || unspec == UNSPEC_HW2_LAST_PCREL
5258	      || unspec == UNSPEC_HW0_PLT_PCREL
5259	      || unspec == UNSPEC_HW1_PLT_PCREL
5260	      || unspec == UNSPEC_HW1_LAST_PLT_PCREL
5261	      || unspec == UNSPEC_HW2_LAST_PLT_PCREL)
5262	    {
5263	      rtx addr2 = XVECEXP (XEXP (x, 0), 0, 1);
5264	      fputs (" - " , file);
5265	      output_addr_const (file, addr2);
5266	    }
5267
5268	  fputc (')', file);
5269	  return;
5270	}
5271      else if (symbolic_operand (x, VOIDmode))
5272	{
5273	  output_addr_const (file, x);
5274	  return;
5275	}
5276      }
5277      /* FALLTHRU */
5278
5279    case 'h':
5280      {
5281	/* Print the low 16 bits of a constant.  */
5282	HOST_WIDE_INT i;
5283	if (CONST_INT_P (x))
5284	  i = INTVAL (x);
5285	else if (GET_CODE (x) == CONST_DOUBLE)
5286	  i = CONST_DOUBLE_LOW (x);
5287	else
5288	  {
5289	    output_operand_lossage ("invalid %%h operand");
5290	    return;
5291	  }
5292	i = trunc_int_for_mode (i, HImode);
5293	fprintf (file, HOST_WIDE_INT_PRINT_DEC, i);
5294	return;
5295      }
5296
5297    case 'I':
5298      /* Print an auto-inc memory operand.  */
5299      if (!MEM_P (x))
5300	{
5301	  output_operand_lossage ("invalid %%I operand");
5302	  return;
5303	}
5304
5305      output_memory_reference_mode = GET_MODE (x);
5306      output_memory_autoinc_first = true;
5307      output_address (XEXP (x, 0));
5308      output_memory_reference_mode = VOIDmode;
5309      return;
5310
5311    case 'i':
5312      /* Print an auto-inc memory operand.  */
5313      if (!MEM_P (x))
5314	{
5315	  output_operand_lossage ("invalid %%i operand");
5316	  return;
5317	}
5318
5319      output_memory_reference_mode = GET_MODE (x);
5320      output_memory_autoinc_first = false;
5321      output_address (XEXP (x, 0));
5322      output_memory_reference_mode = VOIDmode;
5323      return;
5324
5325    case 'j':
5326      {
5327	/* Print the low 8 bits of a constant.  */
5328	HOST_WIDE_INT i;
5329	if (CONST_INT_P (x))
5330	  i = INTVAL (x);
5331	else if (GET_CODE (x) == CONST_DOUBLE)
5332	  i = CONST_DOUBLE_LOW (x);
5333	else if (GET_CODE (x) == CONST_VECTOR
5334		 && CONST_INT_P (CONST_VECTOR_ELT (x, 0)))
5335	  i = INTVAL (CONST_VECTOR_ELT (x, 0));
5336	else
5337	  {
5338	    output_operand_lossage ("invalid %%j operand");
5339	    return;
5340	  }
5341	i = trunc_int_for_mode (i, QImode);
5342	fprintf (file, HOST_WIDE_INT_PRINT_DEC, i);
5343	return;
5344      }
5345
5346    case 'P':
5347      {
5348	/* Print a constant plus one.  */
5349	if (!CONST_INT_P (x))
5350	  {
5351	    output_operand_lossage ("invalid %%P operand");
5352	    return;
5353	  }
5354	fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x) + 1);
5355	return;
5356      }
5357
5358    case 'm':
5359    case 'M':
5360      {
5361	/* Print a bfextu-style bit range.  */
5362	int first_bit, last_bit;
5363	HOST_WIDE_INT flip = (code == 'm') ? ~0 : 0;
5364
5365	if (!CONST_INT_P (x)
5366	    || !tilegx_bitfield_operand_p (INTVAL (x) ^ flip,
5367					   &first_bit, &last_bit))
5368	  {
5369	    output_operand_lossage ("invalid %%%c operand", code);
5370	    return;
5371	  }
5372
5373	fprintf (file, "%d, %d", first_bit, last_bit);
5374	return;
5375      }
5376
5377    case 'N':
5378      {
5379	const char *reg = NULL;
5380
5381	/* Print a network register.  */
5382	if (!CONST_INT_P (x))
5383	  {
5384	    output_operand_lossage ("invalid %%N operand");
5385	    return;
5386	  }
5387
5388	switch (INTVAL (x))
5389	  {
5390	  case TILEGX_NETREG_IDN0: reg = "idn0"; break;
5391	  case TILEGX_NETREG_IDN1: reg = "idn1"; break;
5392	  case TILEGX_NETREG_UDN0: reg = "udn0"; break;
5393	  case TILEGX_NETREG_UDN1: reg = "udn1"; break;
5394	  case TILEGX_NETREG_UDN2: reg = "udn2"; break;
5395	  case TILEGX_NETREG_UDN3: reg = "udn3"; break;
5396	  default:
5397	    gcc_unreachable ();
5398	  }
5399
5400	fprintf (file, reg);
5401	return;
5402      }
5403
5404    case 'p':
5405      if (GET_CODE (x) == SYMBOL_REF)
5406	{
5407	  if (flag_pic && !SYMBOL_REF_LOCAL_P (x))
5408	    fprintf (file, "plt(");
5409	  output_addr_const (file, x);
5410	  if (flag_pic && !SYMBOL_REF_LOCAL_P (x))
5411	    fprintf (file, ")");
5412	}
5413      else
5414	output_addr_const (file, x);
5415      return;
5416
5417    case 'r':
5418      /* In this case we need a register.  Use 'zero' if the operand
5419	 is const0_rtx.  */
5420      if (x == const0_rtx
5421	  || (GET_MODE (x) != VOIDmode && x == CONST0_RTX (GET_MODE (x))))
5422	{
5423	  fputs ("zero", file);
5424	  return;
5425	}
5426      else if (!REG_P (x))
5427	{
5428	  output_operand_lossage ("invalid operand for 'r' specifier");
5429	  return;
5430	}
5431      /* FALLTHRU */
5432
5433    case 0:
5434      if (REG_P (x))
5435	{
5436	  fprintf (file, "%s", reg_names[REGNO (x)]);
5437	  return;
5438	}
5439      else if (MEM_P (x))
5440	{
5441	  output_memory_reference_mode = VOIDmode;
5442	  output_address (XEXP (x, 0));
5443	  return;
5444	}
5445      else
5446	{
5447	  output_addr_const (file, x);
5448	  return;
5449	}
5450    }
5451
5452  debug_rtx (x);
5453  output_operand_lossage ("unable to print out operand yet; code == %d (%c)",
5454			  code, code);
5455}
5456
5457
5458/* Implement TARGET_PRINT_OPERAND_ADDRESS.  */
5459static void
5460tilegx_print_operand_address (FILE *file, rtx addr)
5461{
5462  if (GET_CODE (addr) == POST_DEC
5463      || GET_CODE (addr) == POST_INC)
5464    {
5465      int offset = GET_MODE_SIZE (output_memory_reference_mode);
5466
5467      gcc_assert (output_memory_reference_mode != VOIDmode);
5468
5469      if (output_memory_autoinc_first)
5470	fprintf (file, "%s", reg_names[REGNO (XEXP (addr, 0))]);
5471      else
5472	fprintf (file, "%d",
5473		 GET_CODE (addr) == POST_DEC ? -offset : offset);
5474    }
5475  else if (GET_CODE (addr) == POST_MODIFY)
5476    {
5477      gcc_assert (output_memory_reference_mode != VOIDmode);
5478
5479      gcc_assert (GET_CODE (XEXP (addr, 1)) == PLUS);
5480
5481      if (output_memory_autoinc_first)
5482	fprintf (file, "%s", reg_names[REGNO (XEXP (addr, 0))]);
5483      else
5484	fprintf (file, HOST_WIDE_INT_PRINT_DEC,
5485		 INTVAL (XEXP (XEXP (addr, 1), 1)));
5486    }
5487  else
5488    tilegx_print_operand (file, addr, 'r');
5489}
5490
5491
5492/* Machine mode of current insn, for determining curly brace
5493   placement.  */
5494static machine_mode insn_mode;
5495
5496
5497/* Implement FINAL_PRESCAN_INSN.  This is used to emit bundles.  */
5498void
5499tilegx_final_prescan_insn (rtx_insn *insn)
5500{
5501  /* Record this for tilegx_asm_output_opcode to examine.  */
5502  insn_mode = GET_MODE (insn);
5503}
5504
5505
5506/* While emitting asm, are we currently inside '{' for a bundle?  */
5507static bool tilegx_in_bundle = false;
5508
5509/* Implement ASM_OUTPUT_OPCODE.  Prepend/append curly braces as
5510   appropriate given the bundling information recorded by
5511   tilegx_gen_bundles.  */
5512const char *
5513tilegx_asm_output_opcode (FILE *stream, const char *code)
5514{
5515  bool pseudo = !strcmp (code, "pseudo");
5516
5517  if (!tilegx_in_bundle && insn_mode == SImode)
5518    {
5519      /* Start a new bundle.  */
5520      fprintf (stream, "{\n\t");
5521      tilegx_in_bundle = true;
5522    }
5523
5524  if (tilegx_in_bundle && insn_mode == QImode)
5525    {
5526      /* Close an existing bundle.  */
5527      static char buf[100];
5528
5529      gcc_assert (strlen (code) + 3 + 1 < sizeof (buf));
5530
5531      strcpy (buf, pseudo ? "" : code);
5532      strcat (buf, "\n\t}");
5533      tilegx_in_bundle = false;
5534
5535      return buf;
5536    }
5537  else
5538    {
5539      return pseudo ? "" : code;
5540    }
5541}
5542
5543
5544/* Output assembler code to FILE to increment profiler label # LABELNO
5545   for profiling a function entry.  */
5546void
5547tilegx_function_profiler (FILE *file, int labelno ATTRIBUTE_UNUSED)
5548{
5549  if (tilegx_in_bundle)
5550    {
5551      fprintf (file, "\t}\n");
5552    }
5553
5554  if (flag_pic)
5555    {
5556      fprintf (file,
5557	       "\t{\n"
5558	       "\tmove\tr10, lr\n"
5559	       "\tjal\tplt(%s)\n"
5560	       "\t}\n", MCOUNT_NAME);
5561    }
5562  else
5563    {
5564      fprintf (file,
5565	       "\t{\n"
5566	       "\tmove\tr10, lr\n"
5567	       "\tjal\t%s\n"
5568	       "\t}\n", MCOUNT_NAME);
5569    }
5570
5571  tilegx_in_bundle = false;
5572}
5573
5574
5575/* Implement TARGET_ASM_FILE_END.  */
5576static void
5577tilegx_file_end (void)
5578{
5579  if (NEED_INDICATE_EXEC_STACK)
5580    file_end_indicate_exec_stack ();
5581}
5582
5583
5584
5585#undef  TARGET_HAVE_TLS
5586#define TARGET_HAVE_TLS HAVE_AS_TLS
5587
5588#undef  TARGET_OPTION_OVERRIDE
5589#define TARGET_OPTION_OVERRIDE tilegx_option_override
5590
5591#undef  TARGET_SCALAR_MODE_SUPPORTED_P
5592#define TARGET_SCALAR_MODE_SUPPORTED_P tilegx_scalar_mode_supported_p
5593
5594#undef  TARGET_VECTOR_MODE_SUPPORTED_P
5595#define TARGET_VECTOR_MODE_SUPPORTED_P tilegx_vector_mode_supported_p
5596
5597#undef  TARGET_CANNOT_FORCE_CONST_MEM
5598#define TARGET_CANNOT_FORCE_CONST_MEM tilegx_cannot_force_const_mem
5599
5600#undef  TARGET_FUNCTION_OK_FOR_SIBCALL
5601#define TARGET_FUNCTION_OK_FOR_SIBCALL tilegx_function_ok_for_sibcall
5602
5603#undef  TARGET_PASS_BY_REFERENCE
5604#define TARGET_PASS_BY_REFERENCE tilegx_pass_by_reference
5605
5606#undef  TARGET_RETURN_IN_MSB
5607#define TARGET_RETURN_IN_MSB tilegx_return_in_msb
5608
5609#undef  TARGET_RETURN_IN_MEMORY
5610#define TARGET_RETURN_IN_MEMORY tilegx_return_in_memory
5611
5612#undef  TARGET_MODE_REP_EXTENDED
5613#define TARGET_MODE_REP_EXTENDED tilegx_mode_rep_extended
5614
5615#undef  TARGET_FUNCTION_ARG_BOUNDARY
5616#define TARGET_FUNCTION_ARG_BOUNDARY tilegx_function_arg_boundary
5617
5618#undef  TARGET_FUNCTION_ARG
5619#define TARGET_FUNCTION_ARG tilegx_function_arg
5620
5621#undef  TARGET_FUNCTION_ARG_ADVANCE
5622#define TARGET_FUNCTION_ARG_ADVANCE tilegx_function_arg_advance
5623
5624#undef  TARGET_FUNCTION_VALUE
5625#define TARGET_FUNCTION_VALUE tilegx_function_value
5626
5627#undef  TARGET_LIBCALL_VALUE
5628#define TARGET_LIBCALL_VALUE tilegx_libcall_value
5629
5630#undef  TARGET_FUNCTION_VALUE_REGNO_P
5631#define TARGET_FUNCTION_VALUE_REGNO_P tilegx_function_value_regno_p
5632
5633#undef  TARGET_PROMOTE_FUNCTION_MODE
5634#define TARGET_PROMOTE_FUNCTION_MODE default_promote_function_mode_always_promote
5635
5636#undef  TARGET_PROMOTE_PROTOTYPES
5637#define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_false
5638
5639#undef  TARGET_BUILD_BUILTIN_VA_LIST
5640#define TARGET_BUILD_BUILTIN_VA_LIST tilegx_build_builtin_va_list
5641
5642#undef  TARGET_EXPAND_BUILTIN_VA_START
5643#define TARGET_EXPAND_BUILTIN_VA_START tilegx_va_start
5644
5645#undef  TARGET_SETUP_INCOMING_VARARGS
5646#define TARGET_SETUP_INCOMING_VARARGS tilegx_setup_incoming_varargs
5647
5648#undef  TARGET_GIMPLIFY_VA_ARG_EXPR
5649#define TARGET_GIMPLIFY_VA_ARG_EXPR tilegx_gimplify_va_arg_expr
5650
5651#undef  TARGET_RTX_COSTS
5652#define TARGET_RTX_COSTS tilegx_rtx_costs
5653
5654#undef  TARGET_EXPAND_TO_RTL_HOOK
5655#define TARGET_EXPAND_TO_RTL_HOOK tilegx_expand_to_rtl_hook
5656
5657#undef  TARGET_SHIFT_TRUNCATION_MASK
5658#define TARGET_SHIFT_TRUNCATION_MASK tilegx_shift_truncation_mask
5659
5660#undef  TARGET_INIT_LIBFUNCS
5661#define TARGET_INIT_LIBFUNCS tilegx_init_libfuncs
5662
5663/* Limit to what we can reach in one addli.  */
5664#undef  TARGET_MIN_ANCHOR_OFFSET
5665#define TARGET_MIN_ANCHOR_OFFSET -32768
5666#undef  TARGET_MAX_ANCHOR_OFFSET
5667#define TARGET_MAX_ANCHOR_OFFSET 32767
5668
5669#undef  TARGET_LEGITIMATE_CONSTANT_P
5670#define TARGET_LEGITIMATE_CONSTANT_P tilegx_legitimate_constant_p
5671
5672#undef  TARGET_LEGITIMATE_ADDRESS_P
5673#define TARGET_LEGITIMATE_ADDRESS_P tilegx_legitimate_address_p
5674
5675#undef  TARGET_LEGITIMIZE_ADDRESS
5676#define TARGET_LEGITIMIZE_ADDRESS tilegx_legitimize_address
5677
5678#undef  TARGET_DELEGITIMIZE_ADDRESS
5679#define TARGET_DELEGITIMIZE_ADDRESS tilegx_delegitimize_address
5680
5681#undef  TARGET_INIT_BUILTINS
5682#define TARGET_INIT_BUILTINS  tilegx_init_builtins
5683
5684#undef  TARGET_BUILTIN_DECL
5685#define TARGET_BUILTIN_DECL tilegx_builtin_decl
5686
5687#undef  TARGET_EXPAND_BUILTIN
5688#define TARGET_EXPAND_BUILTIN tilegx_expand_builtin
5689
5690#undef  TARGET_CONDITIONAL_REGISTER_USAGE
5691#define TARGET_CONDITIONAL_REGISTER_USAGE tilegx_conditional_register_usage
5692
5693#undef  TARGET_FRAME_POINTER_REQUIRED
5694#define TARGET_FRAME_POINTER_REQUIRED tilegx_frame_pointer_required
5695
5696#undef  TARGET_DELAY_SCHED2
5697#define TARGET_DELAY_SCHED2 true
5698
5699#undef  TARGET_DELAY_VARTRACK
5700#define TARGET_DELAY_VARTRACK true
5701
5702#undef  TARGET_SCHED_ISSUE_RATE
5703#define TARGET_SCHED_ISSUE_RATE tilegx_issue_rate
5704
5705#undef  TARGET_SCHED_ADJUST_COST
5706#define TARGET_SCHED_ADJUST_COST tilegx_sched_adjust_cost
5707
5708#undef  TARGET_MACHINE_DEPENDENT_REORG
5709#define TARGET_MACHINE_DEPENDENT_REORG tilegx_reorg
5710
5711#undef  TARGET_ASM_CAN_OUTPUT_MI_THUNK
5712#define TARGET_ASM_CAN_OUTPUT_MI_THUNK \
5713  hook_bool_const_tree_hwi_hwi_const_tree_true
5714
5715#undef  TARGET_ASM_OUTPUT_MI_THUNK
5716#define TARGET_ASM_OUTPUT_MI_THUNK tilegx_output_mi_thunk
5717
5718#undef  TARGET_ASM_TRAMPOLINE_TEMPLATE
5719#define TARGET_ASM_TRAMPOLINE_TEMPLATE tilegx_asm_trampoline_template
5720
5721#undef  TARGET_TRAMPOLINE_INIT
5722#define TARGET_TRAMPOLINE_INIT tilegx_trampoline_init
5723
5724#undef  TARGET_PRINT_OPERAND
5725#define TARGET_PRINT_OPERAND tilegx_print_operand
5726
5727#undef  TARGET_PRINT_OPERAND_ADDRESS
5728#define TARGET_PRINT_OPERAND_ADDRESS tilegx_print_operand_address
5729
5730#undef  TARGET_ASM_FILE_END
5731#define TARGET_ASM_FILE_END tilegx_file_end
5732
5733#undef  TARGET_ASM_ALIGNED_DI_OP
5734#define TARGET_ASM_ALIGNED_DI_OP "\t.quad\t"
5735
5736#undef  TARGET_CAN_USE_DOLOOP_P
5737#define TARGET_CAN_USE_DOLOOP_P can_use_doloop_if_innermost
5738
5739struct gcc_target targetm = TARGET_INITIALIZER;
5740
5741#include "gt-tilegx.h"
5742